diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-24 20:35:10 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-24 20:35:10 -0500 |
commit | 21fbd5809ad126b949206d78e0a0e07ec872ea11 (patch) | |
tree | a824045df99fc1f0690095a925cceb50207e332b /drivers/media/platform | |
parent | d9978ec5680059d727b39d6c706777c6973587f2 (diff) | |
parent | ed72d37a33fdf43dc47787fe220532cdec9da528 (diff) |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- Some cleanups at V4L2 documentation
- new drivers: ts2020 frontend, ov9650 sensor, s5c73m3 sensor,
sh-mobile veu mem2mem driver, radio-ma901, davinci_vpfe staging
driver
- Lots of missing MAINTAINERS entries added
- several em28xx driver improvements, including its conversion to
videobuf2
- several fixups on drivers to make them to better comply with the API
- DVB core: add support for DVBv5 stats, allowing the implementation of
statistics for new standards like ISDB
- mb86a20s: add statistics to the driver
- lots of new board additions, cleanups, and driver improvements.
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (596 commits)
[media] media: Add 0x3009 USB PID to ttusb2 driver (fixed diff)
[media] rtl28xxu: Add USB IDs for Compro VideoMate U620F
[media] em28xx: add usb id for terratec h5 rev. 3
[media] media: rc: gpio-ir-recv: add support for device tree parsing
[media] mceusb: move check earlier to make smatch happy
[media] radio-si470x doc: add info about v4l2-ctl and sox+alsa
[media] staging: media: Remove unnecessary OOM messages
[media] sh_vou: Use vou_dev instead of vou_file wherever possible
[media] sh_vou: Use video_drvdata()
[media] drivers/media/platform/soc_camera/pxa_camera.c: use devm_ functions
[media] mt9t112: mt9t111 format set up differs from mt9t112
[media] sh-mobile-ceu-camera: fix SHARPNESS control default
Revert "[media] fc0011: Return early, if the frequency is already tuned"
[media] cx18/ivtv: fix regression: remove __init from a non-init function
[media] em28xx: fix analog streaming with USB bulk transfers
[media] stv0900: remove unnecessary null pointer check
[media] fc0011: Return early, if the frequency is already tuned
[media] fc0011: Add some sanity checks and cleanups
[media] fc0011: Fix xin value clamping
Revert "[media] [PATH,1/2] mxl5007 move reset to attach"
...
Diffstat (limited to 'drivers/media/platform')
93 files changed, 3680 insertions, 2171 deletions
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 33241120a58c..05d7b6333461 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig | |||
@@ -92,7 +92,7 @@ config VIDEO_M32R_AR_M64278 | |||
92 | 92 | ||
93 | config VIDEO_OMAP2 | 93 | config VIDEO_OMAP2 |
94 | tristate "OMAP2 Camera Capture Interface driver" | 94 | tristate "OMAP2 Camera Capture Interface driver" |
95 | depends on VIDEO_DEV && ARCH_OMAP2 | 95 | depends on VIDEO_DEV && ARCH_OMAP2 && VIDEO_V4L2_INT_DEVICE |
96 | select VIDEOBUF_DMA_SG | 96 | select VIDEOBUF_DMA_SG |
97 | ---help--- | 97 | ---help--- |
98 | This is a v4l2 driver for the TI OMAP2 camera capture interface | 98 | This is a v4l2 driver for the TI OMAP2 camera capture interface |
@@ -202,6 +202,15 @@ config VIDEO_SAMSUNG_EXYNOS_GSC | |||
202 | help | 202 | help |
203 | This is a v4l2 driver for Samsung EXYNOS5 SoC G-Scaler. | 203 | This is a v4l2 driver for Samsung EXYNOS5 SoC G-Scaler. |
204 | 204 | ||
205 | config VIDEO_SH_VEU | ||
206 | tristate "SuperH VEU mem2mem video processing driver" | ||
207 | depends on VIDEO_DEV && VIDEO_V4L2 | ||
208 | select VIDEOBUF2_DMA_CONTIG | ||
209 | select V4L2_MEM2MEM_DEV | ||
210 | help | ||
211 | Support for the Video Engine Unit (VEU) on SuperH and | ||
212 | SH-Mobile SoCs. | ||
213 | |||
205 | endif # V4L_MEM2MEM_DRIVERS | 214 | endif # V4L_MEM2MEM_DRIVERS |
206 | 215 | ||
207 | menuconfig V4L_TEST_DRIVERS | 216 | menuconfig V4L_TEST_DRIVERS |
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 4817d2802171..42089ba3600f 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile | |||
@@ -25,6 +25,8 @@ obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o | |||
25 | obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o | 25 | obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o |
26 | obj-$(CONFIG_VIDEO_CODA) += coda.o | 26 | obj-$(CONFIG_VIDEO_CODA) += coda.o |
27 | 27 | ||
28 | obj-$(CONFIG_VIDEO_SH_VEU) += sh_veu.o | ||
29 | |||
28 | obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE) += m2m-deinterlace.o | 30 | obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE) += m2m-deinterlace.o |
29 | 31 | ||
30 | obj-$(CONFIG_VIDEO_S3C_CAMIF) += s3c-camif/ | 32 | obj-$(CONFIG_VIDEO_S3C_CAMIF) += s3c-camif/ |
diff --git a/drivers/media/platform/blackfin/Kconfig b/drivers/media/platform/blackfin/Kconfig index ecd5323768b7..cc239972fa2c 100644 --- a/drivers/media/platform/blackfin/Kconfig +++ b/drivers/media/platform/blackfin/Kconfig | |||
@@ -7,4 +7,9 @@ config VIDEO_BLACKFIN_CAPTURE | |||
7 | Choose PPI or EPPI as its interface. | 7 | Choose PPI or EPPI as its interface. |
8 | 8 | ||
9 | To compile this driver as a module, choose M here: the | 9 | To compile this driver as a module, choose M here: the |
10 | module will be called bfin_video_capture. | 10 | module will be called bfin_capture. |
11 | |||
12 | config VIDEO_BLACKFIN_PPI | ||
13 | tristate | ||
14 | depends on VIDEO_BLACKFIN_CAPTURE | ||
15 | default VIDEO_BLACKFIN_CAPTURE | ||
diff --git a/drivers/media/platform/blackfin/Makefile b/drivers/media/platform/blackfin/Makefile index aa3a0a216387..30421bc23080 100644 --- a/drivers/media/platform/blackfin/Makefile +++ b/drivers/media/platform/blackfin/Makefile | |||
@@ -1,2 +1,2 @@ | |||
1 | bfin_video_capture-objs := bfin_capture.o ppi.o | 1 | obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_capture.o |
2 | obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_video_capture.o | 2 | obj-$(CONFIG_VIDEO_BLACKFIN_PPI) += ppi.o |
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index 1aad2a65d2f3..5f209d5810dc 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c | |||
@@ -52,6 +52,7 @@ struct bcap_format { | |||
52 | u32 pixelformat; | 52 | u32 pixelformat; |
53 | enum v4l2_mbus_pixelcode mbus_code; | 53 | enum v4l2_mbus_pixelcode mbus_code; |
54 | int bpp; /* bits per pixel */ | 54 | int bpp; /* bits per pixel */ |
55 | int dlen; /* data length for ppi in bits */ | ||
55 | }; | 56 | }; |
56 | 57 | ||
57 | struct bcap_buffer { | 58 | struct bcap_buffer { |
@@ -76,18 +77,20 @@ struct bcap_device { | |||
76 | unsigned int cur_input; | 77 | unsigned int cur_input; |
77 | /* current selected standard */ | 78 | /* current selected standard */ |
78 | v4l2_std_id std; | 79 | v4l2_std_id std; |
80 | /* current selected dv_timings */ | ||
81 | struct v4l2_dv_timings dv_timings; | ||
79 | /* used to store pixel format */ | 82 | /* used to store pixel format */ |
80 | struct v4l2_pix_format fmt; | 83 | struct v4l2_pix_format fmt; |
81 | /* bits per pixel*/ | 84 | /* bits per pixel*/ |
82 | int bpp; | 85 | int bpp; |
86 | /* data length for ppi in bits */ | ||
87 | int dlen; | ||
83 | /* used to store sensor supported format */ | 88 | /* used to store sensor supported format */ |
84 | struct bcap_format *sensor_formats; | 89 | struct bcap_format *sensor_formats; |
85 | /* number of sensor formats array */ | 90 | /* number of sensor formats array */ |
86 | int num_sensor_formats; | 91 | int num_sensor_formats; |
87 | /* pointing to current video buffer */ | 92 | /* pointing to current video buffer */ |
88 | struct bcap_buffer *cur_frm; | 93 | struct bcap_buffer *cur_frm; |
89 | /* pointing to next video buffer */ | ||
90 | struct bcap_buffer *next_frm; | ||
91 | /* buffer queue used in videobuf2 */ | 94 | /* buffer queue used in videobuf2 */ |
92 | struct vb2_queue buffer_queue; | 95 | struct vb2_queue buffer_queue; |
93 | /* allocator-specific contexts for each plane */ | 96 | /* allocator-specific contexts for each plane */ |
@@ -116,24 +119,35 @@ static const struct bcap_format bcap_formats[] = { | |||
116 | .pixelformat = V4L2_PIX_FMT_UYVY, | 119 | .pixelformat = V4L2_PIX_FMT_UYVY, |
117 | .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, | 120 | .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, |
118 | .bpp = 16, | 121 | .bpp = 16, |
122 | .dlen = 8, | ||
119 | }, | 123 | }, |
120 | { | 124 | { |
121 | .desc = "YCbCr 4:2:2 Interleaved YUYV", | 125 | .desc = "YCbCr 4:2:2 Interleaved YUYV", |
122 | .pixelformat = V4L2_PIX_FMT_YUYV, | 126 | .pixelformat = V4L2_PIX_FMT_YUYV, |
123 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | 127 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, |
124 | .bpp = 16, | 128 | .bpp = 16, |
129 | .dlen = 8, | ||
130 | }, | ||
131 | { | ||
132 | .desc = "YCbCr 4:2:2 Interleaved UYVY", | ||
133 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
134 | .mbus_code = V4L2_MBUS_FMT_UYVY8_1X16, | ||
135 | .bpp = 16, | ||
136 | .dlen = 16, | ||
125 | }, | 137 | }, |
126 | { | 138 | { |
127 | .desc = "RGB 565", | 139 | .desc = "RGB 565", |
128 | .pixelformat = V4L2_PIX_FMT_RGB565, | 140 | .pixelformat = V4L2_PIX_FMT_RGB565, |
129 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, | 141 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, |
130 | .bpp = 16, | 142 | .bpp = 16, |
143 | .dlen = 8, | ||
131 | }, | 144 | }, |
132 | { | 145 | { |
133 | .desc = "RGB 444", | 146 | .desc = "RGB 444", |
134 | .pixelformat = V4L2_PIX_FMT_RGB444, | 147 | .pixelformat = V4L2_PIX_FMT_RGB444, |
135 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, | 148 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, |
136 | .bpp = 16, | 149 | .bpp = 16, |
150 | .dlen = 8, | ||
137 | }, | 151 | }, |
138 | 152 | ||
139 | }; | 153 | }; |
@@ -366,9 +380,39 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
366 | params.width = bcap_dev->fmt.width; | 380 | params.width = bcap_dev->fmt.width; |
367 | params.height = bcap_dev->fmt.height; | 381 | params.height = bcap_dev->fmt.height; |
368 | params.bpp = bcap_dev->bpp; | 382 | params.bpp = bcap_dev->bpp; |
383 | params.dlen = bcap_dev->dlen; | ||
369 | params.ppi_control = bcap_dev->cfg->ppi_control; | 384 | params.ppi_control = bcap_dev->cfg->ppi_control; |
370 | params.int_mask = bcap_dev->cfg->int_mask; | 385 | params.int_mask = bcap_dev->cfg->int_mask; |
371 | params.blank_clocks = bcap_dev->cfg->blank_clocks; | 386 | if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities |
387 | & V4L2_IN_CAP_CUSTOM_TIMINGS) { | ||
388 | struct v4l2_bt_timings *bt = &bcap_dev->dv_timings.bt; | ||
389 | |||
390 | params.hdelay = bt->hsync + bt->hbackporch; | ||
391 | params.vdelay = bt->vsync + bt->vbackporch; | ||
392 | params.line = bt->hfrontporch + bt->hsync | ||
393 | + bt->hbackporch + bt->width; | ||
394 | params.frame = bt->vfrontporch + bt->vsync | ||
395 | + bt->vbackporch + bt->height; | ||
396 | if (bt->interlaced) | ||
397 | params.frame += bt->il_vfrontporch + bt->il_vsync | ||
398 | + bt->il_vbackporch; | ||
399 | } else if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities | ||
400 | & V4L2_IN_CAP_STD) { | ||
401 | params.hdelay = 0; | ||
402 | params.vdelay = 0; | ||
403 | if (bcap_dev->std & V4L2_STD_525_60) { | ||
404 | params.line = 858; | ||
405 | params.frame = 525; | ||
406 | } else { | ||
407 | params.line = 864; | ||
408 | params.frame = 625; | ||
409 | } | ||
410 | } else { | ||
411 | params.hdelay = 0; | ||
412 | params.vdelay = 0; | ||
413 | params.line = params.width + bcap_dev->cfg->blank_pixels; | ||
414 | params.frame = params.height; | ||
415 | } | ||
372 | ret = ppi->ops->set_params(ppi, ¶ms); | 416 | ret = ppi->ops->set_params(ppi, ¶ms); |
373 | if (ret < 0) { | 417 | if (ret < 0) { |
374 | v4l2_err(&bcap_dev->v4l2_dev, | 418 | v4l2_err(&bcap_dev->v4l2_dev, |
@@ -409,10 +453,10 @@ static int bcap_stop_streaming(struct vb2_queue *vq) | |||
409 | 453 | ||
410 | /* release all active buffers */ | 454 | /* release all active buffers */ |
411 | while (!list_empty(&bcap_dev->dma_queue)) { | 455 | while (!list_empty(&bcap_dev->dma_queue)) { |
412 | bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, | 456 | bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, |
413 | struct bcap_buffer, list); | 457 | struct bcap_buffer, list); |
414 | list_del(&bcap_dev->next_frm->list); | 458 | list_del(&bcap_dev->cur_frm->list); |
415 | vb2_buffer_done(&bcap_dev->next_frm->vb, VB2_BUF_STATE_ERROR); | 459 | vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR); |
416 | } | 460 | } |
417 | return 0; | 461 | return 0; |
418 | } | 462 | } |
@@ -484,17 +528,26 @@ static irqreturn_t bcap_isr(int irq, void *dev_id) | |||
484 | { | 528 | { |
485 | struct ppi_if *ppi = dev_id; | 529 | struct ppi_if *ppi = dev_id; |
486 | struct bcap_device *bcap_dev = ppi->priv; | 530 | struct bcap_device *bcap_dev = ppi->priv; |
487 | struct timeval timevalue; | ||
488 | struct vb2_buffer *vb = &bcap_dev->cur_frm->vb; | 531 | struct vb2_buffer *vb = &bcap_dev->cur_frm->vb; |
489 | dma_addr_t addr; | 532 | dma_addr_t addr; |
490 | 533 | ||
491 | spin_lock(&bcap_dev->lock); | 534 | spin_lock(&bcap_dev->lock); |
492 | 535 | ||
493 | if (bcap_dev->cur_frm != bcap_dev->next_frm) { | 536 | if (!list_empty(&bcap_dev->dma_queue)) { |
494 | do_gettimeofday(&timevalue); | 537 | v4l2_get_timestamp(&vb->v4l2_buf.timestamp); |
495 | vb->v4l2_buf.timestamp = timevalue; | 538 | if (ppi->err) { |
496 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | 539 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); |
497 | bcap_dev->cur_frm = bcap_dev->next_frm; | 540 | ppi->err = false; |
541 | } else { | ||
542 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | ||
543 | } | ||
544 | bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, | ||
545 | struct bcap_buffer, list); | ||
546 | list_del(&bcap_dev->cur_frm->list); | ||
547 | } else { | ||
548 | /* clear error flag, we will get a new frame */ | ||
549 | if (ppi->err) | ||
550 | ppi->err = false; | ||
498 | } | 551 | } |
499 | 552 | ||
500 | ppi->ops->stop(ppi); | 553 | ppi->ops->stop(ppi); |
@@ -502,13 +555,8 @@ static irqreturn_t bcap_isr(int irq, void *dev_id) | |||
502 | if (bcap_dev->stop) { | 555 | if (bcap_dev->stop) { |
503 | complete(&bcap_dev->comp); | 556 | complete(&bcap_dev->comp); |
504 | } else { | 557 | } else { |
505 | if (!list_empty(&bcap_dev->dma_queue)) { | 558 | addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); |
506 | bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, | 559 | ppi->ops->update_addr(ppi, (unsigned long)addr); |
507 | struct bcap_buffer, list); | ||
508 | list_del(&bcap_dev->next_frm->list); | ||
509 | addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->next_frm->vb, 0); | ||
510 | ppi->ops->update_addr(ppi, (unsigned long)addr); | ||
511 | } | ||
512 | ppi->ops->start(ppi); | 560 | ppi->ops->start(ppi); |
513 | } | 561 | } |
514 | 562 | ||
@@ -542,9 +590,8 @@ static int bcap_streamon(struct file *file, void *priv, | |||
542 | } | 590 | } |
543 | 591 | ||
544 | /* get the next frame from the dma queue */ | 592 | /* get the next frame from the dma queue */ |
545 | bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, | 593 | bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, |
546 | struct bcap_buffer, list); | 594 | struct bcap_buffer, list); |
547 | bcap_dev->cur_frm = bcap_dev->next_frm; | ||
548 | /* remove buffer from the dma queue */ | 595 | /* remove buffer from the dma queue */ |
549 | list_del(&bcap_dev->cur_frm->list); | 596 | list_del(&bcap_dev->cur_frm->list); |
550 | addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); | 597 | addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); |
@@ -602,6 +649,37 @@ static int bcap_s_std(struct file *file, void *priv, v4l2_std_id *std) | |||
602 | return 0; | 649 | return 0; |
603 | } | 650 | } |
604 | 651 | ||
652 | static int bcap_g_dv_timings(struct file *file, void *priv, | ||
653 | struct v4l2_dv_timings *timings) | ||
654 | { | ||
655 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
656 | int ret; | ||
657 | |||
658 | ret = v4l2_subdev_call(bcap_dev->sd, video, | ||
659 | g_dv_timings, timings); | ||
660 | if (ret < 0) | ||
661 | return ret; | ||
662 | |||
663 | bcap_dev->dv_timings = *timings; | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static int bcap_s_dv_timings(struct file *file, void *priv, | ||
668 | struct v4l2_dv_timings *timings) | ||
669 | { | ||
670 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
671 | int ret; | ||
672 | if (vb2_is_busy(&bcap_dev->buffer_queue)) | ||
673 | return -EBUSY; | ||
674 | |||
675 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_dv_timings, timings); | ||
676 | if (ret < 0) | ||
677 | return ret; | ||
678 | |||
679 | bcap_dev->dv_timings = *timings; | ||
680 | return 0; | ||
681 | } | ||
682 | |||
605 | static int bcap_enum_input(struct file *file, void *priv, | 683 | static int bcap_enum_input(struct file *file, void *priv, |
606 | struct v4l2_input *input) | 684 | struct v4l2_input *input) |
607 | { | 685 | { |
@@ -650,13 +728,15 @@ static int bcap_s_input(struct file *file, void *priv, unsigned int index) | |||
650 | return ret; | 728 | return ret; |
651 | } | 729 | } |
652 | bcap_dev->cur_input = index; | 730 | bcap_dev->cur_input = index; |
731 | /* if this route has specific config, update ppi control */ | ||
732 | if (route->ppi_control) | ||
733 | config->ppi_control = route->ppi_control; | ||
653 | return 0; | 734 | return 0; |
654 | } | 735 | } |
655 | 736 | ||
656 | static int bcap_try_format(struct bcap_device *bcap, | 737 | static int bcap_try_format(struct bcap_device *bcap, |
657 | struct v4l2_pix_format *pixfmt, | 738 | struct v4l2_pix_format *pixfmt, |
658 | enum v4l2_mbus_pixelcode *mbus_code, | 739 | struct bcap_format *bcap_fmt) |
659 | int *bpp) | ||
660 | { | 740 | { |
661 | struct bcap_format *sf = bcap->sensor_formats; | 741 | struct bcap_format *sf = bcap->sensor_formats; |
662 | struct bcap_format *fmt = NULL; | 742 | struct bcap_format *fmt = NULL; |
@@ -671,16 +751,20 @@ static int bcap_try_format(struct bcap_device *bcap, | |||
671 | if (i == bcap->num_sensor_formats) | 751 | if (i == bcap->num_sensor_formats) |
672 | fmt = &sf[0]; | 752 | fmt = &sf[0]; |
673 | 753 | ||
674 | if (mbus_code) | ||
675 | *mbus_code = fmt->mbus_code; | ||
676 | if (bpp) | ||
677 | *bpp = fmt->bpp; | ||
678 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code); | 754 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code); |
679 | ret = v4l2_subdev_call(bcap->sd, video, | 755 | ret = v4l2_subdev_call(bcap->sd, video, |
680 | try_mbus_fmt, &mbus_fmt); | 756 | try_mbus_fmt, &mbus_fmt); |
681 | if (ret < 0) | 757 | if (ret < 0) |
682 | return ret; | 758 | return ret; |
683 | v4l2_fill_pix_format(pixfmt, &mbus_fmt); | 759 | v4l2_fill_pix_format(pixfmt, &mbus_fmt); |
760 | if (bcap_fmt) { | ||
761 | for (i = 0; i < bcap->num_sensor_formats; i++) { | ||
762 | fmt = &sf[i]; | ||
763 | if (mbus_fmt.code == fmt->mbus_code) | ||
764 | break; | ||
765 | } | ||
766 | *bcap_fmt = *fmt; | ||
767 | } | ||
684 | pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8; | 768 | pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8; |
685 | pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; | 769 | pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; |
686 | return 0; | 770 | return 0; |
@@ -709,7 +793,7 @@ static int bcap_try_fmt_vid_cap(struct file *file, void *priv, | |||
709 | struct bcap_device *bcap_dev = video_drvdata(file); | 793 | struct bcap_device *bcap_dev = video_drvdata(file); |
710 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | 794 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; |
711 | 795 | ||
712 | return bcap_try_format(bcap_dev, pixfmt, NULL, NULL); | 796 | return bcap_try_format(bcap_dev, pixfmt, NULL); |
713 | } | 797 | } |
714 | 798 | ||
715 | static int bcap_g_fmt_vid_cap(struct file *file, void *priv, | 799 | static int bcap_g_fmt_vid_cap(struct file *file, void *priv, |
@@ -726,24 +810,25 @@ static int bcap_s_fmt_vid_cap(struct file *file, void *priv, | |||
726 | { | 810 | { |
727 | struct bcap_device *bcap_dev = video_drvdata(file); | 811 | struct bcap_device *bcap_dev = video_drvdata(file); |
728 | struct v4l2_mbus_framefmt mbus_fmt; | 812 | struct v4l2_mbus_framefmt mbus_fmt; |
729 | enum v4l2_mbus_pixelcode mbus_code; | 813 | struct bcap_format bcap_fmt; |
730 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | 814 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; |
731 | int ret, bpp; | 815 | int ret; |
732 | 816 | ||
733 | if (vb2_is_busy(&bcap_dev->buffer_queue)) | 817 | if (vb2_is_busy(&bcap_dev->buffer_queue)) |
734 | return -EBUSY; | 818 | return -EBUSY; |
735 | 819 | ||
736 | /* see if format works */ | 820 | /* see if format works */ |
737 | ret = bcap_try_format(bcap_dev, pixfmt, &mbus_code, &bpp); | 821 | ret = bcap_try_format(bcap_dev, pixfmt, &bcap_fmt); |
738 | if (ret < 0) | 822 | if (ret < 0) |
739 | return ret; | 823 | return ret; |
740 | 824 | ||
741 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, mbus_code); | 825 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, bcap_fmt.mbus_code); |
742 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt); | 826 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt); |
743 | if (ret < 0) | 827 | if (ret < 0) |
744 | return ret; | 828 | return ret; |
745 | bcap_dev->fmt = *pixfmt; | 829 | bcap_dev->fmt = *pixfmt; |
746 | bcap_dev->bpp = bpp; | 830 | bcap_dev->bpp = bcap_fmt.bpp; |
831 | bcap_dev->dlen = bcap_fmt.dlen; | ||
747 | return 0; | 832 | return 0; |
748 | } | 833 | } |
749 | 834 | ||
@@ -834,6 +919,8 @@ static const struct v4l2_ioctl_ops bcap_ioctl_ops = { | |||
834 | .vidioc_querystd = bcap_querystd, | 919 | .vidioc_querystd = bcap_querystd, |
835 | .vidioc_s_std = bcap_s_std, | 920 | .vidioc_s_std = bcap_s_std, |
836 | .vidioc_g_std = bcap_g_std, | 921 | .vidioc_g_std = bcap_g_std, |
922 | .vidioc_s_dv_timings = bcap_s_dv_timings, | ||
923 | .vidioc_g_dv_timings = bcap_g_dv_timings, | ||
837 | .vidioc_reqbufs = bcap_reqbufs, | 924 | .vidioc_reqbufs = bcap_reqbufs, |
838 | .vidioc_querybuf = bcap_querybuf, | 925 | .vidioc_querybuf = bcap_querybuf, |
839 | .vidioc_qbuf = bcap_qbuf, | 926 | .vidioc_qbuf = bcap_qbuf, |
@@ -869,6 +956,7 @@ static int bcap_probe(struct platform_device *pdev) | |||
869 | struct i2c_adapter *i2c_adap; | 956 | struct i2c_adapter *i2c_adap; |
870 | struct bfin_capture_config *config; | 957 | struct bfin_capture_config *config; |
871 | struct vb2_queue *q; | 958 | struct vb2_queue *q; |
959 | struct bcap_route *route; | ||
872 | int ret; | 960 | int ret; |
873 | 961 | ||
874 | config = pdev->dev.platform_data; | 962 | config = pdev->dev.platform_data; |
@@ -978,6 +1066,12 @@ static int bcap_probe(struct platform_device *pdev) | |||
978 | NULL); | 1066 | NULL); |
979 | if (bcap_dev->sd) { | 1067 | if (bcap_dev->sd) { |
980 | int i; | 1068 | int i; |
1069 | if (!config->num_inputs) { | ||
1070 | v4l2_err(&bcap_dev->v4l2_dev, | ||
1071 | "Unable to work without input\n"); | ||
1072 | goto err_unreg_vdev; | ||
1073 | } | ||
1074 | |||
981 | /* update tvnorms from the sub devices */ | 1075 | /* update tvnorms from the sub devices */ |
982 | for (i = 0; i < config->num_inputs; i++) | 1076 | for (i = 0; i < config->num_inputs; i++) |
983 | vfd->tvnorms |= config->inputs[i].std; | 1077 | vfd->tvnorms |= config->inputs[i].std; |
@@ -989,8 +1083,24 @@ static int bcap_probe(struct platform_device *pdev) | |||
989 | 1083 | ||
990 | v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n"); | 1084 | v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n"); |
991 | 1085 | ||
1086 | /* | ||
1087 | * explicitly set input, otherwise some boards | ||
1088 | * may not work at the state as we expected | ||
1089 | */ | ||
1090 | route = &config->routes[0]; | ||
1091 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_routing, | ||
1092 | route->input, route->output, 0); | ||
1093 | if ((ret < 0) && (ret != -ENOIOCTLCMD)) { | ||
1094 | v4l2_err(&bcap_dev->v4l2_dev, "Failed to set input\n"); | ||
1095 | goto err_unreg_vdev; | ||
1096 | } | ||
1097 | bcap_dev->cur_input = 0; | ||
1098 | /* if this route has specific config, update ppi control */ | ||
1099 | if (route->ppi_control) | ||
1100 | config->ppi_control = route->ppi_control; | ||
1101 | |||
992 | /* now we can probe the default state */ | 1102 | /* now we can probe the default state */ |
993 | if (vfd->tvnorms) { | 1103 | if (config->inputs[0].capabilities & V4L2_IN_CAP_STD) { |
994 | v4l2_std_id std; | 1104 | v4l2_std_id std; |
995 | ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std); | 1105 | ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std); |
996 | if (ret) { | 1106 | if (ret) { |
@@ -1000,6 +1110,17 @@ static int bcap_probe(struct platform_device *pdev) | |||
1000 | } | 1110 | } |
1001 | bcap_dev->std = std; | 1111 | bcap_dev->std = std; |
1002 | } | 1112 | } |
1113 | if (config->inputs[0].capabilities & V4L2_IN_CAP_CUSTOM_TIMINGS) { | ||
1114 | struct v4l2_dv_timings dv_timings; | ||
1115 | ret = v4l2_subdev_call(bcap_dev->sd, video, | ||
1116 | g_dv_timings, &dv_timings); | ||
1117 | if (ret) { | ||
1118 | v4l2_err(&bcap_dev->v4l2_dev, | ||
1119 | "Unable to get dv timings\n"); | ||
1120 | goto err_unreg_vdev; | ||
1121 | } | ||
1122 | bcap_dev->dv_timings = dv_timings; | ||
1123 | } | ||
1003 | ret = bcap_init_sensor_formats(bcap_dev); | 1124 | ret = bcap_init_sensor_formats(bcap_dev); |
1004 | if (ret) { | 1125 | if (ret) { |
1005 | v4l2_err(&bcap_dev->v4l2_dev, | 1126 | v4l2_err(&bcap_dev->v4l2_dev, |
diff --git a/drivers/media/platform/blackfin/ppi.c b/drivers/media/platform/blackfin/ppi.c index d29592186b02..01b5b501347e 100644 --- a/drivers/media/platform/blackfin/ppi.c +++ b/drivers/media/platform/blackfin/ppi.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/module.h> | ||
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | 22 | ||
22 | #include <asm/bfin_ppi.h> | 23 | #include <asm/bfin_ppi.h> |
@@ -58,15 +59,33 @@ static irqreturn_t ppi_irq_err(int irq, void *dev_id) | |||
58 | * others are W1C | 59 | * others are W1C |
59 | */ | 60 | */ |
60 | status = bfin_read16(®->status); | 61 | status = bfin_read16(®->status); |
62 | if (status & 0x3000) | ||
63 | ppi->err = true; | ||
61 | bfin_write16(®->status, 0xff00); | 64 | bfin_write16(®->status, 0xff00); |
62 | break; | 65 | break; |
63 | } | 66 | } |
64 | case PPI_TYPE_EPPI: | 67 | case PPI_TYPE_EPPI: |
65 | { | 68 | { |
66 | struct bfin_eppi_regs *reg = info->base; | 69 | struct bfin_eppi_regs *reg = info->base; |
70 | unsigned short status; | ||
71 | |||
72 | status = bfin_read16(®->status); | ||
73 | if (status & 0x2) | ||
74 | ppi->err = true; | ||
67 | bfin_write16(®->status, 0xffff); | 75 | bfin_write16(®->status, 0xffff); |
68 | break; | 76 | break; |
69 | } | 77 | } |
78 | case PPI_TYPE_EPPI3: | ||
79 | { | ||
80 | struct bfin_eppi3_regs *reg = info->base; | ||
81 | unsigned long stat; | ||
82 | |||
83 | stat = bfin_read32(®->stat); | ||
84 | if (stat & 0x2) | ||
85 | ppi->err = true; | ||
86 | bfin_write32(®->stat, 0xc0ff); | ||
87 | break; | ||
88 | } | ||
70 | default: | 89 | default: |
71 | break; | 90 | break; |
72 | } | 91 | } |
@@ -128,6 +147,12 @@ static int ppi_start(struct ppi_if *ppi) | |||
128 | bfin_write32(®->control, ppi->ppi_control); | 147 | bfin_write32(®->control, ppi->ppi_control); |
129 | break; | 148 | break; |
130 | } | 149 | } |
150 | case PPI_TYPE_EPPI3: | ||
151 | { | ||
152 | struct bfin_eppi3_regs *reg = info->base; | ||
153 | bfin_write32(®->ctl, ppi->ppi_control); | ||
154 | break; | ||
155 | } | ||
131 | default: | 156 | default: |
132 | return -EINVAL; | 157 | return -EINVAL; |
133 | } | 158 | } |
@@ -155,6 +180,12 @@ static int ppi_stop(struct ppi_if *ppi) | |||
155 | bfin_write32(®->control, ppi->ppi_control); | 180 | bfin_write32(®->control, ppi->ppi_control); |
156 | break; | 181 | break; |
157 | } | 182 | } |
183 | case PPI_TYPE_EPPI3: | ||
184 | { | ||
185 | struct bfin_eppi3_regs *reg = info->base; | ||
186 | bfin_write32(®->ctl, ppi->ppi_control); | ||
187 | break; | ||
188 | } | ||
158 | default: | 189 | default: |
159 | return -EINVAL; | 190 | return -EINVAL; |
160 | } | 191 | } |
@@ -171,17 +202,23 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | |||
171 | { | 202 | { |
172 | const struct ppi_info *info = ppi->info; | 203 | const struct ppi_info *info = ppi->info; |
173 | int dma32 = 0; | 204 | int dma32 = 0; |
174 | int dma_config, bytes_per_line, lines_per_frame; | 205 | int dma_config, bytes_per_line; |
206 | int hcount, hdelay, samples_per_line; | ||
175 | 207 | ||
176 | bytes_per_line = params->width * params->bpp / 8; | 208 | bytes_per_line = params->width * params->bpp / 8; |
177 | lines_per_frame = params->height; | 209 | /* convert parameters unit from pixels to samples */ |
210 | hcount = params->width * params->bpp / params->dlen; | ||
211 | hdelay = params->hdelay * params->bpp / params->dlen; | ||
212 | samples_per_line = params->line * params->bpp / params->dlen; | ||
178 | if (params->int_mask == 0xFFFFFFFF) | 213 | if (params->int_mask == 0xFFFFFFFF) |
179 | ppi->err_int = false; | 214 | ppi->err_int = false; |
180 | else | 215 | else |
181 | ppi->err_int = true; | 216 | ppi->err_int = true; |
182 | 217 | ||
183 | dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN); | 218 | dma_config = (DMA_FLOW_STOP | RESTART | DMA2D | DI_EN_Y); |
184 | ppi->ppi_control = params->ppi_control & ~PORT_EN; | 219 | ppi->ppi_control = params->ppi_control & ~PORT_EN; |
220 | if (!(ppi->ppi_control & PORT_DIR)) | ||
221 | dma_config |= WNR; | ||
185 | switch (info->type) { | 222 | switch (info->type) { |
186 | case PPI_TYPE_PPI: | 223 | case PPI_TYPE_PPI: |
187 | { | 224 | { |
@@ -191,8 +228,8 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | |||
191 | dma32 = 1; | 228 | dma32 = 1; |
192 | 229 | ||
193 | bfin_write16(®->control, ppi->ppi_control); | 230 | bfin_write16(®->control, ppi->ppi_control); |
194 | bfin_write16(®->count, bytes_per_line - 1); | 231 | bfin_write16(®->count, samples_per_line - 1); |
195 | bfin_write16(®->frame, lines_per_frame); | 232 | bfin_write16(®->frame, params->frame); |
196 | break; | 233 | break; |
197 | } | 234 | } |
198 | case PPI_TYPE_EPPI: | 235 | case PPI_TYPE_EPPI: |
@@ -204,12 +241,31 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | |||
204 | dma32 = 1; | 241 | dma32 = 1; |
205 | 242 | ||
206 | bfin_write32(®->control, ppi->ppi_control); | 243 | bfin_write32(®->control, ppi->ppi_control); |
207 | bfin_write16(®->line, bytes_per_line + params->blank_clocks); | 244 | bfin_write16(®->line, samples_per_line); |
208 | bfin_write16(®->frame, lines_per_frame); | 245 | bfin_write16(®->frame, params->frame); |
209 | bfin_write16(®->hdelay, 0); | 246 | bfin_write16(®->hdelay, hdelay); |
210 | bfin_write16(®->vdelay, 0); | 247 | bfin_write16(®->vdelay, params->vdelay); |
211 | bfin_write16(®->hcount, bytes_per_line); | 248 | bfin_write16(®->hcount, hcount); |
212 | bfin_write16(®->vcount, lines_per_frame); | 249 | bfin_write16(®->vcount, params->height); |
250 | break; | ||
251 | } | ||
252 | case PPI_TYPE_EPPI3: | ||
253 | { | ||
254 | struct bfin_eppi3_regs *reg = info->base; | ||
255 | |||
256 | if ((params->ppi_control & PACK_EN) | ||
257 | || (params->ppi_control & 0x70000) > DLEN_16) | ||
258 | dma32 = 1; | ||
259 | |||
260 | bfin_write32(®->ctl, ppi->ppi_control); | ||
261 | bfin_write32(®->line, samples_per_line); | ||
262 | bfin_write32(®->frame, params->frame); | ||
263 | bfin_write32(®->hdly, hdelay); | ||
264 | bfin_write32(®->vdly, params->vdelay); | ||
265 | bfin_write32(®->hcnt, hcount); | ||
266 | bfin_write32(®->vcnt, params->height); | ||
267 | if (params->int_mask) | ||
268 | bfin_write32(®->imsk, params->int_mask & 0xFF); | ||
213 | break; | 269 | break; |
214 | } | 270 | } |
215 | default: | 271 | default: |
@@ -217,17 +273,17 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | |||
217 | } | 273 | } |
218 | 274 | ||
219 | if (dma32) { | 275 | if (dma32) { |
220 | dma_config |= WDSIZE_32; | 276 | dma_config |= WDSIZE_32 | PSIZE_32; |
221 | set_dma_x_count(info->dma_ch, bytes_per_line >> 2); | 277 | set_dma_x_count(info->dma_ch, bytes_per_line >> 2); |
222 | set_dma_x_modify(info->dma_ch, 4); | 278 | set_dma_x_modify(info->dma_ch, 4); |
223 | set_dma_y_modify(info->dma_ch, 4); | 279 | set_dma_y_modify(info->dma_ch, 4); |
224 | } else { | 280 | } else { |
225 | dma_config |= WDSIZE_16; | 281 | dma_config |= WDSIZE_16 | PSIZE_16; |
226 | set_dma_x_count(info->dma_ch, bytes_per_line >> 1); | 282 | set_dma_x_count(info->dma_ch, bytes_per_line >> 1); |
227 | set_dma_x_modify(info->dma_ch, 2); | 283 | set_dma_x_modify(info->dma_ch, 2); |
228 | set_dma_y_modify(info->dma_ch, 2); | 284 | set_dma_y_modify(info->dma_ch, 2); |
229 | } | 285 | } |
230 | set_dma_y_count(info->dma_ch, lines_per_frame); | 286 | set_dma_y_count(info->dma_ch, params->height); |
231 | set_dma_config(info->dma_ch, dma_config); | 287 | set_dma_config(info->dma_ch, dma_config); |
232 | 288 | ||
233 | SSYNC(); | 289 | SSYNC(); |
@@ -263,9 +319,15 @@ struct ppi_if *ppi_create_instance(const struct ppi_info *info) | |||
263 | pr_info("ppi probe success\n"); | 319 | pr_info("ppi probe success\n"); |
264 | return ppi; | 320 | return ppi; |
265 | } | 321 | } |
322 | EXPORT_SYMBOL(ppi_create_instance); | ||
266 | 323 | ||
267 | void ppi_delete_instance(struct ppi_if *ppi) | 324 | void ppi_delete_instance(struct ppi_if *ppi) |
268 | { | 325 | { |
269 | peripheral_free_list(ppi->info->pin_req); | 326 | peripheral_free_list(ppi->info->pin_req); |
270 | kfree(ppi); | 327 | kfree(ppi); |
271 | } | 328 | } |
329 | EXPORT_SYMBOL(ppi_delete_instance); | ||
330 | |||
331 | MODULE_DESCRIPTION("Analog Devices PPI driver"); | ||
332 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | ||
333 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 4a980e029ca7..20827ba168fc 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c | |||
@@ -178,6 +178,10 @@ struct coda_ctx { | |||
178 | int idx; | 178 | int idx; |
179 | }; | 179 | }; |
180 | 180 | ||
181 | static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff, | ||
182 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 }; | ||
183 | static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 }; | ||
184 | |||
181 | static inline void coda_write(struct coda_dev *dev, u32 data, u32 reg) | 185 | static inline void coda_write(struct coda_dev *dev, u32 data, u32 reg) |
182 | { | 186 | { |
183 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | 187 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, |
@@ -944,6 +948,24 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_d | |||
944 | return 0; | 948 | return 0; |
945 | } | 949 | } |
946 | 950 | ||
951 | static int coda_h264_padding(int size, char *p) | ||
952 | { | ||
953 | int nal_size; | ||
954 | int diff; | ||
955 | |||
956 | diff = size - (size & ~0x7); | ||
957 | if (diff == 0) | ||
958 | return 0; | ||
959 | |||
960 | nal_size = coda_filler_size[diff]; | ||
961 | memcpy(p, coda_filler_nal, nal_size); | ||
962 | |||
963 | /* Add rbsp stop bit and trailing at the end */ | ||
964 | *(p + nal_size - 1) = 0x80; | ||
965 | |||
966 | return nal_size; | ||
967 | } | ||
968 | |||
947 | static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | 969 | static int coda_start_streaming(struct vb2_queue *q, unsigned int count) |
948 | { | 970 | { |
949 | struct coda_ctx *ctx = vb2_get_drv_priv(q); | 971 | struct coda_ctx *ctx = vb2_get_drv_priv(q); |
@@ -1171,7 +1193,15 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
1171 | coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); | 1193 | coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); |
1172 | memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0), | 1194 | memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0), |
1173 | ctx->vpu_header_size[1]); | 1195 | ctx->vpu_header_size[1]); |
1174 | ctx->vpu_header_size[2] = 0; | 1196 | /* |
1197 | * Length of H.264 headers is variable and thus it might not be | ||
1198 | * aligned for the coda to append the encoded frame. In that is | ||
1199 | * the case a filler NAL must be added to header 2. | ||
1200 | */ | ||
1201 | ctx->vpu_header_size[2] = coda_h264_padding( | ||
1202 | (ctx->vpu_header_size[0] + | ||
1203 | ctx->vpu_header_size[1]), | ||
1204 | ctx->vpu_header[2]); | ||
1175 | break; | 1205 | break; |
1176 | case V4L2_PIX_FMT_MPEG4: | 1206 | case V4L2_PIX_FMT_MPEG4: |
1177 | /* | 1207 | /* |
diff --git a/drivers/media/platform/davinci/Kconfig b/drivers/media/platform/davinci/Kconfig index 3c56037c82fc..ccfde4eb626a 100644 --- a/drivers/media/platform/davinci/Kconfig +++ b/drivers/media/platform/davinci/Kconfig | |||
@@ -97,25 +97,15 @@ config VIDEO_ISIF | |||
97 | To compile this driver as a module, choose M here: the | 97 | To compile this driver as a module, choose M here: the |
98 | module will be called vpfe. | 98 | module will be called vpfe. |
99 | 99 | ||
100 | config VIDEO_DM644X_VPBE | 100 | config VIDEO_DAVINCI_VPBE_DISPLAY |
101 | tristate "DM644X VPBE HW module" | 101 | tristate "DM644X/DM365/DM355 VPBE HW module" |
102 | depends on ARCH_DAVINCI_DM644x | 102 | depends on ARCH_DAVINCI_DM644x || ARCH_DAVINCI_DM355 || ARCH_DAVINCI_DM365 |
103 | select VIDEO_VPSS_SYSTEM | 103 | select VIDEO_VPSS_SYSTEM |
104 | select VIDEOBUF2_DMA_CONTIG | 104 | select VIDEOBUF2_DMA_CONTIG |
105 | help | 105 | help |
106 | Enables VPBE modules used for display on a DM644x | 106 | Enables Davinci VPBE module used for display devices. |
107 | SoC. | 107 | This module is common for following DM644x/DM365/DM355 |
108 | based display devices. | ||
108 | 109 | ||
109 | To compile this driver as a module, choose M here: the | 110 | To compile this driver as a module, choose M here: the |
110 | module will be called vpbe. | 111 | module will be called vpbe. |
111 | |||
112 | |||
113 | config VIDEO_VPBE_DISPLAY | ||
114 | tristate "VPBE V4L2 Display driver" | ||
115 | depends on ARCH_DAVINCI_DM644x | ||
116 | select VIDEO_DM644X_VPBE | ||
117 | help | ||
118 | Enables VPBE V4L2 Display driver on a DM644x device | ||
119 | |||
120 | To compile this driver as a module, choose M here: the | ||
121 | module will be called vpbe_display. | ||
diff --git a/drivers/media/platform/davinci/Makefile b/drivers/media/platform/davinci/Makefile index 74ed92d09257..f40f5219ca50 100644 --- a/drivers/media/platform/davinci/Makefile +++ b/drivers/media/platform/davinci/Makefile | |||
@@ -16,5 +16,5 @@ obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o | |||
16 | obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o | 16 | obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o |
17 | obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o | 17 | obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o |
18 | obj-$(CONFIG_VIDEO_ISIF) += isif.o | 18 | obj-$(CONFIG_VIDEO_ISIF) += isif.o |
19 | obj-$(CONFIG_VIDEO_DM644X_VPBE) += vpbe.o vpbe_osd.o vpbe_venc.o | 19 | obj-$(CONFIG_VIDEO_DAVINCI_VPBE_DISPLAY) += vpbe.o vpbe_osd.o \ |
20 | obj-$(CONFIG_VIDEO_VPBE_DISPLAY) += vpbe_display.o | 20 | vpbe_venc.o vpbe_display.o |
diff --git a/drivers/media/platform/davinci/dm355_ccdc.c b/drivers/media/platform/davinci/dm355_ccdc.c index f263cabade7a..4277e4ad810c 100644 --- a/drivers/media/platform/davinci/dm355_ccdc.c +++ b/drivers/media/platform/davinci/dm355_ccdc.c | |||
@@ -557,7 +557,7 @@ static int ccdc_config_vdfc(struct ccdc_vertical_dft *dfc) | |||
557 | */ | 557 | */ |
558 | static void ccdc_config_csc(struct ccdc_csc *csc) | 558 | static void ccdc_config_csc(struct ccdc_csc *csc) |
559 | { | 559 | { |
560 | u32 val1, val2; | 560 | u32 val1 = 0, val2; |
561 | int i; | 561 | int i; |
562 | 562 | ||
563 | if (!csc->enable) | 563 | if (!csc->enable) |
diff --git a/drivers/media/platform/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c index 841b91a3d255..4ca0f9a2ad8a 100644 --- a/drivers/media/platform/davinci/vpbe.c +++ b/drivers/media/platform/davinci/vpbe.c | |||
@@ -558,9 +558,9 @@ static int platform_device_get(struct device *dev, void *data) | |||
558 | struct platform_device *pdev = to_platform_device(dev); | 558 | struct platform_device *pdev = to_platform_device(dev); |
559 | struct vpbe_device *vpbe_dev = data; | 559 | struct vpbe_device *vpbe_dev = data; |
560 | 560 | ||
561 | if (strcmp("vpbe-osd", pdev->name) == 0) | 561 | if (strstr(pdev->name, "vpbe-osd") != NULL) |
562 | vpbe_dev->osd_device = platform_get_drvdata(pdev); | 562 | vpbe_dev->osd_device = platform_get_drvdata(pdev); |
563 | if (strcmp("vpbe-venc", pdev->name) == 0) | 563 | if (strstr(pdev->name, "vpbe-venc") != NULL) |
564 | vpbe_dev->venc_device = dev_get_platdata(&pdev->dev); | 564 | vpbe_dev->venc_device = dev_get_platdata(&pdev->dev); |
565 | 565 | ||
566 | return 0; | 566 | return 0; |
@@ -584,7 +584,6 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
584 | struct v4l2_subdev **enc_subdev; | 584 | struct v4l2_subdev **enc_subdev; |
585 | struct osd_state *osd_device; | 585 | struct osd_state *osd_device; |
586 | struct i2c_adapter *i2c_adap; | 586 | struct i2c_adapter *i2c_adap; |
587 | int output_index; | ||
588 | int num_encoders; | 587 | int num_encoders; |
589 | int ret = 0; | 588 | int ret = 0; |
590 | int err; | 589 | int err; |
@@ -632,8 +631,10 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
632 | 631 | ||
633 | err = bus_for_each_dev(&platform_bus_type, NULL, vpbe_dev, | 632 | err = bus_for_each_dev(&platform_bus_type, NULL, vpbe_dev, |
634 | platform_device_get); | 633 | platform_device_get); |
635 | if (err < 0) | 634 | if (err < 0) { |
636 | return err; | 635 | ret = err; |
636 | goto fail_dev_unregister; | ||
637 | } | ||
637 | 638 | ||
638 | vpbe_dev->venc = venc_sub_dev_init(&vpbe_dev->v4l2_dev, | 639 | vpbe_dev->venc = venc_sub_dev_init(&vpbe_dev->v4l2_dev, |
639 | vpbe_dev->cfg->venc.module_name); | 640 | vpbe_dev->cfg->venc.module_name); |
@@ -731,7 +732,6 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
731 | /* set the current encoder and output to that of venc by default */ | 732 | /* set the current encoder and output to that of venc by default */ |
732 | vpbe_dev->current_sd_index = 0; | 733 | vpbe_dev->current_sd_index = 0; |
733 | vpbe_dev->current_out_index = 0; | 734 | vpbe_dev->current_out_index = 0; |
734 | output_index = 0; | ||
735 | 735 | ||
736 | mutex_unlock(&vpbe_dev->lock); | 736 | mutex_unlock(&vpbe_dev->lock); |
737 | 737 | ||
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index e707a6f2325b..5e6b0cab514b 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c | |||
@@ -791,7 +791,6 @@ static int vpbe_display_g_crop(struct file *file, void *priv, | |||
791 | struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; | 791 | struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; |
792 | struct osd_state *osd_device = fh->disp_dev->osd_device; | 792 | struct osd_state *osd_device = fh->disp_dev->osd_device; |
793 | struct v4l2_rect *rect = &crop->c; | 793 | struct v4l2_rect *rect = &crop->c; |
794 | int ret; | ||
795 | 794 | ||
796 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, | 795 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, |
797 | "VIDIOC_G_CROP, layer id = %d\n", | 796 | "VIDIOC_G_CROP, layer id = %d\n", |
@@ -799,7 +798,7 @@ static int vpbe_display_g_crop(struct file *file, void *priv, | |||
799 | 798 | ||
800 | if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { | 799 | if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { |
801 | v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buf type\n"); | 800 | v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buf type\n"); |
802 | ret = -EINVAL; | 801 | return -EINVAL; |
803 | } | 802 | } |
804 | osd_device->ops.get_layer_config(osd_device, | 803 | osd_device->ops.get_layer_config(osd_device, |
805 | layer->layer_info.id, cfg); | 804 | layer->layer_info.id, cfg); |
@@ -1393,9 +1392,9 @@ static int vpbe_display_reqbufs(struct file *file, void *priv, | |||
1393 | } | 1392 | } |
1394 | /* Initialize videobuf queue as per the buffer type */ | 1393 | /* Initialize videobuf queue as per the buffer type */ |
1395 | layer->alloc_ctx = vb2_dma_contig_init_ctx(vpbe_dev->pdev); | 1394 | layer->alloc_ctx = vb2_dma_contig_init_ctx(vpbe_dev->pdev); |
1396 | if (!layer->alloc_ctx) { | 1395 | if (IS_ERR(layer->alloc_ctx)) { |
1397 | v4l2_err(&vpbe_dev->v4l2_dev, "Failed to get the context\n"); | 1396 | v4l2_err(&vpbe_dev->v4l2_dev, "Failed to get the context\n"); |
1398 | return -EINVAL; | 1397 | return PTR_ERR(layer->alloc_ctx); |
1399 | } | 1398 | } |
1400 | q = &layer->buffer_queue; | 1399 | q = &layer->buffer_queue; |
1401 | memset(q, 0, sizeof(*q)); | 1400 | memset(q, 0, sizeof(*q)); |
@@ -1656,7 +1655,7 @@ static int vpbe_device_get(struct device *dev, void *data) | |||
1656 | if (strcmp("vpbe_controller", pdev->name) == 0) | 1655 | if (strcmp("vpbe_controller", pdev->name) == 0) |
1657 | vpbe_disp->vpbe_dev = platform_get_drvdata(pdev); | 1656 | vpbe_disp->vpbe_dev = platform_get_drvdata(pdev); |
1658 | 1657 | ||
1659 | if (strcmp("vpbe-osd", pdev->name) == 0) | 1658 | if (strstr(pdev->name, "vpbe-osd") != NULL) |
1660 | vpbe_disp->osd_device = platform_get_drvdata(pdev); | 1659 | vpbe_disp->osd_device = platform_get_drvdata(pdev); |
1661 | 1660 | ||
1662 | return 0; | 1661 | return 0; |
diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c index 707f243f810d..12ad17c52ef3 100644 --- a/drivers/media/platform/davinci/vpbe_osd.c +++ b/drivers/media/platform/davinci/vpbe_osd.c | |||
@@ -39,7 +39,22 @@ | |||
39 | #include <linux/io.h> | 39 | #include <linux/io.h> |
40 | #include "vpbe_osd_regs.h" | 40 | #include "vpbe_osd_regs.h" |
41 | 41 | ||
42 | #define MODULE_NAME VPBE_OSD_SUBDEV_NAME | 42 | #define MODULE_NAME "davinci-vpbe-osd" |
43 | |||
44 | static struct platform_device_id vpbe_osd_devtype[] = { | ||
45 | { | ||
46 | .name = DM644X_VPBE_OSD_SUBDEV_NAME, | ||
47 | .driver_data = VPBE_VERSION_1, | ||
48 | }, { | ||
49 | .name = DM365_VPBE_OSD_SUBDEV_NAME, | ||
50 | .driver_data = VPBE_VERSION_2, | ||
51 | }, { | ||
52 | .name = DM355_VPBE_OSD_SUBDEV_NAME, | ||
53 | .driver_data = VPBE_VERSION_3, | ||
54 | }, | ||
55 | }; | ||
56 | |||
57 | MODULE_DEVICE_TABLE(platform, vpbe_osd_devtype); | ||
43 | 58 | ||
44 | /* register access routines */ | 59 | /* register access routines */ |
45 | static inline u32 osd_read(struct osd_state *sd, u32 offset) | 60 | static inline u32 osd_read(struct osd_state *sd, u32 offset) |
@@ -129,7 +144,7 @@ static int _osd_dm6446_vid0_pingpong(struct osd_state *sd, | |||
129 | struct osd_platform_data *pdata; | 144 | struct osd_platform_data *pdata; |
130 | 145 | ||
131 | pdata = (struct osd_platform_data *)sd->dev->platform_data; | 146 | pdata = (struct osd_platform_data *)sd->dev->platform_data; |
132 | if (pdata->field_inv_wa_enable) { | 147 | if (pdata != NULL && pdata->field_inv_wa_enable) { |
133 | 148 | ||
134 | if (!field_inversion || !lconfig->interlaced) { | 149 | if (!field_inversion || !lconfig->interlaced) { |
135 | osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR); | 150 | osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR); |
@@ -1526,7 +1541,7 @@ static const struct vpbe_osd_ops osd_ops = { | |||
1526 | 1541 | ||
1527 | static int osd_probe(struct platform_device *pdev) | 1542 | static int osd_probe(struct platform_device *pdev) |
1528 | { | 1543 | { |
1529 | struct osd_platform_data *pdata; | 1544 | const struct platform_device_id *pdev_id; |
1530 | struct osd_state *osd; | 1545 | struct osd_state *osd; |
1531 | struct resource *res; | 1546 | struct resource *res; |
1532 | int ret = 0; | 1547 | int ret = 0; |
@@ -1535,16 +1550,15 @@ static int osd_probe(struct platform_device *pdev) | |||
1535 | if (osd == NULL) | 1550 | if (osd == NULL) |
1536 | return -ENOMEM; | 1551 | return -ENOMEM; |
1537 | 1552 | ||
1538 | osd->dev = &pdev->dev; | 1553 | pdev_id = platform_get_device_id(pdev); |
1539 | pdata = (struct osd_platform_data *)pdev->dev.platform_data; | 1554 | if (!pdev_id) { |
1540 | osd->vpbe_type = (enum vpbe_version)pdata->vpbe_type; | 1555 | ret = -EINVAL; |
1541 | if (NULL == pdev->dev.platform_data) { | ||
1542 | dev_err(osd->dev, "No platform data defined for OSD" | ||
1543 | " sub device\n"); | ||
1544 | ret = -ENOENT; | ||
1545 | goto free_mem; | 1556 | goto free_mem; |
1546 | } | 1557 | } |
1547 | 1558 | ||
1559 | osd->dev = &pdev->dev; | ||
1560 | osd->vpbe_type = pdev_id->driver_data; | ||
1561 | |||
1548 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1562 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1549 | if (!res) { | 1563 | if (!res) { |
1550 | dev_err(osd->dev, "Unable to get OSD register address map\n"); | 1564 | dev_err(osd->dev, "Unable to get OSD register address map\n"); |
@@ -1595,6 +1609,7 @@ static struct platform_driver osd_driver = { | |||
1595 | .name = MODULE_NAME, | 1609 | .name = MODULE_NAME, |
1596 | .owner = THIS_MODULE, | 1610 | .owner = THIS_MODULE, |
1597 | }, | 1611 | }, |
1612 | .id_table = vpbe_osd_devtype | ||
1598 | }; | 1613 | }; |
1599 | 1614 | ||
1600 | module_platform_driver(osd_driver); | 1615 | module_platform_driver(osd_driver); |
diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c index aed7369b962a..bdbebd59df98 100644 --- a/drivers/media/platform/davinci/vpbe_venc.c +++ b/drivers/media/platform/davinci/vpbe_venc.c | |||
@@ -38,7 +38,22 @@ | |||
38 | 38 | ||
39 | #include "vpbe_venc_regs.h" | 39 | #include "vpbe_venc_regs.h" |
40 | 40 | ||
41 | #define MODULE_NAME VPBE_VENC_SUBDEV_NAME | 41 | #define MODULE_NAME "davinci-vpbe-venc" |
42 | |||
43 | static struct platform_device_id vpbe_venc_devtype[] = { | ||
44 | { | ||
45 | .name = DM644X_VPBE_VENC_SUBDEV_NAME, | ||
46 | .driver_data = VPBE_VERSION_1, | ||
47 | }, { | ||
48 | .name = DM365_VPBE_VENC_SUBDEV_NAME, | ||
49 | .driver_data = VPBE_VERSION_2, | ||
50 | }, { | ||
51 | .name = DM355_VPBE_VENC_SUBDEV_NAME, | ||
52 | .driver_data = VPBE_VERSION_3, | ||
53 | }, | ||
54 | }; | ||
55 | |||
56 | MODULE_DEVICE_TABLE(platform, vpbe_venc_devtype); | ||
42 | 57 | ||
43 | static int debug = 2; | 58 | static int debug = 2; |
44 | module_param(debug, int, 0644); | 59 | module_param(debug, int, 0644); |
@@ -54,6 +69,7 @@ struct venc_state { | |||
54 | spinlock_t lock; | 69 | spinlock_t lock; |
55 | void __iomem *venc_base; | 70 | void __iomem *venc_base; |
56 | void __iomem *vdaccfg_reg; | 71 | void __iomem *vdaccfg_reg; |
72 | enum vpbe_version venc_type; | ||
57 | }; | 73 | }; |
58 | 74 | ||
59 | static inline struct venc_state *to_state(struct v4l2_subdev *sd) | 75 | static inline struct venc_state *to_state(struct v4l2_subdev *sd) |
@@ -127,7 +143,7 @@ static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index) | |||
127 | static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable) | 143 | static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable) |
128 | { | 144 | { |
129 | struct venc_state *venc = to_state(sd); | 145 | struct venc_state *venc = to_state(sd); |
130 | struct venc_platform_data *pdata = venc->pdata; | 146 | |
131 | v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n"); | 147 | v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n"); |
132 | 148 | ||
133 | if (benable) { | 149 | if (benable) { |
@@ -159,7 +175,7 @@ static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable) | |||
159 | 175 | ||
160 | /* Disable LCD output control (accepting default polarity) */ | 176 | /* Disable LCD output control (accepting default polarity) */ |
161 | venc_write(sd, VENC_LCDOUT, 0); | 177 | venc_write(sd, VENC_LCDOUT, 0); |
162 | if (pdata->venc_type != VPBE_VERSION_3) | 178 | if (venc->venc_type != VPBE_VERSION_3) |
163 | venc_write(sd, VENC_CMPNT, 0x100); | 179 | venc_write(sd, VENC_CMPNT, 0x100); |
164 | venc_write(sd, VENC_HSPLS, 0); | 180 | venc_write(sd, VENC_HSPLS, 0); |
165 | venc_write(sd, VENC_HINT, 0); | 181 | venc_write(sd, VENC_HINT, 0); |
@@ -203,11 +219,11 @@ static int venc_set_ntsc(struct v4l2_subdev *sd) | |||
203 | 219 | ||
204 | venc_enabledigitaloutput(sd, 0); | 220 | venc_enabledigitaloutput(sd, 0); |
205 | 221 | ||
206 | if (pdata->venc_type == VPBE_VERSION_3) { | 222 | if (venc->venc_type == VPBE_VERSION_3) { |
207 | venc_write(sd, VENC_CLKCTL, 0x01); | 223 | venc_write(sd, VENC_CLKCTL, 0x01); |
208 | venc_write(sd, VENC_VIDCTL, 0); | 224 | venc_write(sd, VENC_VIDCTL, 0); |
209 | val = vdaccfg_write(sd, VDAC_CONFIG_SD_V3); | 225 | val = vdaccfg_write(sd, VDAC_CONFIG_SD_V3); |
210 | } else if (pdata->venc_type == VPBE_VERSION_2) { | 226 | } else if (venc->venc_type == VPBE_VERSION_2) { |
211 | venc_write(sd, VENC_CLKCTL, 0x01); | 227 | venc_write(sd, VENC_CLKCTL, 0x01); |
212 | venc_write(sd, VENC_VIDCTL, 0); | 228 | venc_write(sd, VENC_VIDCTL, 0); |
213 | vdaccfg_write(sd, VDAC_CONFIG_SD_V2); | 229 | vdaccfg_write(sd, VDAC_CONFIG_SD_V2); |
@@ -238,7 +254,6 @@ static int venc_set_ntsc(struct v4l2_subdev *sd) | |||
238 | static int venc_set_pal(struct v4l2_subdev *sd) | 254 | static int venc_set_pal(struct v4l2_subdev *sd) |
239 | { | 255 | { |
240 | struct venc_state *venc = to_state(sd); | 256 | struct venc_state *venc = to_state(sd); |
241 | struct venc_platform_data *pdata = venc->pdata; | ||
242 | 257 | ||
243 | v4l2_dbg(debug, 2, sd, "venc_set_pal\n"); | 258 | v4l2_dbg(debug, 2, sd, "venc_set_pal\n"); |
244 | 259 | ||
@@ -249,11 +264,11 @@ static int venc_set_pal(struct v4l2_subdev *sd) | |||
249 | 264 | ||
250 | venc_enabledigitaloutput(sd, 0); | 265 | venc_enabledigitaloutput(sd, 0); |
251 | 266 | ||
252 | if (pdata->venc_type == VPBE_VERSION_3) { | 267 | if (venc->venc_type == VPBE_VERSION_3) { |
253 | venc_write(sd, VENC_CLKCTL, 0x1); | 268 | venc_write(sd, VENC_CLKCTL, 0x1); |
254 | venc_write(sd, VENC_VIDCTL, 0); | 269 | venc_write(sd, VENC_VIDCTL, 0); |
255 | vdaccfg_write(sd, VDAC_CONFIG_SD_V3); | 270 | vdaccfg_write(sd, VDAC_CONFIG_SD_V3); |
256 | } else if (pdata->venc_type == VPBE_VERSION_2) { | 271 | } else if (venc->venc_type == VPBE_VERSION_2) { |
257 | venc_write(sd, VENC_CLKCTL, 0x1); | 272 | venc_write(sd, VENC_CLKCTL, 0x1); |
258 | venc_write(sd, VENC_VIDCTL, 0); | 273 | venc_write(sd, VENC_VIDCTL, 0); |
259 | vdaccfg_write(sd, VDAC_CONFIG_SD_V2); | 274 | vdaccfg_write(sd, VDAC_CONFIG_SD_V2); |
@@ -293,8 +308,8 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd) | |||
293 | struct venc_platform_data *pdata = venc->pdata; | 308 | struct venc_platform_data *pdata = venc->pdata; |
294 | 309 | ||
295 | v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n"); | 310 | v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n"); |
296 | if ((pdata->venc_type != VPBE_VERSION_1) && | 311 | if (venc->venc_type != VPBE_VERSION_1 && |
297 | (pdata->venc_type != VPBE_VERSION_2)) | 312 | venc->venc_type != VPBE_VERSION_2) |
298 | return -EINVAL; | 313 | return -EINVAL; |
299 | 314 | ||
300 | /* Setup clock at VPSS & VENC for SD */ | 315 | /* Setup clock at VPSS & VENC for SD */ |
@@ -303,12 +318,12 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd) | |||
303 | 318 | ||
304 | venc_enabledigitaloutput(sd, 0); | 319 | venc_enabledigitaloutput(sd, 0); |
305 | 320 | ||
306 | if (pdata->venc_type == VPBE_VERSION_2) | 321 | if (venc->venc_type == VPBE_VERSION_2) |
307 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); | 322 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); |
308 | venc_write(sd, VENC_OSDCLK0, 0); | 323 | venc_write(sd, VENC_OSDCLK0, 0); |
309 | venc_write(sd, VENC_OSDCLK1, 1); | 324 | venc_write(sd, VENC_OSDCLK1, 1); |
310 | 325 | ||
311 | if (pdata->venc_type == VPBE_VERSION_1) { | 326 | if (venc->venc_type == VPBE_VERSION_1) { |
312 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ, | 327 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ, |
313 | VENC_VDPRO_DAFRQ); | 328 | VENC_VDPRO_DAFRQ); |
314 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS, | 329 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS, |
@@ -341,8 +356,8 @@ static int venc_set_576p50(struct v4l2_subdev *sd) | |||
341 | 356 | ||
342 | v4l2_dbg(debug, 2, sd, "venc_set_576p50\n"); | 357 | v4l2_dbg(debug, 2, sd, "venc_set_576p50\n"); |
343 | 358 | ||
344 | if ((pdata->venc_type != VPBE_VERSION_1) && | 359 | if (venc->venc_type != VPBE_VERSION_1 && |
345 | (pdata->venc_type != VPBE_VERSION_2)) | 360 | venc->venc_type != VPBE_VERSION_2) |
346 | return -EINVAL; | 361 | return -EINVAL; |
347 | /* Setup clock at VPSS & VENC for SD */ | 362 | /* Setup clock at VPSS & VENC for SD */ |
348 | if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0) | 363 | if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0) |
@@ -350,13 +365,13 @@ static int venc_set_576p50(struct v4l2_subdev *sd) | |||
350 | 365 | ||
351 | venc_enabledigitaloutput(sd, 0); | 366 | venc_enabledigitaloutput(sd, 0); |
352 | 367 | ||
353 | if (pdata->venc_type == VPBE_VERSION_2) | 368 | if (venc->venc_type == VPBE_VERSION_2) |
354 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); | 369 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); |
355 | 370 | ||
356 | venc_write(sd, VENC_OSDCLK0, 0); | 371 | venc_write(sd, VENC_OSDCLK0, 0); |
357 | venc_write(sd, VENC_OSDCLK1, 1); | 372 | venc_write(sd, VENC_OSDCLK1, 1); |
358 | 373 | ||
359 | if (pdata->venc_type == VPBE_VERSION_1) { | 374 | if (venc->venc_type == VPBE_VERSION_1) { |
360 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ, | 375 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ, |
361 | VENC_VDPRO_DAFRQ); | 376 | VENC_VDPRO_DAFRQ); |
362 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS, | 377 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS, |
@@ -460,14 +475,14 @@ static int venc_s_dv_timings(struct v4l2_subdev *sd, | |||
460 | else if (height == 480) | 475 | else if (height == 480) |
461 | return venc_set_480p59_94(sd); | 476 | return venc_set_480p59_94(sd); |
462 | else if ((height == 720) && | 477 | else if ((height == 720) && |
463 | (venc->pdata->venc_type == VPBE_VERSION_2)) { | 478 | (venc->venc_type == VPBE_VERSION_2)) { |
464 | /* TBD setup internal 720p mode here */ | 479 | /* TBD setup internal 720p mode here */ |
465 | ret = venc_set_720p60_internal(sd); | 480 | ret = venc_set_720p60_internal(sd); |
466 | /* for DM365 VPBE, there is DAC inside */ | 481 | /* for DM365 VPBE, there is DAC inside */ |
467 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); | 482 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); |
468 | return ret; | 483 | return ret; |
469 | } else if ((height == 1080) && | 484 | } else if ((height == 1080) && |
470 | (venc->pdata->venc_type == VPBE_VERSION_2)) { | 485 | (venc->venc_type == VPBE_VERSION_2)) { |
471 | /* TBD setup internal 1080i mode here */ | 486 | /* TBD setup internal 1080i mode here */ |
472 | ret = venc_set_1080i30_internal(sd); | 487 | ret = venc_set_1080i30_internal(sd); |
473 | /* for DM365 VPBE, there is DAC inside */ | 488 | /* for DM365 VPBE, there is DAC inside */ |
@@ -556,7 +571,7 @@ static int venc_device_get(struct device *dev, void *data) | |||
556 | struct platform_device *pdev = to_platform_device(dev); | 571 | struct platform_device *pdev = to_platform_device(dev); |
557 | struct venc_state **venc = data; | 572 | struct venc_state **venc = data; |
558 | 573 | ||
559 | if (strcmp(MODULE_NAME, pdev->name) == 0) | 574 | if (strstr(pdev->name, "vpbe-venc") != NULL) |
560 | *venc = platform_get_drvdata(pdev); | 575 | *venc = platform_get_drvdata(pdev); |
561 | 576 | ||
562 | return 0; | 577 | return 0; |
@@ -593,6 +608,7 @@ EXPORT_SYMBOL(venc_sub_dev_init); | |||
593 | 608 | ||
594 | static int venc_probe(struct platform_device *pdev) | 609 | static int venc_probe(struct platform_device *pdev) |
595 | { | 610 | { |
611 | const struct platform_device_id *pdev_id; | ||
596 | struct venc_state *venc; | 612 | struct venc_state *venc; |
597 | struct resource *res; | 613 | struct resource *res; |
598 | int ret; | 614 | int ret; |
@@ -601,6 +617,12 @@ static int venc_probe(struct platform_device *pdev) | |||
601 | if (venc == NULL) | 617 | if (venc == NULL) |
602 | return -ENOMEM; | 618 | return -ENOMEM; |
603 | 619 | ||
620 | pdev_id = platform_get_device_id(pdev); | ||
621 | if (!pdev_id) { | ||
622 | ret = -EINVAL; | ||
623 | goto free_mem; | ||
624 | } | ||
625 | venc->venc_type = pdev_id->driver_data; | ||
604 | venc->pdev = &pdev->dev; | 626 | venc->pdev = &pdev->dev; |
605 | venc->pdata = pdev->dev.platform_data; | 627 | venc->pdata = pdev->dev.platform_data; |
606 | if (NULL == venc->pdata) { | 628 | if (NULL == venc->pdata) { |
@@ -630,7 +652,7 @@ static int venc_probe(struct platform_device *pdev) | |||
630 | goto release_venc_mem_region; | 652 | goto release_venc_mem_region; |
631 | } | 653 | } |
632 | 654 | ||
633 | if (venc->pdata->venc_type != VPBE_VERSION_1) { | 655 | if (venc->venc_type != VPBE_VERSION_1) { |
634 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 656 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
635 | if (!res) { | 657 | if (!res) { |
636 | dev_err(venc->pdev, | 658 | dev_err(venc->pdev, |
@@ -681,7 +703,7 @@ static int venc_remove(struct platform_device *pdev) | |||
681 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 703 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
682 | iounmap((void *)venc->venc_base); | 704 | iounmap((void *)venc->venc_base); |
683 | release_mem_region(res->start, resource_size(res)); | 705 | release_mem_region(res->start, resource_size(res)); |
684 | if (venc->pdata->venc_type != VPBE_VERSION_1) { | 706 | if (venc->venc_type != VPBE_VERSION_1) { |
685 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 707 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
686 | iounmap((void *)venc->vdaccfg_reg); | 708 | iounmap((void *)venc->vdaccfg_reg); |
687 | release_mem_region(res->start, resource_size(res)); | 709 | release_mem_region(res->start, resource_size(res)); |
@@ -698,6 +720,7 @@ static struct platform_driver venc_driver = { | |||
698 | .name = MODULE_NAME, | 720 | .name = MODULE_NAME, |
699 | .owner = THIS_MODULE, | 721 | .owner = THIS_MODULE, |
700 | }, | 722 | }, |
723 | .id_table = vpbe_venc_devtype | ||
701 | }; | 724 | }; |
702 | 725 | ||
703 | module_platform_driver(venc_driver); | 726 | module_platform_driver(venc_driver); |
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index be9d3e1b4868..28d019da4c01 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c | |||
@@ -560,10 +560,7 @@ static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev) | |||
560 | 560 | ||
561 | static void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev) | 561 | static void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev) |
562 | { | 562 | { |
563 | struct timeval timevalue; | 563 | v4l2_get_timestamp(&vpfe_dev->cur_frm->ts); |
564 | |||
565 | do_gettimeofday(&timevalue); | ||
566 | vpfe_dev->cur_frm->ts = timevalue; | ||
567 | vpfe_dev->cur_frm->state = VIDEOBUF_DONE; | 564 | vpfe_dev->cur_frm->state = VIDEOBUF_DONE; |
568 | vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage; | 565 | vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage; |
569 | wake_up_interruptible(&vpfe_dev->cur_frm->done); | 566 | wake_up_interruptible(&vpfe_dev->cur_frm->done); |
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index a409ccefb380..5892d2bc8eee 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c | |||
@@ -411,7 +411,7 @@ static struct vb2_ops video_qops = { | |||
411 | */ | 411 | */ |
412 | static void vpif_process_buffer_complete(struct common_obj *common) | 412 | static void vpif_process_buffer_complete(struct common_obj *common) |
413 | { | 413 | { |
414 | do_gettimeofday(&common->cur_frm->vb.v4l2_buf.timestamp); | 414 | v4l2_get_timestamp(&common->cur_frm->vb.v4l2_buf.timestamp); |
415 | vb2_buffer_done(&common->cur_frm->vb, | 415 | vb2_buffer_done(&common->cur_frm->vb, |
416 | VB2_BUF_STATE_DONE); | 416 | VB2_BUF_STATE_DONE); |
417 | /* Make curFrm pointing to nextFrm */ | 417 | /* Make curFrm pointing to nextFrm */ |
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 9f2b603be9c9..dd249c96126d 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c | |||
@@ -402,7 +402,7 @@ static void process_interlaced_mode(int fid, struct common_obj *common) | |||
402 | /* one frame is displayed If next frame is | 402 | /* one frame is displayed If next frame is |
403 | * available, release cur_frm and move on */ | 403 | * available, release cur_frm and move on */ |
404 | /* Copy frame display time */ | 404 | /* Copy frame display time */ |
405 | do_gettimeofday(&common->cur_frm->vb.v4l2_buf.timestamp); | 405 | v4l2_get_timestamp(&common->cur_frm->vb.v4l2_buf.timestamp); |
406 | /* Change status of the cur_frm */ | 406 | /* Change status of the cur_frm */ |
407 | vb2_buffer_done(&common->cur_frm->vb, | 407 | vb2_buffer_done(&common->cur_frm->vb, |
408 | VB2_BUF_STATE_DONE); | 408 | VB2_BUF_STATE_DONE); |
@@ -462,8 +462,8 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) | |||
462 | if (!channel_first_int[i][channel_id]) { | 462 | if (!channel_first_int[i][channel_id]) { |
463 | /* Mark status of the cur_frm to | 463 | /* Mark status of the cur_frm to |
464 | * done and unlock semaphore on it */ | 464 | * done and unlock semaphore on it */ |
465 | do_gettimeofday(&common->cur_frm->vb. | 465 | v4l2_get_timestamp(&common->cur_frm->vb. |
466 | v4l2_buf.timestamp); | 466 | v4l2_buf.timestamp); |
467 | vb2_buffer_done(&common->cur_frm->vb, | 467 | vb2_buffer_done(&common->cur_frm->vb, |
468 | VB2_BUF_STATE_DONE); | 468 | VB2_BUF_STATE_DONE); |
469 | /* Make cur_frm pointing to next_frm */ | 469 | /* Make cur_frm pointing to next_frm */ |
diff --git a/drivers/media/platform/davinci/vpss.c b/drivers/media/platform/davinci/vpss.c index 684e815a81b6..a19c552232d1 100644 --- a/drivers/media/platform/davinci/vpss.c +++ b/drivers/media/platform/davinci/vpss.c | |||
@@ -50,13 +50,29 @@ MODULE_AUTHOR("Texas Instruments"); | |||
50 | /* VENCINT - vpss_int8 */ | 50 | /* VENCINT - vpss_int8 */ |
51 | #define DM355_VPSSBL_EVTSEL_DEFAULT 0x4 | 51 | #define DM355_VPSSBL_EVTSEL_DEFAULT 0x4 |
52 | 52 | ||
53 | #define DM365_ISP5_PCCR 0x04 | 53 | #define DM365_ISP5_PCCR 0x04 |
54 | #define DM365_ISP5_PCCR_BL_CLK_ENABLE BIT(0) | ||
55 | #define DM365_ISP5_PCCR_ISIF_CLK_ENABLE BIT(1) | ||
56 | #define DM365_ISP5_PCCR_H3A_CLK_ENABLE BIT(2) | ||
57 | #define DM365_ISP5_PCCR_RSZ_CLK_ENABLE BIT(3) | ||
58 | #define DM365_ISP5_PCCR_IPIPE_CLK_ENABLE BIT(4) | ||
59 | #define DM365_ISP5_PCCR_IPIPEIF_CLK_ENABLE BIT(5) | ||
60 | #define DM365_ISP5_PCCR_RSV BIT(6) | ||
61 | |||
62 | #define DM365_ISP5_BCR 0x08 | ||
63 | #define DM365_ISP5_BCR_ISIF_OUT_ENABLE BIT(1) | ||
64 | |||
54 | #define DM365_ISP5_INTSEL1 0x10 | 65 | #define DM365_ISP5_INTSEL1 0x10 |
55 | #define DM365_ISP5_INTSEL2 0x14 | 66 | #define DM365_ISP5_INTSEL2 0x14 |
56 | #define DM365_ISP5_INTSEL3 0x18 | 67 | #define DM365_ISP5_INTSEL3 0x18 |
57 | #define DM365_ISP5_CCDCMUX 0x20 | 68 | #define DM365_ISP5_CCDCMUX 0x20 |
58 | #define DM365_ISP5_PG_FRAME_SIZE 0x28 | 69 | #define DM365_ISP5_PG_FRAME_SIZE 0x28 |
59 | #define DM365_VPBE_CLK_CTRL 0x00 | 70 | #define DM365_VPBE_CLK_CTRL 0x00 |
71 | |||
72 | #define VPSS_CLK_CTRL 0x01c40044 | ||
73 | #define VPSS_CLK_CTRL_VENCCLKEN BIT(3) | ||
74 | #define VPSS_CLK_CTRL_DACCLKEN BIT(4) | ||
75 | |||
60 | /* | 76 | /* |
61 | * vpss interrupts. VDINT0 - vpss_int0, VDINT1 - vpss_int1, | 77 | * vpss interrupts. VDINT0 - vpss_int0, VDINT1 - vpss_int1, |
62 | * AF - vpss_int3 | 78 | * AF - vpss_int3 |
@@ -94,12 +110,19 @@ struct vpss_hw_ops { | |||
94 | void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel); | 110 | void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel); |
95 | /* clear wbl overflow bit */ | 111 | /* clear wbl overflow bit */ |
96 | int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel); | 112 | int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel); |
113 | /* set sync polarity */ | ||
114 | void (*set_sync_pol)(struct vpss_sync_pol); | ||
115 | /* set the PG_FRAME_SIZE register*/ | ||
116 | void (*set_pg_frame_size)(struct vpss_pg_frame_size); | ||
117 | /* check and clear interrupt if occured */ | ||
118 | int (*dma_complete_interrupt)(void); | ||
97 | }; | 119 | }; |
98 | 120 | ||
99 | /* vpss configuration */ | 121 | /* vpss configuration */ |
100 | struct vpss_oper_config { | 122 | struct vpss_oper_config { |
101 | __iomem void *vpss_regs_base0; | 123 | __iomem void *vpss_regs_base0; |
102 | __iomem void *vpss_regs_base1; | 124 | __iomem void *vpss_regs_base1; |
125 | resource_size_t *vpss_regs_base2; | ||
103 | enum vpss_platform_type platform; | 126 | enum vpss_platform_type platform; |
104 | spinlock_t vpss_lock; | 127 | spinlock_t vpss_lock; |
105 | struct vpss_hw_ops hw_ops; | 128 | struct vpss_hw_ops hw_ops; |
@@ -157,6 +180,14 @@ static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) | |||
157 | bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX); | 180 | bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX); |
158 | } | 181 | } |
159 | 182 | ||
183 | int vpss_dma_complete_interrupt(void) | ||
184 | { | ||
185 | if (!oper_cfg.hw_ops.dma_complete_interrupt) | ||
186 | return 2; | ||
187 | return oper_cfg.hw_ops.dma_complete_interrupt(); | ||
188 | } | ||
189 | EXPORT_SYMBOL(vpss_dma_complete_interrupt); | ||
190 | |||
160 | int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) | 191 | int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) |
161 | { | 192 | { |
162 | if (!oper_cfg.hw_ops.select_ccdc_source) | 193 | if (!oper_cfg.hw_ops.select_ccdc_source) |
@@ -182,6 +213,15 @@ static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) | |||
182 | return 0; | 213 | return 0; |
183 | } | 214 | } |
184 | 215 | ||
216 | void vpss_set_sync_pol(struct vpss_sync_pol sync) | ||
217 | { | ||
218 | if (!oper_cfg.hw_ops.set_sync_pol) | ||
219 | return; | ||
220 | |||
221 | oper_cfg.hw_ops.set_sync_pol(sync); | ||
222 | } | ||
223 | EXPORT_SYMBOL(vpss_set_sync_pol); | ||
224 | |||
185 | int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) | 225 | int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) |
186 | { | 226 | { |
187 | if (!oper_cfg.hw_ops.clear_wbl_overflow) | 227 | if (!oper_cfg.hw_ops.clear_wbl_overflow) |
@@ -347,6 +387,15 @@ void dm365_vpss_set_sync_pol(struct vpss_sync_pol sync) | |||
347 | } | 387 | } |
348 | EXPORT_SYMBOL(dm365_vpss_set_sync_pol); | 388 | EXPORT_SYMBOL(dm365_vpss_set_sync_pol); |
349 | 389 | ||
390 | void vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size) | ||
391 | { | ||
392 | if (!oper_cfg.hw_ops.set_pg_frame_size) | ||
393 | return; | ||
394 | |||
395 | oper_cfg.hw_ops.set_pg_frame_size(frame_size); | ||
396 | } | ||
397 | EXPORT_SYMBOL(vpss_set_pg_frame_size); | ||
398 | |||
350 | void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size) | 399 | void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size) |
351 | { | 400 | { |
352 | int current_reg = ((frame_size.hlpfr >> 1) - 1) << 16; | 401 | int current_reg = ((frame_size.hlpfr >> 1) - 1) << 16; |
@@ -425,6 +474,16 @@ static int vpss_probe(struct platform_device *pdev) | |||
425 | oper_cfg.hw_ops.enable_clock = dm365_enable_clock; | 474 | oper_cfg.hw_ops.enable_clock = dm365_enable_clock; |
426 | oper_cfg.hw_ops.select_ccdc_source = dm365_select_ccdc_source; | 475 | oper_cfg.hw_ops.select_ccdc_source = dm365_select_ccdc_source; |
427 | /* Setup vpss interrupts */ | 476 | /* Setup vpss interrupts */ |
477 | isp5_write((isp5_read(DM365_ISP5_PCCR) | | ||
478 | DM365_ISP5_PCCR_BL_CLK_ENABLE | | ||
479 | DM365_ISP5_PCCR_ISIF_CLK_ENABLE | | ||
480 | DM365_ISP5_PCCR_H3A_CLK_ENABLE | | ||
481 | DM365_ISP5_PCCR_RSZ_CLK_ENABLE | | ||
482 | DM365_ISP5_PCCR_IPIPE_CLK_ENABLE | | ||
483 | DM365_ISP5_PCCR_IPIPEIF_CLK_ENABLE | | ||
484 | DM365_ISP5_PCCR_RSV), DM365_ISP5_PCCR); | ||
485 | isp5_write((isp5_read(DM365_ISP5_BCR) | | ||
486 | DM365_ISP5_BCR_ISIF_OUT_ENABLE), DM365_ISP5_BCR); | ||
428 | isp5_write(DM365_ISP5_INTSEL1_DEFAULT, DM365_ISP5_INTSEL1); | 487 | isp5_write(DM365_ISP5_INTSEL1_DEFAULT, DM365_ISP5_INTSEL1); |
429 | isp5_write(DM365_ISP5_INTSEL2_DEFAULT, DM365_ISP5_INTSEL2); | 488 | isp5_write(DM365_ISP5_INTSEL2_DEFAULT, DM365_ISP5_INTSEL2); |
430 | isp5_write(DM365_ISP5_INTSEL3_DEFAULT, DM365_ISP5_INTSEL3); | 489 | isp5_write(DM365_ISP5_INTSEL3_DEFAULT, DM365_ISP5_INTSEL3); |
@@ -470,11 +529,20 @@ static struct platform_driver vpss_driver = { | |||
470 | 529 | ||
471 | static void vpss_exit(void) | 530 | static void vpss_exit(void) |
472 | { | 531 | { |
532 | iounmap(oper_cfg.vpss_regs_base2); | ||
533 | release_mem_region(VPSS_CLK_CTRL, 4); | ||
473 | platform_driver_unregister(&vpss_driver); | 534 | platform_driver_unregister(&vpss_driver); |
474 | } | 535 | } |
475 | 536 | ||
476 | static int __init vpss_init(void) | 537 | static int __init vpss_init(void) |
477 | { | 538 | { |
539 | if (!request_mem_region(VPSS_CLK_CTRL, 4, "vpss_clock_control")) | ||
540 | return -EBUSY; | ||
541 | |||
542 | oper_cfg.vpss_regs_base2 = ioremap(VPSS_CLK_CTRL, 4); | ||
543 | writel(VPSS_CLK_CTRL_VENCCLKEN | | ||
544 | VPSS_CLK_CTRL_DACCLKEN, oper_cfg.vpss_regs_base2); | ||
545 | |||
478 | return platform_driver_register(&vpss_driver); | 546 | return platform_driver_register(&vpss_driver); |
479 | } | 547 | } |
480 | subsys_initcall(vpss_init); | 548 | subsys_initcall(vpss_init); |
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index c1a07133cc56..82d9f6ac12f3 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c | |||
@@ -185,6 +185,15 @@ static const struct gsc_fmt gsc_formats[] = { | |||
185 | .corder = GSC_CRCB, | 185 | .corder = GSC_CRCB, |
186 | .num_planes = 3, | 186 | .num_planes = 3, |
187 | .num_comp = 3, | 187 | .num_comp = 3, |
188 | }, { | ||
189 | .name = "YUV 4:2:0 n.c. 2p, Y/CbCr tiled", | ||
190 | .pixelformat = V4L2_PIX_FMT_NV12MT_16X16, | ||
191 | .depth = { 8, 4 }, | ||
192 | .color = GSC_YUV420, | ||
193 | .yorder = GSC_LSB_Y, | ||
194 | .corder = GSC_CBCR, | ||
195 | .num_planes = 2, | ||
196 | .num_comp = 2, | ||
188 | } | 197 | } |
189 | }; | 198 | }; |
190 | 199 | ||
@@ -935,8 +944,8 @@ static struct gsc_variant gsc_v_100_variant = { | |||
935 | .pix_max = &gsc_v_100_max, | 944 | .pix_max = &gsc_v_100_max, |
936 | .pix_min = &gsc_v_100_min, | 945 | .pix_min = &gsc_v_100_min, |
937 | .pix_align = &gsc_v_100_align, | 946 | .pix_align = &gsc_v_100_align, |
938 | .in_buf_cnt = 8, | 947 | .in_buf_cnt = 32, |
939 | .out_buf_cnt = 16, | 948 | .out_buf_cnt = 32, |
940 | .sc_up_max = 8, | 949 | .sc_up_max = 8, |
941 | .sc_down_max = 16, | 950 | .sc_down_max = 16, |
942 | .poly_sc_down_max = 4, | 951 | .poly_sc_down_max = 4, |
@@ -993,12 +1002,8 @@ static void *gsc_get_drv_data(struct platform_device *pdev) | |||
993 | 1002 | ||
994 | static void gsc_clk_put(struct gsc_dev *gsc) | 1003 | static void gsc_clk_put(struct gsc_dev *gsc) |
995 | { | 1004 | { |
996 | if (IS_ERR_OR_NULL(gsc->clock)) | 1005 | if (!IS_ERR(gsc->clock)) |
997 | return; | 1006 | clk_unprepare(gsc->clock); |
998 | |||
999 | clk_unprepare(gsc->clock); | ||
1000 | clk_put(gsc->clock); | ||
1001 | gsc->clock = NULL; | ||
1002 | } | 1007 | } |
1003 | 1008 | ||
1004 | static int gsc_clk_get(struct gsc_dev *gsc) | 1009 | static int gsc_clk_get(struct gsc_dev *gsc) |
@@ -1007,27 +1012,22 @@ static int gsc_clk_get(struct gsc_dev *gsc) | |||
1007 | 1012 | ||
1008 | dev_dbg(&gsc->pdev->dev, "gsc_clk_get Called\n"); | 1013 | dev_dbg(&gsc->pdev->dev, "gsc_clk_get Called\n"); |
1009 | 1014 | ||
1010 | gsc->clock = clk_get(&gsc->pdev->dev, GSC_CLOCK_GATE_NAME); | 1015 | gsc->clock = devm_clk_get(&gsc->pdev->dev, GSC_CLOCK_GATE_NAME); |
1011 | if (IS_ERR(gsc->clock)) | 1016 | if (IS_ERR(gsc->clock)) { |
1012 | goto err_print; | 1017 | dev_err(&gsc->pdev->dev, "failed to get clock~~~: %s\n", |
1018 | GSC_CLOCK_GATE_NAME); | ||
1019 | return PTR_ERR(gsc->clock); | ||
1020 | } | ||
1013 | 1021 | ||
1014 | ret = clk_prepare(gsc->clock); | 1022 | ret = clk_prepare(gsc->clock); |
1015 | if (ret < 0) { | 1023 | if (ret < 0) { |
1016 | clk_put(gsc->clock); | 1024 | dev_err(&gsc->pdev->dev, "clock prepare failed for clock: %s\n", |
1017 | gsc->clock = NULL; | 1025 | GSC_CLOCK_GATE_NAME); |
1018 | goto err; | 1026 | gsc->clock = ERR_PTR(-EINVAL); |
1027 | return ret; | ||
1019 | } | 1028 | } |
1020 | 1029 | ||
1021 | return 0; | 1030 | return 0; |
1022 | |||
1023 | err: | ||
1024 | dev_err(&gsc->pdev->dev, "clock prepare failed for clock: %s\n", | ||
1025 | GSC_CLOCK_GATE_NAME); | ||
1026 | gsc_clk_put(gsc); | ||
1027 | err_print: | ||
1028 | dev_err(&gsc->pdev->dev, "failed to get clock~~~: %s\n", | ||
1029 | GSC_CLOCK_GATE_NAME); | ||
1030 | return -ENXIO; | ||
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | static int gsc_m2m_suspend(struct gsc_dev *gsc) | 1033 | static int gsc_m2m_suspend(struct gsc_dev *gsc) |
@@ -1096,6 +1096,7 @@ static int gsc_probe(struct platform_device *pdev) | |||
1096 | init_waitqueue_head(&gsc->irq_queue); | 1096 | init_waitqueue_head(&gsc->irq_queue); |
1097 | spin_lock_init(&gsc->slock); | 1097 | spin_lock_init(&gsc->slock); |
1098 | mutex_init(&gsc->lock); | 1098 | mutex_init(&gsc->lock); |
1099 | gsc->clock = ERR_PTR(-EINVAL); | ||
1099 | 1100 | ||
1100 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1101 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1101 | gsc->regs = devm_ioremap_resource(dev, res); | 1102 | gsc->regs = devm_ioremap_resource(dev, res); |
@@ -1157,6 +1158,7 @@ static int gsc_remove(struct platform_device *pdev) | |||
1157 | 1158 | ||
1158 | vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); | 1159 | vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); |
1159 | pm_runtime_disable(&pdev->dev); | 1160 | pm_runtime_disable(&pdev->dev); |
1161 | gsc_clk_put(gsc); | ||
1160 | 1162 | ||
1161 | dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name); | 1163 | dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name); |
1162 | return 0; | 1164 | return 0; |
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h index 5f157efd24f0..cc19bba09bd1 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.h +++ b/drivers/media/platform/exynos-gsc/gsc-core.h | |||
@@ -427,6 +427,11 @@ static inline void gsc_ctx_state_lock_clear(u32 state, struct gsc_ctx *ctx) | |||
427 | spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags); | 427 | spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags); |
428 | } | 428 | } |
429 | 429 | ||
430 | static inline int is_tiled(const struct gsc_fmt *fmt) | ||
431 | { | ||
432 | return fmt->pixelformat == V4L2_PIX_FMT_NV12MT_16X16; | ||
433 | } | ||
434 | |||
430 | static inline void gsc_hw_enable_control(struct gsc_dev *dev, bool on) | 435 | static inline void gsc_hw_enable_control(struct gsc_dev *dev, bool on) |
431 | { | 436 | { |
432 | u32 cfg = readl(dev->regs + GSC_ENABLE); | 437 | u32 cfg = readl(dev->regs + GSC_ENABLE); |
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index c267c57c76fd..386c0a7a3a52 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c | |||
@@ -99,22 +99,28 @@ static void gsc_m2m_job_abort(void *priv) | |||
99 | gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); | 99 | gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); |
100 | } | 100 | } |
101 | 101 | ||
102 | static int gsc_fill_addr(struct gsc_ctx *ctx) | 102 | static int gsc_get_bufs(struct gsc_ctx *ctx) |
103 | { | 103 | { |
104 | struct gsc_frame *s_frame, *d_frame; | 104 | struct gsc_frame *s_frame, *d_frame; |
105 | struct vb2_buffer *vb = NULL; | 105 | struct vb2_buffer *src_vb, *dst_vb; |
106 | int ret; | 106 | int ret; |
107 | 107 | ||
108 | s_frame = &ctx->s_frame; | 108 | s_frame = &ctx->s_frame; |
109 | d_frame = &ctx->d_frame; | 109 | d_frame = &ctx->d_frame; |
110 | 110 | ||
111 | vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | 111 | src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); |
112 | ret = gsc_prepare_addr(ctx, vb, s_frame, &s_frame->addr); | 112 | ret = gsc_prepare_addr(ctx, src_vb, s_frame, &s_frame->addr); |
113 | if (ret) | 113 | if (ret) |
114 | return ret; | 114 | return ret; |
115 | 115 | ||
116 | vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | 116 | dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); |
117 | return gsc_prepare_addr(ctx, vb, d_frame, &d_frame->addr); | 117 | ret = gsc_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr); |
118 | if (ret) | ||
119 | return ret; | ||
120 | |||
121 | dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp; | ||
122 | |||
123 | return 0; | ||
118 | } | 124 | } |
119 | 125 | ||
120 | static void gsc_m2m_device_run(void *priv) | 126 | static void gsc_m2m_device_run(void *priv) |
@@ -148,7 +154,7 @@ static void gsc_m2m_device_run(void *priv) | |||
148 | goto put_device; | 154 | goto put_device; |
149 | } | 155 | } |
150 | 156 | ||
151 | ret = gsc_fill_addr(ctx); | 157 | ret = gsc_get_bufs(ctx); |
152 | if (ret) { | 158 | if (ret) { |
153 | pr_err("Wrong address"); | 159 | pr_err("Wrong address"); |
154 | goto put_device; | 160 | goto put_device; |
@@ -367,6 +373,13 @@ static int gsc_m2m_reqbufs(struct file *file, void *fh, | |||
367 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); | 373 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); |
368 | } | 374 | } |
369 | 375 | ||
376 | static int gsc_m2m_expbuf(struct file *file, void *fh, | ||
377 | struct v4l2_exportbuffer *eb) | ||
378 | { | ||
379 | struct gsc_ctx *ctx = fh_to_ctx(fh); | ||
380 | return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); | ||
381 | } | ||
382 | |||
370 | static int gsc_m2m_querybuf(struct file *file, void *fh, | 383 | static int gsc_m2m_querybuf(struct file *file, void *fh, |
371 | struct v4l2_buffer *buf) | 384 | struct v4l2_buffer *buf) |
372 | { | 385 | { |
@@ -548,6 +561,7 @@ static const struct v4l2_ioctl_ops gsc_m2m_ioctl_ops = { | |||
548 | .vidioc_s_fmt_vid_cap_mplane = gsc_m2m_s_fmt_mplane, | 561 | .vidioc_s_fmt_vid_cap_mplane = gsc_m2m_s_fmt_mplane, |
549 | .vidioc_s_fmt_vid_out_mplane = gsc_m2m_s_fmt_mplane, | 562 | .vidioc_s_fmt_vid_out_mplane = gsc_m2m_s_fmt_mplane, |
550 | .vidioc_reqbufs = gsc_m2m_reqbufs, | 563 | .vidioc_reqbufs = gsc_m2m_reqbufs, |
564 | .vidioc_expbuf = gsc_m2m_expbuf, | ||
551 | .vidioc_querybuf = gsc_m2m_querybuf, | 565 | .vidioc_querybuf = gsc_m2m_querybuf, |
552 | .vidioc_qbuf = gsc_m2m_qbuf, | 566 | .vidioc_qbuf = gsc_m2m_qbuf, |
553 | .vidioc_dqbuf = gsc_m2m_dqbuf, | 567 | .vidioc_dqbuf = gsc_m2m_dqbuf, |
@@ -565,7 +579,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, | |||
565 | 579 | ||
566 | memset(src_vq, 0, sizeof(*src_vq)); | 580 | memset(src_vq, 0, sizeof(*src_vq)); |
567 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 581 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
568 | src_vq->io_modes = VB2_MMAP | VB2_USERPTR; | 582 | src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; |
569 | src_vq->drv_priv = ctx; | 583 | src_vq->drv_priv = ctx; |
570 | src_vq->ops = &gsc_m2m_qops; | 584 | src_vq->ops = &gsc_m2m_qops; |
571 | src_vq->mem_ops = &vb2_dma_contig_memops; | 585 | src_vq->mem_ops = &vb2_dma_contig_memops; |
@@ -577,7 +591,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, | |||
577 | 591 | ||
578 | memset(dst_vq, 0, sizeof(*dst_vq)); | 592 | memset(dst_vq, 0, sizeof(*dst_vq)); |
579 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 593 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
580 | dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; | 594 | dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; |
581 | dst_vq->drv_priv = ctx; | 595 | dst_vq->drv_priv = ctx; |
582 | dst_vq->ops = &gsc_m2m_qops; | 596 | dst_vq->ops = &gsc_m2m_qops; |
583 | dst_vq->mem_ops = &vb2_dma_contig_memops; | 597 | dst_vq->mem_ops = &vb2_dma_contig_memops; |
@@ -597,7 +611,7 @@ static int gsc_m2m_open(struct file *file) | |||
597 | if (mutex_lock_interruptible(&gsc->lock)) | 611 | if (mutex_lock_interruptible(&gsc->lock)) |
598 | return -ERESTARTSYS; | 612 | return -ERESTARTSYS; |
599 | 613 | ||
600 | ctx = kzalloc(sizeof (*ctx), GFP_KERNEL); | 614 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
601 | if (!ctx) { | 615 | if (!ctx) { |
602 | ret = -ENOMEM; | 616 | ret = -ENOMEM; |
603 | goto unlock; | 617 | goto unlock; |
diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.c b/drivers/media/platform/exynos-gsc/gsc-regs.c index 0146b354dc22..6f5b5a486cf3 100644 --- a/drivers/media/platform/exynos-gsc/gsc-regs.c +++ b/drivers/media/platform/exynos-gsc/gsc-regs.c | |||
@@ -214,6 +214,9 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) | |||
214 | break; | 214 | break; |
215 | } | 215 | } |
216 | 216 | ||
217 | if (is_tiled(frame->fmt)) | ||
218 | cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE; | ||
219 | |||
217 | writel(cfg, dev->regs + GSC_IN_CON); | 220 | writel(cfg, dev->regs + GSC_IN_CON); |
218 | } | 221 | } |
219 | 222 | ||
@@ -334,6 +337,9 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) | |||
334 | break; | 337 | break; |
335 | } | 338 | } |
336 | 339 | ||
340 | if (is_tiled(frame->fmt)) | ||
341 | cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE; | ||
342 | |||
337 | end_set: | 343 | end_set: |
338 | writel(cfg, dev->regs + GSC_OUT_CON); | 344 | writel(cfg, dev->regs + GSC_OUT_CON); |
339 | } | 345 | } |
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index 9115a2c8d075..5f7db3f1f6f5 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c | |||
@@ -1181,7 +1181,7 @@ static void viu_capture_intr(struct viu_dev *dev, u32 status) | |||
1181 | 1181 | ||
1182 | if (waitqueue_active(&buf->vb.done)) { | 1182 | if (waitqueue_active(&buf->vb.done)) { |
1183 | list_del(&buf->vb.queue); | 1183 | list_del(&buf->vb.queue); |
1184 | do_gettimeofday(&buf->vb.ts); | 1184 | v4l2_get_timestamp(&buf->vb.ts); |
1185 | buf->vb.state = VIDEOBUF_DONE; | 1185 | buf->vb.state = VIDEOBUF_DONE; |
1186 | buf->vb.field_count++; | 1186 | buf->vb.field_count++; |
1187 | wake_up(&buf->vb.done); | 1187 | wake_up(&buf->vb.done); |
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index 05c560f2ef06..6c4db9b98989 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c | |||
@@ -28,7 +28,7 @@ MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com"); | |||
28 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
29 | MODULE_VERSION("0.0.1"); | 29 | MODULE_VERSION("0.0.1"); |
30 | 30 | ||
31 | static bool debug = true; | 31 | static bool debug; |
32 | module_param(debug, bool, 0644); | 32 | module_param(debug, bool, 0644); |
33 | 33 | ||
34 | /* Flags that indicate a format can be used for capture/output */ | 34 | /* Flags that indicate a format can be used for capture/output */ |
@@ -917,10 +917,8 @@ static int deinterlace_open(struct file *file) | |||
917 | ctx->xt = kzalloc(sizeof(struct dma_async_tx_descriptor) + | 917 | ctx->xt = kzalloc(sizeof(struct dma_async_tx_descriptor) + |
918 | sizeof(struct data_chunk), GFP_KERNEL); | 918 | sizeof(struct data_chunk), GFP_KERNEL); |
919 | if (!ctx->xt) { | 919 | if (!ctx->xt) { |
920 | int ret = PTR_ERR(ctx->xt); | ||
921 | |||
922 | kfree(ctx); | 920 | kfree(ctx); |
923 | return ret; | 921 | return -ENOMEM; |
924 | } | 922 | } |
925 | 923 | ||
926 | ctx->colorspace = V4L2_COLORSPACE_REC709; | 924 | ctx->colorspace = V4L2_COLORSPACE_REC709; |
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index ce2b7b4788d6..92a33f081852 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/videodev2.h> | 22 | #include <linux/videodev2.h> |
23 | #include <media/v4l2-device.h> | 23 | #include <media/v4l2-device.h> |
24 | #include <media/v4l2-ioctl.h> | 24 | #include <media/v4l2-ioctl.h> |
25 | #include <media/v4l2-ctrls.h> | ||
25 | #include <media/v4l2-chip-ident.h> | 26 | #include <media/v4l2-chip-ident.h> |
26 | #include <media/ov7670.h> | 27 | #include <media/ov7670.h> |
27 | #include <media/videobuf2-vmalloc.h> | 28 | #include <media/videobuf2-vmalloc.h> |
@@ -30,13 +31,6 @@ | |||
30 | 31 | ||
31 | #include "mcam-core.h" | 32 | #include "mcam-core.h" |
32 | 33 | ||
33 | /* | ||
34 | * Basic frame stats - to be deleted shortly | ||
35 | */ | ||
36 | static int frames; | ||
37 | static int singles; | ||
38 | static int delivered; | ||
39 | |||
40 | #ifdef MCAM_MODE_VMALLOC | 34 | #ifdef MCAM_MODE_VMALLOC |
41 | /* | 35 | /* |
42 | * Internal DMA buffer management. Since the controller cannot do S/G I/O, | 36 | * Internal DMA buffer management. Since the controller cannot do S/G I/O, |
@@ -367,10 +361,10 @@ static void mcam_frame_tasklet(unsigned long data) | |||
367 | if (!test_bit(bufno, &cam->flags)) | 361 | if (!test_bit(bufno, &cam->flags)) |
368 | continue; | 362 | continue; |
369 | if (list_empty(&cam->buffers)) { | 363 | if (list_empty(&cam->buffers)) { |
370 | singles++; | 364 | cam->frame_state.singles++; |
371 | break; /* Leave it valid, hope for better later */ | 365 | break; /* Leave it valid, hope for better later */ |
372 | } | 366 | } |
373 | delivered++; | 367 | cam->frame_state.delivered++; |
374 | clear_bit(bufno, &cam->flags); | 368 | clear_bit(bufno, &cam->flags); |
375 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, | 369 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, |
376 | queue); | 370 | queue); |
@@ -452,7 +446,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame) | |||
452 | mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, | 446 | mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, |
453 | vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0)); | 447 | vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0)); |
454 | set_bit(CF_SINGLE_BUFFER, &cam->flags); | 448 | set_bit(CF_SINGLE_BUFFER, &cam->flags); |
455 | singles++; | 449 | cam->frame_state.singles++; |
456 | return; | 450 | return; |
457 | } | 451 | } |
458 | /* | 452 | /* |
@@ -485,7 +479,7 @@ static void mcam_dma_contig_done(struct mcam_camera *cam, int frame) | |||
485 | struct mcam_vb_buffer *buf = cam->vb_bufs[frame]; | 479 | struct mcam_vb_buffer *buf = cam->vb_bufs[frame]; |
486 | 480 | ||
487 | if (!test_bit(CF_SINGLE_BUFFER, &cam->flags)) { | 481 | if (!test_bit(CF_SINGLE_BUFFER, &cam->flags)) { |
488 | delivered++; | 482 | cam->frame_state.delivered++; |
489 | mcam_buffer_done(cam, frame, &buf->vb_buf); | 483 | mcam_buffer_done(cam, frame, &buf->vb_buf); |
490 | } | 484 | } |
491 | mcam_set_contig_buffer(cam, frame); | 485 | mcam_set_contig_buffer(cam, frame); |
@@ -578,13 +572,13 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame) | |||
578 | */ | 572 | */ |
579 | } else { | 573 | } else { |
580 | set_bit(CF_SG_RESTART, &cam->flags); | 574 | set_bit(CF_SG_RESTART, &cam->flags); |
581 | singles++; | 575 | cam->frame_state.singles++; |
582 | cam->vb_bufs[0] = NULL; | 576 | cam->vb_bufs[0] = NULL; |
583 | } | 577 | } |
584 | /* | 578 | /* |
585 | * Now we can give the completed frame back to user space. | 579 | * Now we can give the completed frame back to user space. |
586 | */ | 580 | */ |
587 | delivered++; | 581 | cam->frame_state.delivered++; |
588 | mcam_buffer_done(cam, frame, &buf->vb_buf); | 582 | mcam_buffer_done(cam, frame, &buf->vb_buf); |
589 | } | 583 | } |
590 | 584 | ||
@@ -1232,47 +1226,6 @@ static int mcam_vidioc_dqbuf(struct file *filp, void *priv, | |||
1232 | return ret; | 1226 | return ret; |
1233 | } | 1227 | } |
1234 | 1228 | ||
1235 | |||
1236 | |||
1237 | static int mcam_vidioc_queryctrl(struct file *filp, void *priv, | ||
1238 | struct v4l2_queryctrl *qc) | ||
1239 | { | ||
1240 | struct mcam_camera *cam = priv; | ||
1241 | int ret; | ||
1242 | |||
1243 | mutex_lock(&cam->s_mutex); | ||
1244 | ret = sensor_call(cam, core, queryctrl, qc); | ||
1245 | mutex_unlock(&cam->s_mutex); | ||
1246 | return ret; | ||
1247 | } | ||
1248 | |||
1249 | |||
1250 | static int mcam_vidioc_g_ctrl(struct file *filp, void *priv, | ||
1251 | struct v4l2_control *ctrl) | ||
1252 | { | ||
1253 | struct mcam_camera *cam = priv; | ||
1254 | int ret; | ||
1255 | |||
1256 | mutex_lock(&cam->s_mutex); | ||
1257 | ret = sensor_call(cam, core, g_ctrl, ctrl); | ||
1258 | mutex_unlock(&cam->s_mutex); | ||
1259 | return ret; | ||
1260 | } | ||
1261 | |||
1262 | |||
1263 | static int mcam_vidioc_s_ctrl(struct file *filp, void *priv, | ||
1264 | struct v4l2_control *ctrl) | ||
1265 | { | ||
1266 | struct mcam_camera *cam = priv; | ||
1267 | int ret; | ||
1268 | |||
1269 | mutex_lock(&cam->s_mutex); | ||
1270 | ret = sensor_call(cam, core, s_ctrl, ctrl); | ||
1271 | mutex_unlock(&cam->s_mutex); | ||
1272 | return ret; | ||
1273 | } | ||
1274 | |||
1275 | |||
1276 | static int mcam_vidioc_querycap(struct file *file, void *priv, | 1229 | static int mcam_vidioc_querycap(struct file *file, void *priv, |
1277 | struct v4l2_capability *cap) | 1230 | struct v4l2_capability *cap) |
1278 | { | 1231 | { |
@@ -1520,9 +1473,6 @@ static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = { | |||
1520 | .vidioc_dqbuf = mcam_vidioc_dqbuf, | 1473 | .vidioc_dqbuf = mcam_vidioc_dqbuf, |
1521 | .vidioc_streamon = mcam_vidioc_streamon, | 1474 | .vidioc_streamon = mcam_vidioc_streamon, |
1522 | .vidioc_streamoff = mcam_vidioc_streamoff, | 1475 | .vidioc_streamoff = mcam_vidioc_streamoff, |
1523 | .vidioc_queryctrl = mcam_vidioc_queryctrl, | ||
1524 | .vidioc_g_ctrl = mcam_vidioc_g_ctrl, | ||
1525 | .vidioc_s_ctrl = mcam_vidioc_s_ctrl, | ||
1526 | .vidioc_g_parm = mcam_vidioc_g_parm, | 1476 | .vidioc_g_parm = mcam_vidioc_g_parm, |
1527 | .vidioc_s_parm = mcam_vidioc_s_parm, | 1477 | .vidioc_s_parm = mcam_vidioc_s_parm, |
1528 | .vidioc_enum_framesizes = mcam_vidioc_enum_framesizes, | 1478 | .vidioc_enum_framesizes = mcam_vidioc_enum_framesizes, |
@@ -1545,7 +1495,9 @@ static int mcam_v4l_open(struct file *filp) | |||
1545 | 1495 | ||
1546 | filp->private_data = cam; | 1496 | filp->private_data = cam; |
1547 | 1497 | ||
1548 | frames = singles = delivered = 0; | 1498 | cam->frame_state.frames = 0; |
1499 | cam->frame_state.singles = 0; | ||
1500 | cam->frame_state.delivered = 0; | ||
1549 | mutex_lock(&cam->s_mutex); | 1501 | mutex_lock(&cam->s_mutex); |
1550 | if (cam->users == 0) { | 1502 | if (cam->users == 0) { |
1551 | ret = mcam_setup_vb2(cam); | 1503 | ret = mcam_setup_vb2(cam); |
@@ -1566,8 +1518,9 @@ static int mcam_v4l_release(struct file *filp) | |||
1566 | { | 1518 | { |
1567 | struct mcam_camera *cam = filp->private_data; | 1519 | struct mcam_camera *cam = filp->private_data; |
1568 | 1520 | ||
1569 | cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", frames, | 1521 | cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", |
1570 | singles, delivered); | 1522 | cam->frame_state.frames, cam->frame_state.singles, |
1523 | cam->frame_state.delivered); | ||
1571 | mutex_lock(&cam->s_mutex); | 1524 | mutex_lock(&cam->s_mutex); |
1572 | (cam->users)--; | 1525 | (cam->users)--; |
1573 | if (cam->users == 0) { | 1526 | if (cam->users == 0) { |
@@ -1660,7 +1613,7 @@ static void mcam_frame_complete(struct mcam_camera *cam, int frame) | |||
1660 | clear_bit(CF_DMA_ACTIVE, &cam->flags); | 1613 | clear_bit(CF_DMA_ACTIVE, &cam->flags); |
1661 | cam->next_buf = frame; | 1614 | cam->next_buf = frame; |
1662 | cam->buf_seq[frame] = ++(cam->sequence); | 1615 | cam->buf_seq[frame] = ++(cam->sequence); |
1663 | frames++; | 1616 | cam->frame_state.frames++; |
1664 | /* | 1617 | /* |
1665 | * "This should never happen" | 1618 | * "This should never happen" |
1666 | */ | 1619 | */ |
@@ -1786,14 +1739,19 @@ int mccic_register(struct mcam_camera *cam) | |||
1786 | /* | 1739 | /* |
1787 | * Get the v4l2 setup done. | 1740 | * Get the v4l2 setup done. |
1788 | */ | 1741 | */ |
1742 | ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10); | ||
1743 | if (ret) | ||
1744 | goto out_unregister; | ||
1745 | cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler; | ||
1746 | |||
1789 | mutex_lock(&cam->s_mutex); | 1747 | mutex_lock(&cam->s_mutex); |
1790 | cam->vdev = mcam_v4l_template; | 1748 | cam->vdev = mcam_v4l_template; |
1791 | cam->vdev.debug = 0; | 1749 | cam->vdev.debug = 0; |
1792 | cam->vdev.v4l2_dev = &cam->v4l2_dev; | 1750 | cam->vdev.v4l2_dev = &cam->v4l2_dev; |
1751 | video_set_drvdata(&cam->vdev, cam); | ||
1793 | ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); | 1752 | ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); |
1794 | if (ret) | 1753 | if (ret) |
1795 | goto out; | 1754 | goto out; |
1796 | video_set_drvdata(&cam->vdev, cam); | ||
1797 | 1755 | ||
1798 | /* | 1756 | /* |
1799 | * If so requested, try to get our DMA buffers now. | 1757 | * If so requested, try to get our DMA buffers now. |
@@ -1805,6 +1763,7 @@ int mccic_register(struct mcam_camera *cam) | |||
1805 | } | 1763 | } |
1806 | 1764 | ||
1807 | out: | 1765 | out: |
1766 | v4l2_ctrl_handler_free(&cam->ctrl_handler); | ||
1808 | mutex_unlock(&cam->s_mutex); | 1767 | mutex_unlock(&cam->s_mutex); |
1809 | return ret; | 1768 | return ret; |
1810 | out_unregister: | 1769 | out_unregister: |
@@ -1829,6 +1788,7 @@ void mccic_shutdown(struct mcam_camera *cam) | |||
1829 | if (cam->buffer_mode == B_vmalloc) | 1788 | if (cam->buffer_mode == B_vmalloc) |
1830 | mcam_free_dma_bufs(cam); | 1789 | mcam_free_dma_bufs(cam); |
1831 | video_unregister_device(&cam->vdev); | 1790 | video_unregister_device(&cam->vdev); |
1791 | v4l2_ctrl_handler_free(&cam->ctrl_handler); | ||
1832 | v4l2_device_unregister(&cam->v4l2_dev); | 1792 | v4l2_device_unregister(&cam->v4l2_dev); |
1833 | } | 1793 | } |
1834 | 1794 | ||
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h index bd6acba9fb37..01dec9e5fc2b 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.h +++ b/drivers/media/platform/marvell-ccic/mcam-core.h | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/list.h> | 9 | #include <linux/list.h> |
10 | #include <media/v4l2-common.h> | 10 | #include <media/v4l2-common.h> |
11 | #include <media/v4l2-ctrls.h> | ||
11 | #include <media/v4l2-dev.h> | 12 | #include <media/v4l2-dev.h> |
12 | #include <media/videobuf2-core.h> | 13 | #include <media/videobuf2-core.h> |
13 | 14 | ||
@@ -15,15 +16,15 @@ | |||
15 | * Create our own symbols for the supported buffer modes, but, for now, | 16 | * Create our own symbols for the supported buffer modes, but, for now, |
16 | * base them entirely on which videobuf2 options have been selected. | 17 | * base them entirely on which videobuf2 options have been selected. |
17 | */ | 18 | */ |
18 | #if defined(CONFIG_VIDEOBUF2_VMALLOC) || defined(CONFIG_VIDEOBUF2_VMALLOC_MODULE) | 19 | #if IS_ENABLED(CONFIG_VIDEOBUF2_VMALLOC) |
19 | #define MCAM_MODE_VMALLOC 1 | 20 | #define MCAM_MODE_VMALLOC 1 |
20 | #endif | 21 | #endif |
21 | 22 | ||
22 | #if defined(CONFIG_VIDEOBUF2_DMA_CONTIG) || defined(CONFIG_VIDEOBUF2_DMA_CONTIG_MODULE) | 23 | #if IS_ENABLED(CONFIG_VIDEOBUF2_DMA_CONTIG) |
23 | #define MCAM_MODE_DMA_CONTIG 1 | 24 | #define MCAM_MODE_DMA_CONTIG 1 |
24 | #endif | 25 | #endif |
25 | 26 | ||
26 | #if defined(CONFIG_VIDEOBUF2_DMA_SG) || defined(CONFIG_VIDEOBUF2_DMA_SG_MODULE) | 27 | #if IS_ENABLED(CONFIG_VIDEOBUF2_DMA_SG) |
27 | #define MCAM_MODE_DMA_SG 1 | 28 | #define MCAM_MODE_DMA_SG 1 |
28 | #endif | 29 | #endif |
29 | 30 | ||
@@ -73,6 +74,14 @@ static inline int mcam_buffer_mode_supported(enum mcam_buffer_mode mode) | |||
73 | } | 74 | } |
74 | } | 75 | } |
75 | 76 | ||
77 | /* | ||
78 | * Basic frame states | ||
79 | */ | ||
80 | struct mcam_frame_state { | ||
81 | unsigned int frames; | ||
82 | unsigned int singles; | ||
83 | unsigned int delivered; | ||
84 | }; | ||
76 | 85 | ||
77 | /* | 86 | /* |
78 | * A description of one of our devices. | 87 | * A description of one of our devices. |
@@ -104,10 +113,12 @@ struct mcam_camera { | |||
104 | * should not be touched by the platform code. | 113 | * should not be touched by the platform code. |
105 | */ | 114 | */ |
106 | struct v4l2_device v4l2_dev; | 115 | struct v4l2_device v4l2_dev; |
116 | struct v4l2_ctrl_handler ctrl_handler; | ||
107 | enum mcam_state state; | 117 | enum mcam_state state; |
108 | unsigned long flags; /* Buffer status, mainly (dev_lock) */ | 118 | unsigned long flags; /* Buffer status, mainly (dev_lock) */ |
109 | int users; /* How many open FDs */ | 119 | int users; /* How many open FDs */ |
110 | 120 | ||
121 | struct mcam_frame_state frame_state; /* Frame state counter */ | ||
111 | /* | 122 | /* |
112 | * Subsystem structures. | 123 | * Subsystem structures. |
113 | */ | 124 | */ |
diff --git a/drivers/media/platform/omap/Kconfig b/drivers/media/platform/omap/Kconfig index 390ab094f9f2..37ad446b35b3 100644 --- a/drivers/media/platform/omap/Kconfig +++ b/drivers/media/platform/omap/Kconfig | |||
@@ -6,7 +6,7 @@ config VIDEO_OMAP2_VOUT | |||
6 | depends on ARCH_OMAP2 || ARCH_OMAP3 | 6 | depends on ARCH_OMAP2 || ARCH_OMAP3 |
7 | select VIDEOBUF_GEN | 7 | select VIDEOBUF_GEN |
8 | select VIDEOBUF_DMA_CONTIG | 8 | select VIDEOBUF_DMA_CONTIG |
9 | select OMAP2_DSS | 9 | select OMAP2_DSS if HAS_IOMEM && ARCH_OMAP2PLUS |
10 | select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3 | 10 | select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3 |
11 | select VIDEO_OMAP2_VOUT_VRFB if VIDEO_OMAP2_VOUT && OMAP2_VRFB | 11 | select VIDEO_OMAP2_VOUT_VRFB if VIDEO_OMAP2_VOUT && OMAP2_VRFB |
12 | default n | 12 | default n |
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 35cc526e6c93..96c4a17e4280 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c | |||
@@ -205,19 +205,21 @@ static u32 omap_vout_uservirt_to_phys(u32 virtp) | |||
205 | struct vm_area_struct *vma; | 205 | struct vm_area_struct *vma; |
206 | struct mm_struct *mm = current->mm; | 206 | struct mm_struct *mm = current->mm; |
207 | 207 | ||
208 | vma = find_vma(mm, virtp); | ||
209 | /* For kernel direct-mapped memory, take the easy way */ | 208 | /* For kernel direct-mapped memory, take the easy way */ |
210 | if (virtp >= PAGE_OFFSET) { | 209 | if (virtp >= PAGE_OFFSET) |
211 | physp = virt_to_phys((void *) virtp); | 210 | return virt_to_phys((void *) virtp); |
212 | } else if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) { | 211 | |
212 | down_read(¤t->mm->mmap_sem); | ||
213 | vma = find_vma(mm, virtp); | ||
214 | if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) { | ||
213 | /* this will catch, kernel-allocated, mmaped-to-usermode | 215 | /* this will catch, kernel-allocated, mmaped-to-usermode |
214 | addresses */ | 216 | addresses */ |
215 | physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); | 217 | physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); |
218 | up_read(¤t->mm->mmap_sem); | ||
216 | } else { | 219 | } else { |
217 | /* otherwise, use get_user_pages() for general userland pages */ | 220 | /* otherwise, use get_user_pages() for general userland pages */ |
218 | int res, nr_pages = 1; | 221 | int res, nr_pages = 1; |
219 | struct page *pages; | 222 | struct page *pages; |
220 | down_read(¤t->mm->mmap_sem); | ||
221 | 223 | ||
222 | res = get_user_pages(current, current->mm, virtp, nr_pages, 1, | 224 | res = get_user_pages(current, current->mm, virtp, nr_pages, 1, |
223 | 0, &pages, NULL); | 225 | 0, &pages, NULL); |
@@ -595,7 +597,7 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus) | |||
595 | return; | 597 | return; |
596 | 598 | ||
597 | spin_lock(&vout->vbq_lock); | 599 | spin_lock(&vout->vbq_lock); |
598 | do_gettimeofday(&timevalue); | 600 | v4l2_get_timestamp(&timevalue); |
599 | 601 | ||
600 | switch (cur_display->type) { | 602 | switch (cur_display->type) { |
601 | case OMAP_DISPLAY_TYPE_DSI: | 603 | case OMAP_DISPLAY_TYPE_DSI: |
@@ -1230,21 +1232,6 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh, | |||
1230 | return ret; | 1232 | return ret; |
1231 | } | 1233 | } |
1232 | 1234 | ||
1233 | static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh, | ||
1234 | struct v4l2_fmtdesc *fmt) | ||
1235 | { | ||
1236 | int index = fmt->index; | ||
1237 | |||
1238 | if (index >= NUM_OUTPUT_FORMATS) | ||
1239 | return -EINVAL; | ||
1240 | |||
1241 | fmt->flags = omap_formats[index].flags; | ||
1242 | strlcpy(fmt->description, omap_formats[index].description, | ||
1243 | sizeof(fmt->description)); | ||
1244 | fmt->pixelformat = omap_formats[index].pixelformat; | ||
1245 | return 0; | ||
1246 | } | ||
1247 | |||
1248 | static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, | 1235 | static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, |
1249 | struct v4l2_format *f) | 1236 | struct v4l2_format *f) |
1250 | { | 1237 | { |
@@ -1858,10 +1845,9 @@ static const struct v4l2_ioctl_ops vout_ioctl_ops = { | |||
1858 | .vidioc_s_fbuf = vidioc_s_fbuf, | 1845 | .vidioc_s_fbuf = vidioc_s_fbuf, |
1859 | .vidioc_g_fbuf = vidioc_g_fbuf, | 1846 | .vidioc_g_fbuf = vidioc_g_fbuf, |
1860 | .vidioc_s_ctrl = vidioc_s_ctrl, | 1847 | .vidioc_s_ctrl = vidioc_s_ctrl, |
1861 | .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, | 1848 | .vidioc_try_fmt_vid_out_overlay = vidioc_try_fmt_vid_overlay, |
1862 | .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, | 1849 | .vidioc_s_fmt_vid_out_overlay = vidioc_s_fmt_vid_overlay, |
1863 | .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, | 1850 | .vidioc_g_fmt_vid_out_overlay = vidioc_g_fmt_vid_overlay, |
1864 | .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, | ||
1865 | .vidioc_cropcap = vidioc_cropcap, | 1851 | .vidioc_cropcap = vidioc_cropcap, |
1866 | .vidioc_g_crop = vidioc_g_crop, | 1852 | .vidioc_g_crop = vidioc_g_crop, |
1867 | .vidioc_s_crop = vidioc_s_crop, | 1853 | .vidioc_s_crop = vidioc_s_crop, |
diff --git a/drivers/media/platform/omap24xxcam.c b/drivers/media/platform/omap24xxcam.c index 8b7ccea982e7..debb44ceb185 100644 --- a/drivers/media/platform/omap24xxcam.c +++ b/drivers/media/platform/omap24xxcam.c | |||
@@ -402,7 +402,7 @@ static void omap24xxcam_vbq_complete(struct omap24xxcam_sgdma *sgdma, | |||
402 | omap24xxcam_core_disable(cam); | 402 | omap24xxcam_core_disable(cam); |
403 | spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags); | 403 | spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags); |
404 | 404 | ||
405 | do_gettimeofday(&vb->ts); | 405 | v4l2_get_timestamp(&vb->ts); |
406 | vb->field_count = atomic_add_return(2, &fh->field_count); | 406 | vb->field_count = atomic_add_return(2, &fh->field_count); |
407 | if (csr & csr_error) { | 407 | if (csr & csr_error) { |
408 | vb->state = VIDEOBUF_ERROR; | 408 | vb->state = VIDEOBUF_ERROR; |
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index e4aaee91201d..383a727b8aa0 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c | |||
@@ -1406,28 +1406,15 @@ static const char *isp_clocks[] = { | |||
1406 | "l3_ick", | 1406 | "l3_ick", |
1407 | }; | 1407 | }; |
1408 | 1408 | ||
1409 | static void isp_put_clocks(struct isp_device *isp) | ||
1410 | { | ||
1411 | unsigned int i; | ||
1412 | |||
1413 | for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) { | ||
1414 | if (isp->clock[i]) { | ||
1415 | clk_put(isp->clock[i]); | ||
1416 | isp->clock[i] = NULL; | ||
1417 | } | ||
1418 | } | ||
1419 | } | ||
1420 | |||
1421 | static int isp_get_clocks(struct isp_device *isp) | 1409 | static int isp_get_clocks(struct isp_device *isp) |
1422 | { | 1410 | { |
1423 | struct clk *clk; | 1411 | struct clk *clk; |
1424 | unsigned int i; | 1412 | unsigned int i; |
1425 | 1413 | ||
1426 | for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) { | 1414 | for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) { |
1427 | clk = clk_get(isp->dev, isp_clocks[i]); | 1415 | clk = devm_clk_get(isp->dev, isp_clocks[i]); |
1428 | if (IS_ERR(clk)) { | 1416 | if (IS_ERR(clk)) { |
1429 | dev_err(isp->dev, "clk_get %s failed\n", isp_clocks[i]); | 1417 | dev_err(isp->dev, "clk_get %s failed\n", isp_clocks[i]); |
1430 | isp_put_clocks(isp); | ||
1431 | return PTR_ERR(clk); | 1418 | return PTR_ERR(clk); |
1432 | } | 1419 | } |
1433 | 1420 | ||
@@ -1993,7 +1980,6 @@ error_csiphy: | |||
1993 | static int isp_remove(struct platform_device *pdev) | 1980 | static int isp_remove(struct platform_device *pdev) |
1994 | { | 1981 | { |
1995 | struct isp_device *isp = platform_get_drvdata(pdev); | 1982 | struct isp_device *isp = platform_get_drvdata(pdev); |
1996 | int i; | ||
1997 | 1983 | ||
1998 | isp_unregister_entities(isp); | 1984 | isp_unregister_entities(isp); |
1999 | isp_cleanup_modules(isp); | 1985 | isp_cleanup_modules(isp); |
@@ -2004,26 +1990,6 @@ static int isp_remove(struct platform_device *pdev) | |||
2004 | isp->domain = NULL; | 1990 | isp->domain = NULL; |
2005 | omap3isp_put(isp); | 1991 | omap3isp_put(isp); |
2006 | 1992 | ||
2007 | free_irq(isp->irq_num, isp); | ||
2008 | isp_put_clocks(isp); | ||
2009 | |||
2010 | for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) { | ||
2011 | if (isp->mmio_base[i]) { | ||
2012 | iounmap(isp->mmio_base[i]); | ||
2013 | isp->mmio_base[i] = NULL; | ||
2014 | } | ||
2015 | |||
2016 | if (isp->mmio_base_phys[i]) { | ||
2017 | release_mem_region(isp->mmio_base_phys[i], | ||
2018 | isp->mmio_size[i]); | ||
2019 | isp->mmio_base_phys[i] = 0; | ||
2020 | } | ||
2021 | } | ||
2022 | |||
2023 | regulator_put(isp->isp_csiphy1.vdd); | ||
2024 | regulator_put(isp->isp_csiphy2.vdd); | ||
2025 | kfree(isp); | ||
2026 | |||
2027 | return 0; | 1993 | return 0; |
2028 | } | 1994 | } |
2029 | 1995 | ||
@@ -2041,7 +2007,8 @@ static int isp_map_mem_resource(struct platform_device *pdev, | |||
2041 | return -ENODEV; | 2007 | return -ENODEV; |
2042 | } | 2008 | } |
2043 | 2009 | ||
2044 | if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) { | 2010 | if (!devm_request_mem_region(isp->dev, mem->start, resource_size(mem), |
2011 | pdev->name)) { | ||
2045 | dev_err(isp->dev, | 2012 | dev_err(isp->dev, |
2046 | "cannot reserve camera register I/O region\n"); | 2013 | "cannot reserve camera register I/O region\n"); |
2047 | return -ENODEV; | 2014 | return -ENODEV; |
@@ -2050,8 +2017,9 @@ static int isp_map_mem_resource(struct platform_device *pdev, | |||
2050 | isp->mmio_size[res] = resource_size(mem); | 2017 | isp->mmio_size[res] = resource_size(mem); |
2051 | 2018 | ||
2052 | /* map the region */ | 2019 | /* map the region */ |
2053 | isp->mmio_base[res] = ioremap_nocache(isp->mmio_base_phys[res], | 2020 | isp->mmio_base[res] = devm_ioremap_nocache(isp->dev, |
2054 | isp->mmio_size[res]); | 2021 | isp->mmio_base_phys[res], |
2022 | isp->mmio_size[res]); | ||
2055 | if (!isp->mmio_base[res]) { | 2023 | if (!isp->mmio_base[res]) { |
2056 | dev_err(isp->dev, "cannot map camera register I/O region\n"); | 2024 | dev_err(isp->dev, "cannot map camera register I/O region\n"); |
2057 | return -ENODEV; | 2025 | return -ENODEV; |
@@ -2081,7 +2049,7 @@ static int isp_probe(struct platform_device *pdev) | |||
2081 | if (pdata == NULL) | 2049 | if (pdata == NULL) |
2082 | return -EINVAL; | 2050 | return -EINVAL; |
2083 | 2051 | ||
2084 | isp = kzalloc(sizeof(*isp), GFP_KERNEL); | 2052 | isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL); |
2085 | if (!isp) { | 2053 | if (!isp) { |
2086 | dev_err(&pdev->dev, "could not allocate memory\n"); | 2054 | dev_err(&pdev->dev, "could not allocate memory\n"); |
2087 | return -ENOMEM; | 2055 | return -ENOMEM; |
@@ -2104,8 +2072,8 @@ static int isp_probe(struct platform_device *pdev) | |||
2104 | platform_set_drvdata(pdev, isp); | 2072 | platform_set_drvdata(pdev, isp); |
2105 | 2073 | ||
2106 | /* Regulators */ | 2074 | /* Regulators */ |
2107 | isp->isp_csiphy1.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY1"); | 2075 | isp->isp_csiphy1.vdd = devm_regulator_get(&pdev->dev, "VDD_CSIPHY1"); |
2108 | isp->isp_csiphy2.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY2"); | 2076 | isp->isp_csiphy2.vdd = devm_regulator_get(&pdev->dev, "VDD_CSIPHY2"); |
2109 | 2077 | ||
2110 | /* Clocks | 2078 | /* Clocks |
2111 | * | 2079 | * |
@@ -2180,7 +2148,8 @@ static int isp_probe(struct platform_device *pdev) | |||
2180 | goto detach_dev; | 2148 | goto detach_dev; |
2181 | } | 2149 | } |
2182 | 2150 | ||
2183 | if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) { | 2151 | if (devm_request_irq(isp->dev, isp->irq_num, isp_isr, IRQF_SHARED, |
2152 | "OMAP3 ISP", isp)) { | ||
2184 | dev_err(isp->dev, "Unable to request IRQ\n"); | 2153 | dev_err(isp->dev, "Unable to request IRQ\n"); |
2185 | ret = -EINVAL; | 2154 | ret = -EINVAL; |
2186 | goto detach_dev; | 2155 | goto detach_dev; |
@@ -2189,7 +2158,7 @@ static int isp_probe(struct platform_device *pdev) | |||
2189 | /* Entities */ | 2158 | /* Entities */ |
2190 | ret = isp_initialize_modules(isp); | 2159 | ret = isp_initialize_modules(isp); |
2191 | if (ret < 0) | 2160 | if (ret < 0) |
2192 | goto error_irq; | 2161 | goto detach_dev; |
2193 | 2162 | ||
2194 | ret = isp_register_entities(isp); | 2163 | ret = isp_register_entities(isp); |
2195 | if (ret < 0) | 2164 | if (ret < 0) |
@@ -2202,8 +2171,6 @@ static int isp_probe(struct platform_device *pdev) | |||
2202 | 2171 | ||
2203 | error_modules: | 2172 | error_modules: |
2204 | isp_cleanup_modules(isp); | 2173 | isp_cleanup_modules(isp); |
2205 | error_irq: | ||
2206 | free_irq(isp->irq_num, isp); | ||
2207 | detach_dev: | 2174 | detach_dev: |
2208 | iommu_detach_device(isp->domain, &pdev->dev); | 2175 | iommu_detach_device(isp->domain, &pdev->dev); |
2209 | free_domain: | 2176 | free_domain: |
@@ -2211,26 +2178,9 @@ free_domain: | |||
2211 | error_isp: | 2178 | error_isp: |
2212 | omap3isp_put(isp); | 2179 | omap3isp_put(isp); |
2213 | error: | 2180 | error: |
2214 | isp_put_clocks(isp); | ||
2215 | |||
2216 | for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) { | ||
2217 | if (isp->mmio_base[i]) { | ||
2218 | iounmap(isp->mmio_base[i]); | ||
2219 | isp->mmio_base[i] = NULL; | ||
2220 | } | ||
2221 | |||
2222 | if (isp->mmio_base_phys[i]) { | ||
2223 | release_mem_region(isp->mmio_base_phys[i], | ||
2224 | isp->mmio_size[i]); | ||
2225 | isp->mmio_base_phys[i] = 0; | ||
2226 | } | ||
2227 | } | ||
2228 | regulator_put(isp->isp_csiphy2.vdd); | ||
2229 | regulator_put(isp->isp_csiphy1.vdd); | ||
2230 | platform_set_drvdata(pdev, NULL); | 2181 | platform_set_drvdata(pdev, NULL); |
2231 | 2182 | ||
2232 | mutex_destroy(&isp->isp_mutex); | 2183 | mutex_destroy(&isp->isp_mutex); |
2233 | kfree(isp); | ||
2234 | 2184 | ||
2235 | return ret; | 2185 | return ret; |
2236 | } | 2186 | } |
diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c index 85f0de85f37c..c5d84c977e29 100644 --- a/drivers/media/platform/omap3isp/ispccp2.c +++ b/drivers/media/platform/omap3isp/ispccp2.c | |||
@@ -1136,7 +1136,7 @@ int omap3isp_ccp2_init(struct isp_device *isp) | |||
1136 | * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c). | 1136 | * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c). |
1137 | */ | 1137 | */ |
1138 | if (isp->revision == ISP_REVISION_2_0) { | 1138 | if (isp->revision == ISP_REVISION_2_0) { |
1139 | ccp2->vdds_csib = regulator_get(isp->dev, "vdds_csib"); | 1139 | ccp2->vdds_csib = devm_regulator_get(isp->dev, "vdds_csib"); |
1140 | if (IS_ERR(ccp2->vdds_csib)) { | 1140 | if (IS_ERR(ccp2->vdds_csib)) { |
1141 | dev_dbg(isp->dev, | 1141 | dev_dbg(isp->dev, |
1142 | "Could not get regulator vdds_csib\n"); | 1142 | "Could not get regulator vdds_csib\n"); |
@@ -1147,10 +1147,8 @@ int omap3isp_ccp2_init(struct isp_device *isp) | |||
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | ret = ccp2_init_entities(ccp2); | 1149 | ret = ccp2_init_entities(ccp2); |
1150 | if (ret < 0) { | 1150 | if (ret < 0) |
1151 | regulator_put(ccp2->vdds_csib); | ||
1152 | return ret; | 1151 | return ret; |
1153 | } | ||
1154 | 1152 | ||
1155 | ccp2_reset(ccp2); | 1153 | ccp2_reset(ccp2); |
1156 | return 0; | 1154 | return 0; |
@@ -1166,6 +1164,4 @@ void omap3isp_ccp2_cleanup(struct isp_device *isp) | |||
1166 | 1164 | ||
1167 | omap3isp_video_cleanup(&ccp2->video_in); | 1165 | omap3isp_video_cleanup(&ccp2->video_in); |
1168 | media_entity_cleanup(&ccp2->subdev.entity); | 1166 | media_entity_cleanup(&ccp2->subdev.entity); |
1169 | |||
1170 | regulator_put(ccp2->vdds_csib); | ||
1171 | } | 1167 | } |
diff --git a/drivers/media/platform/omap3isp/ispcsiphy.c b/drivers/media/platform/omap3isp/ispcsiphy.c index 3d56b33f85e8..c09de32f986a 100644 --- a/drivers/media/platform/omap3isp/ispcsiphy.c +++ b/drivers/media/platform/omap3isp/ispcsiphy.c | |||
@@ -32,7 +32,8 @@ | |||
32 | #include "ispreg.h" | 32 | #include "ispreg.h" |
33 | #include "ispcsiphy.h" | 33 | #include "ispcsiphy.h" |
34 | 34 | ||
35 | static void csiphy_routing_cfg_3630(struct isp_csiphy *phy, u32 iface, | 35 | static void csiphy_routing_cfg_3630(struct isp_csiphy *phy, |
36 | enum isp_interface_type iface, | ||
36 | bool ccp2_strobe) | 37 | bool ccp2_strobe) |
37 | { | 38 | { |
38 | u32 reg = isp_reg_readl( | 39 | u32 reg = isp_reg_readl( |
@@ -40,6 +41,8 @@ static void csiphy_routing_cfg_3630(struct isp_csiphy *phy, u32 iface, | |||
40 | u32 shift, mode; | 41 | u32 shift, mode; |
41 | 42 | ||
42 | switch (iface) { | 43 | switch (iface) { |
44 | default: | ||
45 | /* Should not happen in practice, but let's keep the compiler happy. */ | ||
43 | case ISP_INTERFACE_CCP2B_PHY1: | 46 | case ISP_INTERFACE_CCP2B_PHY1: |
44 | reg &= ~OMAP3630_CONTROL_CAMERA_PHY_CTRL_CSI1_RX_SEL_PHY2; | 47 | reg &= ~OMAP3630_CONTROL_CAMERA_PHY_CTRL_CSI1_RX_SEL_PHY2; |
45 | shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY1_SHIFT; | 48 | shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY1_SHIFT; |
@@ -59,9 +62,8 @@ static void csiphy_routing_cfg_3630(struct isp_csiphy *phy, u32 iface, | |||
59 | } | 62 | } |
60 | 63 | ||
61 | /* Select data/clock or data/strobe mode for CCP2 */ | 64 | /* Select data/clock or data/strobe mode for CCP2 */ |
62 | switch (iface) { | 65 | if (iface == ISP_INTERFACE_CCP2B_PHY1 || |
63 | case ISP_INTERFACE_CCP2B_PHY1: | 66 | iface == ISP_INTERFACE_CCP2B_PHY2) { |
64 | case ISP_INTERFACE_CCP2B_PHY2: | ||
65 | if (ccp2_strobe) | 67 | if (ccp2_strobe) |
66 | mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_STROBE; | 68 | mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_STROBE; |
67 | else | 69 | else |
@@ -110,7 +112,8 @@ static void csiphy_routing_cfg_3430(struct isp_csiphy *phy, u32 iface, bool on, | |||
110 | * and 3630, so they will not hold their contents in off-mode. This isn't an | 112 | * and 3630, so they will not hold their contents in off-mode. This isn't an |
111 | * issue since the MPU power domain is forced on whilst the ISP is in use. | 113 | * issue since the MPU power domain is forced on whilst the ISP is in use. |
112 | */ | 114 | */ |
113 | static void csiphy_routing_cfg(struct isp_csiphy *phy, u32 iface, bool on, | 115 | static void csiphy_routing_cfg(struct isp_csiphy *phy, |
116 | enum isp_interface_type iface, bool on, | ||
114 | bool ccp2_strobe) | 117 | bool ccp2_strobe) |
115 | { | 118 | { |
116 | if (phy->isp->mmio_base[OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL] | 119 | if (phy->isp->mmio_base[OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL] |
diff --git a/drivers/media/platform/omap3isp/isph3a_aewb.c b/drivers/media/platform/omap3isp/isph3a_aewb.c index 036e9961d027..75fd82b152ba 100644 --- a/drivers/media/platform/omap3isp/isph3a_aewb.c +++ b/drivers/media/platform/omap3isp/isph3a_aewb.c | |||
@@ -300,13 +300,11 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp) | |||
300 | struct ispstat *aewb = &isp->isp_aewb; | 300 | struct ispstat *aewb = &isp->isp_aewb; |
301 | struct omap3isp_h3a_aewb_config *aewb_cfg; | 301 | struct omap3isp_h3a_aewb_config *aewb_cfg; |
302 | struct omap3isp_h3a_aewb_config *aewb_recover_cfg; | 302 | struct omap3isp_h3a_aewb_config *aewb_recover_cfg; |
303 | int ret; | ||
304 | 303 | ||
305 | aewb_cfg = kzalloc(sizeof(*aewb_cfg), GFP_KERNEL); | 304 | aewb_cfg = devm_kzalloc(isp->dev, sizeof(*aewb_cfg), GFP_KERNEL); |
306 | if (!aewb_cfg) | 305 | if (!aewb_cfg) |
307 | return -ENOMEM; | 306 | return -ENOMEM; |
308 | 307 | ||
309 | memset(aewb, 0, sizeof(*aewb)); | ||
310 | aewb->ops = &h3a_aewb_ops; | 308 | aewb->ops = &h3a_aewb_ops; |
311 | aewb->priv = aewb_cfg; | 309 | aewb->priv = aewb_cfg; |
312 | aewb->dma_ch = -1; | 310 | aewb->dma_ch = -1; |
@@ -314,12 +312,12 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp) | |||
314 | aewb->isp = isp; | 312 | aewb->isp = isp; |
315 | 313 | ||
316 | /* Set recover state configuration */ | 314 | /* Set recover state configuration */ |
317 | aewb_recover_cfg = kzalloc(sizeof(*aewb_recover_cfg), GFP_KERNEL); | 315 | aewb_recover_cfg = devm_kzalloc(isp->dev, sizeof(*aewb_recover_cfg), |
316 | GFP_KERNEL); | ||
318 | if (!aewb_recover_cfg) { | 317 | if (!aewb_recover_cfg) { |
319 | dev_err(aewb->isp->dev, "AEWB: cannot allocate memory for " | 318 | dev_err(aewb->isp->dev, "AEWB: cannot allocate memory for " |
320 | "recover configuration.\n"); | 319 | "recover configuration.\n"); |
321 | ret = -ENOMEM; | 320 | return -ENOMEM; |
322 | goto err_recover_alloc; | ||
323 | } | 321 | } |
324 | 322 | ||
325 | aewb_recover_cfg->saturation_limit = OMAP3ISP_AEWB_MAX_SATURATION_LIM; | 323 | aewb_recover_cfg->saturation_limit = OMAP3ISP_AEWB_MAX_SATURATION_LIM; |
@@ -336,25 +334,13 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp) | |||
336 | if (h3a_aewb_validate_params(aewb, aewb_recover_cfg)) { | 334 | if (h3a_aewb_validate_params(aewb, aewb_recover_cfg)) { |
337 | dev_err(aewb->isp->dev, "AEWB: recover configuration is " | 335 | dev_err(aewb->isp->dev, "AEWB: recover configuration is " |
338 | "invalid.\n"); | 336 | "invalid.\n"); |
339 | ret = -EINVAL; | 337 | return -EINVAL; |
340 | goto err_conf; | ||
341 | } | 338 | } |
342 | 339 | ||
343 | aewb_recover_cfg->buf_size = h3a_aewb_get_buf_size(aewb_recover_cfg); | 340 | aewb_recover_cfg->buf_size = h3a_aewb_get_buf_size(aewb_recover_cfg); |
344 | aewb->recover_priv = aewb_recover_cfg; | 341 | aewb->recover_priv = aewb_recover_cfg; |
345 | 342 | ||
346 | ret = omap3isp_stat_init(aewb, "AEWB", &h3a_aewb_subdev_ops); | 343 | return omap3isp_stat_init(aewb, "AEWB", &h3a_aewb_subdev_ops); |
347 | if (ret) | ||
348 | goto err_conf; | ||
349 | |||
350 | return 0; | ||
351 | |||
352 | err_conf: | ||
353 | kfree(aewb_recover_cfg); | ||
354 | err_recover_alloc: | ||
355 | kfree(aewb_cfg); | ||
356 | |||
357 | return ret; | ||
358 | } | 344 | } |
359 | 345 | ||
360 | /* | 346 | /* |
@@ -362,7 +348,5 @@ err_recover_alloc: | |||
362 | */ | 348 | */ |
363 | void omap3isp_h3a_aewb_cleanup(struct isp_device *isp) | 349 | void omap3isp_h3a_aewb_cleanup(struct isp_device *isp) |
364 | { | 350 | { |
365 | kfree(isp->isp_aewb.priv); | ||
366 | kfree(isp->isp_aewb.recover_priv); | ||
367 | omap3isp_stat_cleanup(&isp->isp_aewb); | 351 | omap3isp_stat_cleanup(&isp->isp_aewb); |
368 | } | 352 | } |
diff --git a/drivers/media/platform/omap3isp/isph3a_af.c b/drivers/media/platform/omap3isp/isph3a_af.c index 42ccce318d5d..a0bf5af32438 100644 --- a/drivers/media/platform/omap3isp/isph3a_af.c +++ b/drivers/media/platform/omap3isp/isph3a_af.c | |||
@@ -363,13 +363,11 @@ int omap3isp_h3a_af_init(struct isp_device *isp) | |||
363 | struct ispstat *af = &isp->isp_af; | 363 | struct ispstat *af = &isp->isp_af; |
364 | struct omap3isp_h3a_af_config *af_cfg; | 364 | struct omap3isp_h3a_af_config *af_cfg; |
365 | struct omap3isp_h3a_af_config *af_recover_cfg; | 365 | struct omap3isp_h3a_af_config *af_recover_cfg; |
366 | int ret; | ||
367 | 366 | ||
368 | af_cfg = kzalloc(sizeof(*af_cfg), GFP_KERNEL); | 367 | af_cfg = devm_kzalloc(isp->dev, sizeof(*af_cfg), GFP_KERNEL); |
369 | if (af_cfg == NULL) | 368 | if (af_cfg == NULL) |
370 | return -ENOMEM; | 369 | return -ENOMEM; |
371 | 370 | ||
372 | memset(af, 0, sizeof(*af)); | ||
373 | af->ops = &h3a_af_ops; | 371 | af->ops = &h3a_af_ops; |
374 | af->priv = af_cfg; | 372 | af->priv = af_cfg; |
375 | af->dma_ch = -1; | 373 | af->dma_ch = -1; |
@@ -377,12 +375,12 @@ int omap3isp_h3a_af_init(struct isp_device *isp) | |||
377 | af->isp = isp; | 375 | af->isp = isp; |
378 | 376 | ||
379 | /* Set recover state configuration */ | 377 | /* Set recover state configuration */ |
380 | af_recover_cfg = kzalloc(sizeof(*af_recover_cfg), GFP_KERNEL); | 378 | af_recover_cfg = devm_kzalloc(isp->dev, sizeof(*af_recover_cfg), |
379 | GFP_KERNEL); | ||
381 | if (!af_recover_cfg) { | 380 | if (!af_recover_cfg) { |
382 | dev_err(af->isp->dev, "AF: cannot allocate memory for recover " | 381 | dev_err(af->isp->dev, "AF: cannot allocate memory for recover " |
383 | "configuration.\n"); | 382 | "configuration.\n"); |
384 | ret = -ENOMEM; | 383 | return -ENOMEM; |
385 | goto err_recover_alloc; | ||
386 | } | 384 | } |
387 | 385 | ||
388 | af_recover_cfg->paxel.h_start = OMAP3ISP_AF_PAXEL_HZSTART_MIN; | 386 | af_recover_cfg->paxel.h_start = OMAP3ISP_AF_PAXEL_HZSTART_MIN; |
@@ -394,30 +392,16 @@ int omap3isp_h3a_af_init(struct isp_device *isp) | |||
394 | if (h3a_af_validate_params(af, af_recover_cfg)) { | 392 | if (h3a_af_validate_params(af, af_recover_cfg)) { |
395 | dev_err(af->isp->dev, "AF: recover configuration is " | 393 | dev_err(af->isp->dev, "AF: recover configuration is " |
396 | "invalid.\n"); | 394 | "invalid.\n"); |
397 | ret = -EINVAL; | 395 | return -EINVAL; |
398 | goto err_conf; | ||
399 | } | 396 | } |
400 | 397 | ||
401 | af_recover_cfg->buf_size = h3a_af_get_buf_size(af_recover_cfg); | 398 | af_recover_cfg->buf_size = h3a_af_get_buf_size(af_recover_cfg); |
402 | af->recover_priv = af_recover_cfg; | 399 | af->recover_priv = af_recover_cfg; |
403 | 400 | ||
404 | ret = omap3isp_stat_init(af, "AF", &h3a_af_subdev_ops); | 401 | return omap3isp_stat_init(af, "AF", &h3a_af_subdev_ops); |
405 | if (ret) | ||
406 | goto err_conf; | ||
407 | |||
408 | return 0; | ||
409 | |||
410 | err_conf: | ||
411 | kfree(af_recover_cfg); | ||
412 | err_recover_alloc: | ||
413 | kfree(af_cfg); | ||
414 | |||
415 | return ret; | ||
416 | } | 402 | } |
417 | 403 | ||
418 | void omap3isp_h3a_af_cleanup(struct isp_device *isp) | 404 | void omap3isp_h3a_af_cleanup(struct isp_device *isp) |
419 | { | 405 | { |
420 | kfree(isp->isp_af.priv); | ||
421 | kfree(isp->isp_af.recover_priv); | ||
422 | omap3isp_stat_cleanup(&isp->isp_af); | 406 | omap3isp_stat_cleanup(&isp->isp_af); |
423 | } | 407 | } |
diff --git a/drivers/media/platform/omap3isp/isphist.c b/drivers/media/platform/omap3isp/isphist.c index 2d759c56f37c..e070c24048ef 100644 --- a/drivers/media/platform/omap3isp/isphist.c +++ b/drivers/media/platform/omap3isp/isphist.c | |||
@@ -114,14 +114,14 @@ static void hist_setup_regs(struct ispstat *hist, void *priv) | |||
114 | /* Regions size and position */ | 114 | /* Regions size and position */ |
115 | for (c = 0; c < OMAP3ISP_HIST_MAX_REGIONS; c++) { | 115 | for (c = 0; c < OMAP3ISP_HIST_MAX_REGIONS; c++) { |
116 | if (c < conf->num_regions) { | 116 | if (c < conf->num_regions) { |
117 | reg_hor[c] = conf->region[c].h_start << | 117 | reg_hor[c] = (conf->region[c].h_start << |
118 | ISPHIST_REG_START_SHIFT; | 118 | ISPHIST_REG_START_SHIFT) |
119 | reg_hor[c] = conf->region[c].h_end << | 119 | | (conf->region[c].h_end << |
120 | ISPHIST_REG_END_SHIFT; | 120 | ISPHIST_REG_END_SHIFT); |
121 | reg_ver[c] = conf->region[c].v_start << | 121 | reg_ver[c] = (conf->region[c].v_start << |
122 | ISPHIST_REG_START_SHIFT; | 122 | ISPHIST_REG_START_SHIFT) |
123 | reg_ver[c] = conf->region[c].v_end << | 123 | | (conf->region[c].v_end << |
124 | ISPHIST_REG_END_SHIFT; | 124 | ISPHIST_REG_END_SHIFT); |
125 | } else { | 125 | } else { |
126 | reg_hor[c] = 0; | 126 | reg_hor[c] = 0; |
127 | reg_ver[c] = 0; | 127 | reg_ver[c] = 0; |
@@ -477,11 +477,10 @@ int omap3isp_hist_init(struct isp_device *isp) | |||
477 | struct omap3isp_hist_config *hist_cfg; | 477 | struct omap3isp_hist_config *hist_cfg; |
478 | int ret = -1; | 478 | int ret = -1; |
479 | 479 | ||
480 | hist_cfg = kzalloc(sizeof(*hist_cfg), GFP_KERNEL); | 480 | hist_cfg = devm_kzalloc(isp->dev, sizeof(*hist_cfg), GFP_KERNEL); |
481 | if (hist_cfg == NULL) | 481 | if (hist_cfg == NULL) |
482 | return -ENOMEM; | 482 | return -ENOMEM; |
483 | 483 | ||
484 | memset(hist, 0, sizeof(*hist)); | ||
485 | hist->isp = isp; | 484 | hist->isp = isp; |
486 | 485 | ||
487 | if (HIST_CONFIG_DMA) | 486 | if (HIST_CONFIG_DMA) |
@@ -504,7 +503,6 @@ int omap3isp_hist_init(struct isp_device *isp) | |||
504 | 503 | ||
505 | ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops); | 504 | ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops); |
506 | if (ret) { | 505 | if (ret) { |
507 | kfree(hist_cfg); | ||
508 | if (HIST_USING_DMA(hist)) | 506 | if (HIST_USING_DMA(hist)) |
509 | omap_free_dma(hist->dma_ch); | 507 | omap_free_dma(hist->dma_ch); |
510 | } | 508 | } |
@@ -519,6 +517,5 @@ void omap3isp_hist_cleanup(struct isp_device *isp) | |||
519 | { | 517 | { |
520 | if (HIST_USING_DMA(&isp->isp_hist)) | 518 | if (HIST_USING_DMA(&isp->isp_hist)) |
521 | omap_free_dma(isp->isp_hist.dma_ch); | 519 | omap_free_dma(isp->isp_hist.dma_ch); |
522 | kfree(isp->isp_hist.priv); | ||
523 | omap3isp_stat_cleanup(&isp->isp_hist); | 520 | omap3isp_stat_cleanup(&isp->isp_hist); |
524 | } | 521 | } |
diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c index 691b92a3c3e7..cd8831aebdeb 100644 --- a/drivers/media/platform/omap3isp/isppreview.c +++ b/drivers/media/platform/omap3isp/isppreview.c | |||
@@ -82,8 +82,9 @@ static struct omap3isp_prev_csc flr_prev_csc = { | |||
82 | * The preview engine crops several rows and columns internally depending on | 82 | * The preview engine crops several rows and columns internally depending on |
83 | * which filters are enabled. To avoid format changes when the filters are | 83 | * which filters are enabled. To avoid format changes when the filters are |
84 | * enabled or disabled (which would prevent them from being turned on or off | 84 | * enabled or disabled (which would prevent them from being turned on or off |
85 | * during streaming), the driver assumes all the filters are enabled when | 85 | * during streaming), the driver assumes all filters that can be configured |
86 | * computing sink crop and source format limits. | 86 | * during streaming are enabled when computing sink crop and source format |
87 | * limits. | ||
87 | * | 88 | * |
88 | * If a filter is disabled, additional cropping is automatically added at the | 89 | * If a filter is disabled, additional cropping is automatically added at the |
89 | * preview engine input by the driver to avoid overflow at line and frame end. | 90 | * preview engine input by the driver to avoid overflow at line and frame end. |
@@ -92,25 +93,23 @@ static struct omap3isp_prev_csc flr_prev_csc = { | |||
92 | * Median filter 4 pixels | 93 | * Median filter 4 pixels |
93 | * Noise filter, | 94 | * Noise filter, |
94 | * Faulty pixels correction 4 pixels, 4 lines | 95 | * Faulty pixels correction 4 pixels, 4 lines |
95 | * CFA filter 4 pixels, 4 lines in Bayer mode | ||
96 | * 2 lines in other modes | ||
97 | * Color suppression 2 pixels | 96 | * Color suppression 2 pixels |
98 | * or luma enhancement | 97 | * or luma enhancement |
99 | * ------------------------------------------------------------- | 98 | * ------------------------------------------------------------- |
100 | * Maximum total 14 pixels, 8 lines | 99 | * Maximum total 10 pixels, 4 lines |
101 | * | 100 | * |
102 | * The color suppression and luma enhancement filters are applied after bayer to | 101 | * The color suppression and luma enhancement filters are applied after bayer to |
103 | * YUV conversion. They thus can crop one pixel on the left and one pixel on the | 102 | * YUV conversion. They thus can crop one pixel on the left and one pixel on the |
104 | * right side of the image without changing the color pattern. When both those | 103 | * right side of the image without changing the color pattern. When both those |
105 | * filters are disabled, the driver must crop the two pixels on the same side of | 104 | * filters are disabled, the driver must crop the two pixels on the same side of |
106 | * the image to avoid changing the bayer pattern. The left margin is thus set to | 105 | * the image to avoid changing the bayer pattern. The left margin is thus set to |
107 | * 8 pixels and the right margin to 6 pixels. | 106 | * 6 pixels and the right margin to 4 pixels. |
108 | */ | 107 | */ |
109 | 108 | ||
110 | #define PREV_MARGIN_LEFT 8 | 109 | #define PREV_MARGIN_LEFT 6 |
111 | #define PREV_MARGIN_RIGHT 6 | 110 | #define PREV_MARGIN_RIGHT 4 |
112 | #define PREV_MARGIN_TOP 4 | 111 | #define PREV_MARGIN_TOP 2 |
113 | #define PREV_MARGIN_BOTTOM 4 | 112 | #define PREV_MARGIN_BOTTOM 2 |
114 | 113 | ||
115 | #define PREV_MIN_IN_WIDTH 64 | 114 | #define PREV_MIN_IN_WIDTH 64 |
116 | #define PREV_MIN_IN_HEIGHT 8 | 115 | #define PREV_MIN_IN_HEIGHT 8 |
@@ -1080,7 +1079,6 @@ static void preview_config_input_format(struct isp_prev_device *prev, | |||
1080 | */ | 1079 | */ |
1081 | static void preview_config_input_size(struct isp_prev_device *prev, u32 active) | 1080 | static void preview_config_input_size(struct isp_prev_device *prev, u32 active) |
1082 | { | 1081 | { |
1083 | const struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK]; | ||
1084 | struct isp_device *isp = to_isp_device(prev); | 1082 | struct isp_device *isp = to_isp_device(prev); |
1085 | unsigned int sph = prev->crop.left; | 1083 | unsigned int sph = prev->crop.left; |
1086 | unsigned int eph = prev->crop.left + prev->crop.width - 1; | 1084 | unsigned int eph = prev->crop.left + prev->crop.width - 1; |
@@ -1088,14 +1086,6 @@ static void preview_config_input_size(struct isp_prev_device *prev, u32 active) | |||
1088 | unsigned int elv = prev->crop.top + prev->crop.height - 1; | 1086 | unsigned int elv = prev->crop.top + prev->crop.height - 1; |
1089 | u32 features; | 1087 | u32 features; |
1090 | 1088 | ||
1091 | if (format->code != V4L2_MBUS_FMT_Y8_1X8 && | ||
1092 | format->code != V4L2_MBUS_FMT_Y10_1X10) { | ||
1093 | sph -= 2; | ||
1094 | eph += 2; | ||
1095 | slv -= 2; | ||
1096 | elv += 2; | ||
1097 | } | ||
1098 | |||
1099 | features = (prev->params.params[0].features & active) | 1089 | features = (prev->params.params[0].features & active) |
1100 | | (prev->params.params[1].features & ~active); | 1090 | | (prev->params.params[1].features & ~active); |
1101 | 1091 | ||
@@ -1849,6 +1839,18 @@ static void preview_try_crop(struct isp_prev_device *prev, | |||
1849 | right -= 2; | 1839 | right -= 2; |
1850 | } | 1840 | } |
1851 | 1841 | ||
1842 | /* The CFA filter crops 4 lines and 4 columns in Bayer mode, and 2 lines | ||
1843 | * and no columns in other modes. Increase the margins based on the sink | ||
1844 | * format. | ||
1845 | */ | ||
1846 | if (sink->code != V4L2_MBUS_FMT_Y8_1X8 && | ||
1847 | sink->code != V4L2_MBUS_FMT_Y10_1X10) { | ||
1848 | left += 2; | ||
1849 | right -= 2; | ||
1850 | top += 2; | ||
1851 | bottom -= 2; | ||
1852 | } | ||
1853 | |||
1852 | /* Restrict left/top to even values to keep the Bayer pattern. */ | 1854 | /* Restrict left/top to even values to keep the Bayer pattern. */ |
1853 | crop->left &= ~1; | 1855 | crop->left &= ~1; |
1854 | crop->top &= ~1; | 1856 | crop->top &= ~1; |
diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c index 15bf3eab2224..e15f01342058 100644 --- a/drivers/media/platform/omap3isp/ispqueue.c +++ b/drivers/media/platform/omap3isp/ispqueue.c | |||
@@ -366,7 +366,7 @@ static int isp_video_buffer_prepare_pfnmap(struct isp_video_buffer *buf) | |||
366 | unsigned long this_pfn; | 366 | unsigned long this_pfn; |
367 | unsigned long start; | 367 | unsigned long start; |
368 | unsigned long end; | 368 | unsigned long end; |
369 | dma_addr_t pa; | 369 | dma_addr_t pa = 0; |
370 | int ret = -EFAULT; | 370 | int ret = -EFAULT; |
371 | 371 | ||
372 | start = buf->vbuf.m.userptr; | 372 | start = buf->vbuf.m.userptr; |
@@ -419,7 +419,7 @@ done: | |||
419 | static int isp_video_buffer_prepare_vm_flags(struct isp_video_buffer *buf) | 419 | static int isp_video_buffer_prepare_vm_flags(struct isp_video_buffer *buf) |
420 | { | 420 | { |
421 | struct vm_area_struct *vma; | 421 | struct vm_area_struct *vma; |
422 | pgprot_t vm_page_prot; | 422 | pgprot_t uninitialized_var(vm_page_prot); |
423 | unsigned long start; | 423 | unsigned long start; |
424 | unsigned long end; | 424 | unsigned long end; |
425 | int ret = -EFAULT; | 425 | int ret = -EFAULT; |
@@ -674,6 +674,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue, | |||
674 | buf->vbuf.index = i; | 674 | buf->vbuf.index = i; |
675 | buf->vbuf.length = size; | 675 | buf->vbuf.length = size; |
676 | buf->vbuf.type = queue->type; | 676 | buf->vbuf.type = queue->type; |
677 | buf->vbuf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
677 | buf->vbuf.field = V4L2_FIELD_NONE; | 678 | buf->vbuf.field = V4L2_FIELD_NONE; |
678 | buf->vbuf.memory = memory; | 679 | buf->vbuf.memory = memory; |
679 | 680 | ||
diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c index 09a8c9cac5c9..0d0fab1a7b5e 100644 --- a/drivers/media/platform/s3c-camif/camif-core.c +++ b/drivers/media/platform/s3c-camif/camif-core.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pm_runtime.h> | 27 | #include <linux/pm_runtime.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | #include <linux/version.h> | ||
30 | 31 | ||
31 | #include <media/media-device.h> | 32 | #include <media/media-device.h> |
32 | #include <media/v4l2-ctrls.h> | 33 | #include <media/v4l2-ctrls.h> |
diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c index fdb6740248a7..f553cc2a8ee8 100644 --- a/drivers/media/platform/s5p-fimc/fimc-capture.c +++ b/drivers/media/platform/s5p-fimc/fimc-capture.c | |||
@@ -486,6 +486,7 @@ static struct vb2_ops fimc_capture_qops = { | |||
486 | int fimc_capture_ctrls_create(struct fimc_dev *fimc) | 486 | int fimc_capture_ctrls_create(struct fimc_dev *fimc) |
487 | { | 487 | { |
488 | struct fimc_vid_cap *vid_cap = &fimc->vid_cap; | 488 | struct fimc_vid_cap *vid_cap = &fimc->vid_cap; |
489 | struct v4l2_subdev *sensor = fimc->pipeline.subdevs[IDX_SENSOR]; | ||
489 | int ret; | 490 | int ret; |
490 | 491 | ||
491 | if (WARN_ON(vid_cap->ctx == NULL)) | 492 | if (WARN_ON(vid_cap->ctx == NULL)) |
@@ -494,11 +495,13 @@ int fimc_capture_ctrls_create(struct fimc_dev *fimc) | |||
494 | return 0; | 495 | return 0; |
495 | 496 | ||
496 | ret = fimc_ctrls_create(vid_cap->ctx); | 497 | ret = fimc_ctrls_create(vid_cap->ctx); |
497 | if (ret || vid_cap->user_subdev_api || !vid_cap->ctx->ctrls.ready) | 498 | |
499 | if (ret || vid_cap->user_subdev_api || !sensor || | ||
500 | !vid_cap->ctx->ctrls.ready) | ||
498 | return ret; | 501 | return ret; |
499 | 502 | ||
500 | return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrls.handler, | 503 | return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrls.handler, |
501 | fimc->pipeline.subdevs[IDX_SENSOR]->ctrl_handler, NULL); | 504 | sensor->ctrl_handler, NULL); |
502 | } | 505 | } |
503 | 506 | ||
504 | static int fimc_capture_set_default_format(struct fimc_dev *fimc); | 507 | static int fimc_capture_set_default_format(struct fimc_dev *fimc); |
@@ -510,8 +513,8 @@ static int fimc_capture_open(struct file *file) | |||
510 | 513 | ||
511 | dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); | 514 | dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); |
512 | 515 | ||
513 | if (mutex_lock_interruptible(&fimc->lock)) | 516 | fimc_md_graph_lock(fimc); |
514 | return -ERESTARTSYS; | 517 | mutex_lock(&fimc->lock); |
515 | 518 | ||
516 | if (fimc_m2m_active(fimc)) | 519 | if (fimc_m2m_active(fimc)) |
517 | goto unlock; | 520 | goto unlock; |
@@ -546,6 +549,7 @@ static int fimc_capture_open(struct file *file) | |||
546 | } | 549 | } |
547 | unlock: | 550 | unlock: |
548 | mutex_unlock(&fimc->lock); | 551 | mutex_unlock(&fimc->lock); |
552 | fimc_md_graph_unlock(fimc); | ||
549 | return ret; | 553 | return ret; |
550 | } | 554 | } |
551 | 555 | ||
@@ -626,8 +630,8 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx, | |||
626 | { | 630 | { |
627 | bool rotation = ctx->rotation == 90 || ctx->rotation == 270; | 631 | bool rotation = ctx->rotation == 90 || ctx->rotation == 270; |
628 | struct fimc_dev *fimc = ctx->fimc_dev; | 632 | struct fimc_dev *fimc = ctx->fimc_dev; |
629 | struct fimc_variant *var = fimc->variant; | 633 | const struct fimc_variant *var = fimc->variant; |
630 | struct fimc_pix_limit *pl = var->pix_limit; | 634 | const struct fimc_pix_limit *pl = var->pix_limit; |
631 | struct fimc_frame *dst = &ctx->d_frame; | 635 | struct fimc_frame *dst = &ctx->d_frame; |
632 | u32 depth, min_w, max_w, min_h, align_h = 3; | 636 | u32 depth, min_w, max_w, min_h, align_h = 3; |
633 | u32 mask = FMT_FLAGS_CAM; | 637 | u32 mask = FMT_FLAGS_CAM; |
@@ -699,8 +703,8 @@ static void fimc_capture_try_selection(struct fimc_ctx *ctx, | |||
699 | { | 703 | { |
700 | bool rotate = ctx->rotation == 90 || ctx->rotation == 270; | 704 | bool rotate = ctx->rotation == 90 || ctx->rotation == 270; |
701 | struct fimc_dev *fimc = ctx->fimc_dev; | 705 | struct fimc_dev *fimc = ctx->fimc_dev; |
702 | struct fimc_variant *var = fimc->variant; | 706 | const struct fimc_variant *var = fimc->variant; |
703 | struct fimc_pix_limit *pl = var->pix_limit; | 707 | const struct fimc_pix_limit *pl = var->pix_limit; |
704 | struct fimc_frame *sink = &ctx->s_frame; | 708 | struct fimc_frame *sink = &ctx->s_frame; |
705 | u32 max_w, max_h, min_w = 0, min_h = 0, min_sz; | 709 | u32 max_w, max_h, min_w = 0, min_h = 0, min_sz; |
706 | u32 align_sz = 0, align_h = 4; | 710 | u32 align_sz = 0, align_h = 4; |
@@ -793,6 +797,21 @@ static int fimc_cap_enum_fmt_mplane(struct file *file, void *priv, | |||
793 | return 0; | 797 | return 0; |
794 | } | 798 | } |
795 | 799 | ||
800 | static struct media_entity *fimc_pipeline_get_head(struct media_entity *me) | ||
801 | { | ||
802 | struct media_pad *pad = &me->pads[0]; | ||
803 | |||
804 | while (!(pad->flags & MEDIA_PAD_FL_SOURCE)) { | ||
805 | pad = media_entity_remote_source(pad); | ||
806 | if (!pad) | ||
807 | break; | ||
808 | me = pad->entity; | ||
809 | pad = &me->pads[0]; | ||
810 | } | ||
811 | |||
812 | return me; | ||
813 | } | ||
814 | |||
796 | /** | 815 | /** |
797 | * fimc_pipeline_try_format - negotiate and/or set formats at pipeline | 816 | * fimc_pipeline_try_format - negotiate and/or set formats at pipeline |
798 | * elements | 817 | * elements |
@@ -808,19 +827,23 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, | |||
808 | { | 827 | { |
809 | struct fimc_dev *fimc = ctx->fimc_dev; | 828 | struct fimc_dev *fimc = ctx->fimc_dev; |
810 | struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR]; | 829 | struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR]; |
811 | struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS]; | ||
812 | struct v4l2_subdev_format sfmt; | 830 | struct v4l2_subdev_format sfmt; |
813 | struct v4l2_mbus_framefmt *mf = &sfmt.format; | 831 | struct v4l2_mbus_framefmt *mf = &sfmt.format; |
814 | struct fimc_fmt *ffmt = NULL; | 832 | struct media_entity *me; |
815 | int ret, i = 0; | 833 | struct fimc_fmt *ffmt; |
834 | struct media_pad *pad; | ||
835 | int ret, i = 1; | ||
836 | u32 fcc; | ||
816 | 837 | ||
817 | if (WARN_ON(!sd || !tfmt)) | 838 | if (WARN_ON(!sd || !tfmt)) |
818 | return -EINVAL; | 839 | return -EINVAL; |
819 | 840 | ||
820 | memset(&sfmt, 0, sizeof(sfmt)); | 841 | memset(&sfmt, 0, sizeof(sfmt)); |
821 | sfmt.format = *tfmt; | 842 | sfmt.format = *tfmt; |
822 | |||
823 | sfmt.which = set ? V4L2_SUBDEV_FORMAT_ACTIVE : V4L2_SUBDEV_FORMAT_TRY; | 843 | sfmt.which = set ? V4L2_SUBDEV_FORMAT_ACTIVE : V4L2_SUBDEV_FORMAT_TRY; |
844 | |||
845 | me = fimc_pipeline_get_head(&sd->entity); | ||
846 | |||
824 | while (1) { | 847 | while (1) { |
825 | ffmt = fimc_find_format(NULL, mf->code != 0 ? &mf->code : NULL, | 848 | ffmt = fimc_find_format(NULL, mf->code != 0 ? &mf->code : NULL, |
826 | FMT_FLAGS_CAM, i++); | 849 | FMT_FLAGS_CAM, i++); |
@@ -833,40 +856,52 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, | |||
833 | } | 856 | } |
834 | mf->code = tfmt->code = ffmt->mbus_code; | 857 | mf->code = tfmt->code = ffmt->mbus_code; |
835 | 858 | ||
836 | ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt); | 859 | /* set format on all pipeline subdevs */ |
837 | if (ret) | 860 | while (me != &fimc->vid_cap.subdev.entity) { |
838 | return ret; | 861 | sd = media_entity_to_v4l2_subdev(me); |
839 | if (mf->code != tfmt->code) { | 862 | |
840 | mf->code = 0; | 863 | sfmt.pad = 0; |
841 | continue; | 864 | ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt); |
865 | if (ret) | ||
866 | return ret; | ||
867 | |||
868 | if (me->pads[0].flags & MEDIA_PAD_FL_SINK) { | ||
869 | sfmt.pad = me->num_pads - 1; | ||
870 | mf->code = tfmt->code; | ||
871 | ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, | ||
872 | &sfmt); | ||
873 | if (ret) | ||
874 | return ret; | ||
875 | } | ||
876 | |||
877 | pad = media_entity_remote_source(&me->pads[sfmt.pad]); | ||
878 | if (!pad) | ||
879 | return -EINVAL; | ||
880 | me = pad->entity; | ||
842 | } | 881 | } |
843 | if (mf->width != tfmt->width || mf->height != tfmt->height) { | ||
844 | u32 fcc = ffmt->fourcc; | ||
845 | tfmt->width = mf->width; | ||
846 | tfmt->height = mf->height; | ||
847 | ffmt = fimc_capture_try_format(ctx, | ||
848 | &tfmt->width, &tfmt->height, | ||
849 | NULL, &fcc, FIMC_SD_PAD_SOURCE); | ||
850 | if (ffmt && ffmt->mbus_code) | ||
851 | mf->code = ffmt->mbus_code; | ||
852 | if (mf->width != tfmt->width || | ||
853 | mf->height != tfmt->height) | ||
854 | continue; | ||
855 | tfmt->code = mf->code; | ||
856 | } | ||
857 | if (csis) | ||
858 | ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt); | ||
859 | 882 | ||
860 | if (mf->code == tfmt->code && | 883 | if (mf->code != tfmt->code) |
861 | mf->width == tfmt->width && mf->height == tfmt->height) | 884 | continue; |
862 | break; | 885 | |
886 | fcc = ffmt->fourcc; | ||
887 | tfmt->width = mf->width; | ||
888 | tfmt->height = mf->height; | ||
889 | ffmt = fimc_capture_try_format(ctx, &tfmt->width, &tfmt->height, | ||
890 | NULL, &fcc, FIMC_SD_PAD_SINK); | ||
891 | ffmt = fimc_capture_try_format(ctx, &tfmt->width, &tfmt->height, | ||
892 | NULL, &fcc, FIMC_SD_PAD_SOURCE); | ||
893 | if (ffmt && ffmt->mbus_code) | ||
894 | mf->code = ffmt->mbus_code; | ||
895 | if (mf->width != tfmt->width || mf->height != tfmt->height) | ||
896 | continue; | ||
897 | tfmt->code = mf->code; | ||
898 | break; | ||
863 | } | 899 | } |
864 | 900 | ||
865 | if (fmt_id && ffmt) | 901 | if (fmt_id && ffmt) |
866 | *fmt_id = ffmt; | 902 | *fmt_id = ffmt; |
867 | *tfmt = *mf; | 903 | *tfmt = *mf; |
868 | 904 | ||
869 | dbg("code: 0x%x, %dx%d, %p", mf->code, mf->width, mf->height, ffmt); | ||
870 | return 0; | 905 | return 0; |
871 | } | 906 | } |
872 | 907 | ||
@@ -884,14 +919,16 @@ static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor, | |||
884 | { | 919 | { |
885 | struct v4l2_mbus_frame_desc fd; | 920 | struct v4l2_mbus_frame_desc fd; |
886 | int i, ret; | 921 | int i, ret; |
922 | int pad; | ||
887 | 923 | ||
888 | for (i = 0; i < num_planes; i++) | 924 | for (i = 0; i < num_planes; i++) |
889 | fd.entry[i].length = plane_fmt[i].sizeimage; | 925 | fd.entry[i].length = plane_fmt[i].sizeimage; |
890 | 926 | ||
927 | pad = sensor->entity.num_pads - 1; | ||
891 | if (try) | 928 | if (try) |
892 | ret = v4l2_subdev_call(sensor, pad, set_frame_desc, 0, &fd); | 929 | ret = v4l2_subdev_call(sensor, pad, set_frame_desc, pad, &fd); |
893 | else | 930 | else |
894 | ret = v4l2_subdev_call(sensor, pad, get_frame_desc, 0, &fd); | 931 | ret = v4l2_subdev_call(sensor, pad, get_frame_desc, pad, &fd); |
895 | 932 | ||
896 | if (ret < 0) | 933 | if (ret < 0) |
897 | return ret; | 934 | return ret; |
@@ -916,9 +953,9 @@ static int fimc_cap_g_fmt_mplane(struct file *file, void *fh, | |||
916 | struct v4l2_format *f) | 953 | struct v4l2_format *f) |
917 | { | 954 | { |
918 | struct fimc_dev *fimc = video_drvdata(file); | 955 | struct fimc_dev *fimc = video_drvdata(file); |
919 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; | ||
920 | 956 | ||
921 | return fimc_fill_format(&ctx->d_frame, f); | 957 | __fimc_get_format(&fimc->vid_cap.ctx->d_frame, f); |
958 | return 0; | ||
922 | } | 959 | } |
923 | 960 | ||
924 | static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, | 961 | static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, |
@@ -929,6 +966,10 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, | |||
929 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; | 966 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; |
930 | struct v4l2_mbus_framefmt mf; | 967 | struct v4l2_mbus_framefmt mf; |
931 | struct fimc_fmt *ffmt = NULL; | 968 | struct fimc_fmt *ffmt = NULL; |
969 | int ret = 0; | ||
970 | |||
971 | fimc_md_graph_lock(fimc); | ||
972 | mutex_lock(&fimc->lock); | ||
932 | 973 | ||
933 | if (fimc_jpeg_fourcc(pix->pixelformat)) { | 974 | if (fimc_jpeg_fourcc(pix->pixelformat)) { |
934 | fimc_capture_try_format(ctx, &pix->width, &pix->height, | 975 | fimc_capture_try_format(ctx, &pix->width, &pix->height, |
@@ -940,16 +981,16 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, | |||
940 | ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, | 981 | ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, |
941 | NULL, &pix->pixelformat, | 982 | NULL, &pix->pixelformat, |
942 | FIMC_SD_PAD_SOURCE); | 983 | FIMC_SD_PAD_SOURCE); |
943 | if (!ffmt) | 984 | if (!ffmt) { |
944 | return -EINVAL; | 985 | ret = -EINVAL; |
986 | goto unlock; | ||
987 | } | ||
945 | 988 | ||
946 | if (!fimc->vid_cap.user_subdev_api) { | 989 | if (!fimc->vid_cap.user_subdev_api) { |
947 | mf.width = pix->width; | 990 | mf.width = pix->width; |
948 | mf.height = pix->height; | 991 | mf.height = pix->height; |
949 | mf.code = ffmt->mbus_code; | 992 | mf.code = ffmt->mbus_code; |
950 | fimc_md_graph_lock(fimc); | ||
951 | fimc_pipeline_try_format(ctx, &mf, &ffmt, false); | 993 | fimc_pipeline_try_format(ctx, &mf, &ffmt, false); |
952 | fimc_md_graph_unlock(fimc); | ||
953 | pix->width = mf.width; | 994 | pix->width = mf.width; |
954 | pix->height = mf.height; | 995 | pix->height = mf.height; |
955 | if (ffmt) | 996 | if (ffmt) |
@@ -961,8 +1002,11 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, | |||
961 | if (ffmt->flags & FMT_FLAGS_COMPRESSED) | 1002 | if (ffmt->flags & FMT_FLAGS_COMPRESSED) |
962 | fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], | 1003 | fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], |
963 | pix->plane_fmt, ffmt->memplanes, true); | 1004 | pix->plane_fmt, ffmt->memplanes, true); |
1005 | unlock: | ||
1006 | mutex_unlock(&fimc->lock); | ||
1007 | fimc_md_graph_unlock(fimc); | ||
964 | 1008 | ||
965 | return 0; | 1009 | return ret; |
966 | } | 1010 | } |
967 | 1011 | ||
968 | static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, | 1012 | static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, |
@@ -979,7 +1023,8 @@ static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, | |||
979 | clear_bit(ST_CAPT_JPEG, &ctx->fimc_dev->state); | 1023 | clear_bit(ST_CAPT_JPEG, &ctx->fimc_dev->state); |
980 | } | 1024 | } |
981 | 1025 | ||
982 | static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f) | 1026 | static int __fimc_capture_set_format(struct fimc_dev *fimc, |
1027 | struct v4l2_format *f) | ||
983 | { | 1028 | { |
984 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; | 1029 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; |
985 | struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; | 1030 | struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; |
@@ -1014,12 +1059,10 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f) | |||
1014 | mf->code = ff->fmt->mbus_code; | 1059 | mf->code = ff->fmt->mbus_code; |
1015 | mf->width = pix->width; | 1060 | mf->width = pix->width; |
1016 | mf->height = pix->height; | 1061 | mf->height = pix->height; |
1017 | |||
1018 | fimc_md_graph_lock(fimc); | ||
1019 | ret = fimc_pipeline_try_format(ctx, mf, &s_fmt, true); | 1062 | ret = fimc_pipeline_try_format(ctx, mf, &s_fmt, true); |
1020 | fimc_md_graph_unlock(fimc); | ||
1021 | if (ret) | 1063 | if (ret) |
1022 | return ret; | 1064 | return ret; |
1065 | |||
1023 | pix->width = mf->width; | 1066 | pix->width = mf->width; |
1024 | pix->height = mf->height; | 1067 | pix->height = mf->height; |
1025 | } | 1068 | } |
@@ -1034,8 +1077,10 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f) | |||
1034 | return ret; | 1077 | return ret; |
1035 | } | 1078 | } |
1036 | 1079 | ||
1037 | for (i = 0; i < ff->fmt->memplanes; i++) | 1080 | for (i = 0; i < ff->fmt->memplanes; i++) { |
1081 | ff->bytesperline[i] = pix->plane_fmt[i].bytesperline; | ||
1038 | ff->payload[i] = pix->plane_fmt[i].sizeimage; | 1082 | ff->payload[i] = pix->plane_fmt[i].sizeimage; |
1083 | } | ||
1039 | 1084 | ||
1040 | set_frame_bounds(ff, pix->width, pix->height); | 1085 | set_frame_bounds(ff, pix->width, pix->height); |
1041 | /* Reset the composition rectangle if not yet configured */ | 1086 | /* Reset the composition rectangle if not yet configured */ |
@@ -1058,8 +1103,23 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, | |||
1058 | struct v4l2_format *f) | 1103 | struct v4l2_format *f) |
1059 | { | 1104 | { |
1060 | struct fimc_dev *fimc = video_drvdata(file); | 1105 | struct fimc_dev *fimc = video_drvdata(file); |
1106 | int ret; | ||
1107 | |||
1108 | fimc_md_graph_lock(fimc); | ||
1109 | mutex_lock(&fimc->lock); | ||
1110 | /* | ||
1111 | * The graph is walked within __fimc_capture_set_format() to set | ||
1112 | * the format at subdevs thus the graph mutex needs to be held at | ||
1113 | * this point and acquired before the video mutex, to avoid AB-BA | ||
1114 | * deadlock when fimc_md_link_notify() is called by other thread. | ||
1115 | * Ideally the graph walking and setting format at the whole pipeline | ||
1116 | * should be removed from this driver and handled in userspace only. | ||
1117 | */ | ||
1118 | ret = __fimc_capture_set_format(fimc, f); | ||
1061 | 1119 | ||
1062 | return fimc_capture_set_format(fimc, f); | 1120 | mutex_unlock(&fimc->lock); |
1121 | fimc_md_graph_unlock(fimc); | ||
1122 | return ret; | ||
1063 | } | 1123 | } |
1064 | 1124 | ||
1065 | static int fimc_cap_enum_input(struct file *file, void *priv, | 1125 | static int fimc_cap_enum_input(struct file *file, void *priv, |
@@ -1528,6 +1588,10 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd, | |||
1528 | *mf = fmt->format; | 1588 | *mf = fmt->format; |
1529 | return 0; | 1589 | return 0; |
1530 | } | 1590 | } |
1591 | /* There must be a bug in the driver if this happens */ | ||
1592 | if (WARN_ON(ffmt == NULL)) | ||
1593 | return -EINVAL; | ||
1594 | |||
1531 | /* Update RGB Alpha control state and value range */ | 1595 | /* Update RGB Alpha control state and value range */ |
1532 | fimc_alpha_ctrl_update(ctx); | 1596 | fimc_alpha_ctrl_update(ctx); |
1533 | 1597 | ||
@@ -1624,16 +1688,6 @@ static int fimc_subdev_set_selection(struct v4l2_subdev *sd, | |||
1624 | fimc_capture_try_selection(ctx, r, V4L2_SEL_TGT_CROP); | 1688 | fimc_capture_try_selection(ctx, r, V4L2_SEL_TGT_CROP); |
1625 | 1689 | ||
1626 | switch (sel->target) { | 1690 | switch (sel->target) { |
1627 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
1628 | f = &ctx->d_frame; | ||
1629 | case V4L2_SEL_TGT_CROP_BOUNDS: | ||
1630 | r->width = f->o_width; | ||
1631 | r->height = f->o_height; | ||
1632 | r->left = 0; | ||
1633 | r->top = 0; | ||
1634 | mutex_unlock(&fimc->lock); | ||
1635 | return 0; | ||
1636 | |||
1637 | case V4L2_SEL_TGT_CROP: | 1691 | case V4L2_SEL_TGT_CROP: |
1638 | try_sel = v4l2_subdev_get_try_crop(fh, sel->pad); | 1692 | try_sel = v4l2_subdev_get_try_crop(fh, sel->pad); |
1639 | break; | 1693 | break; |
@@ -1652,9 +1706,9 @@ static int fimc_subdev_set_selection(struct v4l2_subdev *sd, | |||
1652 | spin_lock_irqsave(&fimc->slock, flags); | 1706 | spin_lock_irqsave(&fimc->slock, flags); |
1653 | set_frame_crop(f, r->left, r->top, r->width, r->height); | 1707 | set_frame_crop(f, r->left, r->top, r->width, r->height); |
1654 | set_bit(ST_CAPT_APPLY_CFG, &fimc->state); | 1708 | set_bit(ST_CAPT_APPLY_CFG, &fimc->state); |
1655 | spin_unlock_irqrestore(&fimc->slock, flags); | ||
1656 | if (sel->target == V4L2_SEL_TGT_COMPOSE) | 1709 | if (sel->target == V4L2_SEL_TGT_COMPOSE) |
1657 | ctx->state |= FIMC_COMPOSE; | 1710 | ctx->state |= FIMC_COMPOSE; |
1711 | spin_unlock_irqrestore(&fimc->slock, flags); | ||
1658 | } | 1712 | } |
1659 | 1713 | ||
1660 | dbg("target %#x: (%d,%d)/%dx%d", sel->target, r->left, r->top, | 1714 | dbg("target %#x: (%d,%d)/%dx%d", sel->target, r->left, r->top, |
@@ -1690,7 +1744,7 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc) | |||
1690 | }, | 1744 | }, |
1691 | }; | 1745 | }; |
1692 | 1746 | ||
1693 | return fimc_capture_set_format(fimc, &fmt); | 1747 | return __fimc_capture_set_format(fimc, &fmt); |
1694 | } | 1748 | } |
1695 | 1749 | ||
1696 | /* fimc->lock must be already initialized */ | 1750 | /* fimc->lock must be already initialized */ |
@@ -1752,6 +1806,12 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, | |||
1752 | ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0); | 1806 | ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0); |
1753 | if (ret) | 1807 | if (ret) |
1754 | goto err_ent; | 1808 | goto err_ent; |
1809 | /* | ||
1810 | * For proper order of acquiring/releasing the video | ||
1811 | * and the graph mutex. | ||
1812 | */ | ||
1813 | v4l2_disable_ioctl_locking(vfd, VIDIOC_TRY_FMT); | ||
1814 | v4l2_disable_ioctl_locking(vfd, VIDIOC_S_FMT); | ||
1755 | 1815 | ||
1756 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); | 1816 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); |
1757 | if (ret) | 1817 | if (ret) |
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c index acc0f84ffa56..e3916bde45cf 100644 --- a/drivers/media/platform/s5p-fimc/fimc-core.c +++ b/drivers/media/platform/s5p-fimc/fimc-core.c | |||
@@ -241,7 +241,7 @@ static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift) | |||
241 | 241 | ||
242 | int fimc_set_scaler_info(struct fimc_ctx *ctx) | 242 | int fimc_set_scaler_info(struct fimc_ctx *ctx) |
243 | { | 243 | { |
244 | struct fimc_variant *variant = ctx->fimc_dev->variant; | 244 | const struct fimc_variant *variant = ctx->fimc_dev->variant; |
245 | struct device *dev = &ctx->fimc_dev->pdev->dev; | 245 | struct device *dev = &ctx->fimc_dev->pdev->dev; |
246 | struct fimc_scaler *sc = &ctx->scaler; | 246 | struct fimc_scaler *sc = &ctx->scaler; |
247 | struct fimc_frame *s_frame = &ctx->s_frame; | 247 | struct fimc_frame *s_frame = &ctx->s_frame; |
@@ -257,14 +257,14 @@ int fimc_set_scaler_info(struct fimc_ctx *ctx) | |||
257 | ty = d_frame->height; | 257 | ty = d_frame->height; |
258 | } | 258 | } |
259 | if (tx <= 0 || ty <= 0) { | 259 | if (tx <= 0 || ty <= 0) { |
260 | dev_err(dev, "Invalid target size: %dx%d", tx, ty); | 260 | dev_err(dev, "Invalid target size: %dx%d\n", tx, ty); |
261 | return -EINVAL; | 261 | return -EINVAL; |
262 | } | 262 | } |
263 | 263 | ||
264 | sx = s_frame->width; | 264 | sx = s_frame->width; |
265 | sy = s_frame->height; | 265 | sy = s_frame->height; |
266 | if (sx <= 0 || sy <= 0) { | 266 | if (sx <= 0 || sy <= 0) { |
267 | dev_err(dev, "Invalid source size: %dx%d", sx, sy); | 267 | dev_err(dev, "Invalid source size: %dx%d\n", sx, sy); |
268 | return -EINVAL; | 268 | return -EINVAL; |
269 | } | 269 | } |
270 | sc->real_width = sx; | 270 | sc->real_width = sx; |
@@ -440,7 +440,7 @@ void fimc_set_yuv_order(struct fimc_ctx *ctx) | |||
440 | 440 | ||
441 | void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f) | 441 | void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f) |
442 | { | 442 | { |
443 | struct fimc_variant *variant = ctx->fimc_dev->variant; | 443 | const struct fimc_variant *variant = ctx->fimc_dev->variant; |
444 | u32 i, depth = 0; | 444 | u32 i, depth = 0; |
445 | 445 | ||
446 | for (i = 0; i < f->fmt->colplanes; i++) | 446 | for (i = 0; i < f->fmt->colplanes; i++) |
@@ -524,8 +524,7 @@ static int fimc_set_color_effect(struct fimc_ctx *ctx, enum v4l2_colorfx colorfx | |||
524 | static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl) | 524 | static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl) |
525 | { | 525 | { |
526 | struct fimc_dev *fimc = ctx->fimc_dev; | 526 | struct fimc_dev *fimc = ctx->fimc_dev; |
527 | struct fimc_variant *variant = fimc->variant; | 527 | const struct fimc_variant *variant = fimc->variant; |
528 | unsigned int flags = FIMC_DST_FMT | FIMC_SRC_FMT; | ||
529 | int ret = 0; | 528 | int ret = 0; |
530 | 529 | ||
531 | if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) | 530 | if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) |
@@ -541,8 +540,7 @@ static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl) | |||
541 | break; | 540 | break; |
542 | 541 | ||
543 | case V4L2_CID_ROTATE: | 542 | case V4L2_CID_ROTATE: |
544 | if (fimc_capture_pending(fimc) || | 543 | if (fimc_capture_pending(fimc)) { |
545 | (ctx->state & flags) == flags) { | ||
546 | ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, | 544 | ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, |
547 | ctx->s_frame.height, ctx->d_frame.width, | 545 | ctx->s_frame.height, ctx->d_frame.width, |
548 | ctx->d_frame.height, ctrl->val); | 546 | ctx->d_frame.height, ctrl->val); |
@@ -591,7 +589,7 @@ static const struct v4l2_ctrl_ops fimc_ctrl_ops = { | |||
591 | 589 | ||
592 | int fimc_ctrls_create(struct fimc_ctx *ctx) | 590 | int fimc_ctrls_create(struct fimc_ctx *ctx) |
593 | { | 591 | { |
594 | struct fimc_variant *variant = ctx->fimc_dev->variant; | 592 | const struct fimc_variant *variant = ctx->fimc_dev->variant; |
595 | unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt); | 593 | unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt); |
596 | struct fimc_ctrls *ctrls = &ctx->ctrls; | 594 | struct fimc_ctrls *ctrls = &ctx->ctrls; |
597 | struct v4l2_ctrl_handler *handler = &ctrls->handler; | 595 | struct v4l2_ctrl_handler *handler = &ctrls->handler; |
@@ -691,7 +689,7 @@ void fimc_alpha_ctrl_update(struct fimc_ctx *ctx) | |||
691 | v4l2_ctrl_unlock(ctrl); | 689 | v4l2_ctrl_unlock(ctrl); |
692 | } | 690 | } |
693 | 691 | ||
694 | int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f) | 692 | void __fimc_get_format(struct fimc_frame *frame, struct v4l2_format *f) |
695 | { | 693 | { |
696 | struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; | 694 | struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; |
697 | int i; | 695 | int i; |
@@ -704,35 +702,9 @@ int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f) | |||
704 | pixm->num_planes = frame->fmt->memplanes; | 702 | pixm->num_planes = frame->fmt->memplanes; |
705 | 703 | ||
706 | for (i = 0; i < pixm->num_planes; ++i) { | 704 | for (i = 0; i < pixm->num_planes; ++i) { |
707 | int bpl = frame->f_width; | 705 | pixm->plane_fmt[i].bytesperline = frame->bytesperline[i]; |
708 | if (frame->fmt->colplanes == 1) /* packed formats */ | 706 | pixm->plane_fmt[i].sizeimage = frame->payload[i]; |
709 | bpl = (bpl * frame->fmt->depth[0]) / 8; | ||
710 | pixm->plane_fmt[i].bytesperline = bpl; | ||
711 | |||
712 | if (frame->fmt->flags & FMT_FLAGS_COMPRESSED) { | ||
713 | pixm->plane_fmt[i].sizeimage = frame->payload[i]; | ||
714 | continue; | ||
715 | } | ||
716 | pixm->plane_fmt[i].sizeimage = (frame->o_width * | ||
717 | frame->o_height * frame->fmt->depth[i]) / 8; | ||
718 | } | 707 | } |
719 | return 0; | ||
720 | } | ||
721 | |||
722 | void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f) | ||
723 | { | ||
724 | struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; | ||
725 | |||
726 | frame->f_width = pixm->plane_fmt[0].bytesperline; | ||
727 | if (frame->fmt->colplanes == 1) | ||
728 | frame->f_width = (frame->f_width * 8) / frame->fmt->depth[0]; | ||
729 | frame->f_height = pixm->height; | ||
730 | frame->width = pixm->width; | ||
731 | frame->height = pixm->height; | ||
732 | frame->o_width = pixm->width; | ||
733 | frame->o_height = pixm->height; | ||
734 | frame->offs_h = 0; | ||
735 | frame->offs_v = 0; | ||
736 | } | 708 | } |
737 | 709 | ||
738 | /** | 710 | /** |
@@ -765,9 +737,16 @@ void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height, | |||
765 | if (fmt->colplanes == 1 && /* Packed */ | 737 | if (fmt->colplanes == 1 && /* Packed */ |
766 | (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width)) | 738 | (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width)) |
767 | bpl = (pix->width * fmt->depth[0]) / 8; | 739 | bpl = (pix->width * fmt->depth[0]) / 8; |
768 | 740 | /* | |
769 | if (i == 0) /* Same bytesperline for each plane. */ | 741 | * Currently bytesperline for each plane is same, except |
742 | * V4L2_PIX_FMT_YUV420M format. This calculation may need | ||
743 | * to be changed when other multi-planar formats are added | ||
744 | * to the fimc_formats[] array. | ||
745 | */ | ||
746 | if (i == 0) | ||
770 | bytesperline = bpl; | 747 | bytesperline = bpl; |
748 | else if (i == 1 && fmt->memplanes == 3) | ||
749 | bytesperline /= 2; | ||
771 | 750 | ||
772 | plane_fmt->bytesperline = bytesperline; | 751 | plane_fmt->bytesperline = bytesperline; |
773 | plane_fmt->sizeimage = max((pix->width * pix->height * | 752 | plane_fmt->sizeimage = max((pix->width * pix->height * |
@@ -811,11 +790,11 @@ static void fimc_clk_put(struct fimc_dev *fimc) | |||
811 | { | 790 | { |
812 | int i; | 791 | int i; |
813 | for (i = 0; i < MAX_FIMC_CLOCKS; i++) { | 792 | for (i = 0; i < MAX_FIMC_CLOCKS; i++) { |
814 | if (IS_ERR_OR_NULL(fimc->clock[i])) | 793 | if (IS_ERR(fimc->clock[i])) |
815 | continue; | 794 | continue; |
816 | clk_unprepare(fimc->clock[i]); | 795 | clk_unprepare(fimc->clock[i]); |
817 | clk_put(fimc->clock[i]); | 796 | clk_put(fimc->clock[i]); |
818 | fimc->clock[i] = NULL; | 797 | fimc->clock[i] = ERR_PTR(-EINVAL); |
819 | } | 798 | } |
820 | } | 799 | } |
821 | 800 | ||
@@ -823,14 +802,19 @@ static int fimc_clk_get(struct fimc_dev *fimc) | |||
823 | { | 802 | { |
824 | int i, ret; | 803 | int i, ret; |
825 | 804 | ||
805 | for (i = 0; i < MAX_FIMC_CLOCKS; i++) | ||
806 | fimc->clock[i] = ERR_PTR(-EINVAL); | ||
807 | |||
826 | for (i = 0; i < MAX_FIMC_CLOCKS; i++) { | 808 | for (i = 0; i < MAX_FIMC_CLOCKS; i++) { |
827 | fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); | 809 | fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); |
828 | if (IS_ERR(fimc->clock[i])) | 810 | if (IS_ERR(fimc->clock[i])) { |
811 | ret = PTR_ERR(fimc->clock[i]); | ||
829 | goto err; | 812 | goto err; |
813 | } | ||
830 | ret = clk_prepare(fimc->clock[i]); | 814 | ret = clk_prepare(fimc->clock[i]); |
831 | if (ret < 0) { | 815 | if (ret < 0) { |
832 | clk_put(fimc->clock[i]); | 816 | clk_put(fimc->clock[i]); |
833 | fimc->clock[i] = NULL; | 817 | fimc->clock[i] = ERR_PTR(-EINVAL); |
834 | goto err; | 818 | goto err; |
835 | } | 819 | } |
836 | } | 820 | } |
@@ -881,7 +865,7 @@ static int fimc_m2m_resume(struct fimc_dev *fimc) | |||
881 | 865 | ||
882 | static int fimc_probe(struct platform_device *pdev) | 866 | static int fimc_probe(struct platform_device *pdev) |
883 | { | 867 | { |
884 | struct fimc_drvdata *drv_data = fimc_get_drvdata(pdev); | 868 | const struct fimc_drvdata *drv_data = fimc_get_drvdata(pdev); |
885 | struct s5p_platform_fimc *pdata; | 869 | struct s5p_platform_fimc *pdata; |
886 | struct fimc_dev *fimc; | 870 | struct fimc_dev *fimc; |
887 | struct resource *res; | 871 | struct resource *res; |
@@ -922,8 +906,14 @@ static int fimc_probe(struct platform_device *pdev) | |||
922 | ret = fimc_clk_get(fimc); | 906 | ret = fimc_clk_get(fimc); |
923 | if (ret) | 907 | if (ret) |
924 | return ret; | 908 | return ret; |
925 | clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); | 909 | |
926 | clk_enable(fimc->clock[CLK_BUS]); | 910 | ret = clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); |
911 | if (ret < 0) | ||
912 | return ret; | ||
913 | |||
914 | ret = clk_enable(fimc->clock[CLK_BUS]); | ||
915 | if (ret < 0) | ||
916 | return ret; | ||
927 | 917 | ||
928 | ret = devm_request_irq(&pdev->dev, res->start, fimc_irq_handler, | 918 | ret = devm_request_irq(&pdev->dev, res->start, fimc_irq_handler, |
929 | 0, dev_name(&pdev->dev), fimc); | 919 | 0, dev_name(&pdev->dev), fimc); |
@@ -957,6 +947,7 @@ err_pm: | |||
957 | err_sd: | 947 | err_sd: |
958 | fimc_unregister_capture_subdev(fimc); | 948 | fimc_unregister_capture_subdev(fimc); |
959 | err_clk: | 949 | err_clk: |
950 | clk_disable(fimc->clock[CLK_BUS]); | ||
960 | fimc_clk_put(fimc); | 951 | fimc_clk_put(fimc); |
961 | return ret; | 952 | return ret; |
962 | } | 953 | } |
@@ -1051,7 +1042,7 @@ static int fimc_remove(struct platform_device *pdev) | |||
1051 | } | 1042 | } |
1052 | 1043 | ||
1053 | /* Image pixel limits, similar across several FIMC HW revisions. */ | 1044 | /* Image pixel limits, similar across several FIMC HW revisions. */ |
1054 | static struct fimc_pix_limit s5p_pix_limit[4] = { | 1045 | static const struct fimc_pix_limit s5p_pix_limit[4] = { |
1055 | [0] = { | 1046 | [0] = { |
1056 | .scaler_en_w = 3264, | 1047 | .scaler_en_w = 3264, |
1057 | .scaler_dis_w = 8192, | 1048 | .scaler_dis_w = 8192, |
@@ -1086,7 +1077,7 @@ static struct fimc_pix_limit s5p_pix_limit[4] = { | |||
1086 | }, | 1077 | }, |
1087 | }; | 1078 | }; |
1088 | 1079 | ||
1089 | static struct fimc_variant fimc0_variant_s5p = { | 1080 | static const struct fimc_variant fimc0_variant_s5p = { |
1090 | .has_inp_rot = 1, | 1081 | .has_inp_rot = 1, |
1091 | .has_out_rot = 1, | 1082 | .has_out_rot = 1, |
1092 | .has_cam_if = 1, | 1083 | .has_cam_if = 1, |
@@ -1098,7 +1089,7 @@ static struct fimc_variant fimc0_variant_s5p = { | |||
1098 | .pix_limit = &s5p_pix_limit[0], | 1089 | .pix_limit = &s5p_pix_limit[0], |
1099 | }; | 1090 | }; |
1100 | 1091 | ||
1101 | static struct fimc_variant fimc2_variant_s5p = { | 1092 | static const struct fimc_variant fimc2_variant_s5p = { |
1102 | .has_cam_if = 1, | 1093 | .has_cam_if = 1, |
1103 | .min_inp_pixsize = 16, | 1094 | .min_inp_pixsize = 16, |
1104 | .min_out_pixsize = 16, | 1095 | .min_out_pixsize = 16, |
@@ -1108,7 +1099,7 @@ static struct fimc_variant fimc2_variant_s5p = { | |||
1108 | .pix_limit = &s5p_pix_limit[1], | 1099 | .pix_limit = &s5p_pix_limit[1], |
1109 | }; | 1100 | }; |
1110 | 1101 | ||
1111 | static struct fimc_variant fimc0_variant_s5pv210 = { | 1102 | static const struct fimc_variant fimc0_variant_s5pv210 = { |
1112 | .pix_hoff = 1, | 1103 | .pix_hoff = 1, |
1113 | .has_inp_rot = 1, | 1104 | .has_inp_rot = 1, |
1114 | .has_out_rot = 1, | 1105 | .has_out_rot = 1, |
@@ -1121,7 +1112,7 @@ static struct fimc_variant fimc0_variant_s5pv210 = { | |||
1121 | .pix_limit = &s5p_pix_limit[1], | 1112 | .pix_limit = &s5p_pix_limit[1], |
1122 | }; | 1113 | }; |
1123 | 1114 | ||
1124 | static struct fimc_variant fimc1_variant_s5pv210 = { | 1115 | static const struct fimc_variant fimc1_variant_s5pv210 = { |
1125 | .pix_hoff = 1, | 1116 | .pix_hoff = 1, |
1126 | .has_inp_rot = 1, | 1117 | .has_inp_rot = 1, |
1127 | .has_out_rot = 1, | 1118 | .has_out_rot = 1, |
@@ -1135,7 +1126,7 @@ static struct fimc_variant fimc1_variant_s5pv210 = { | |||
1135 | .pix_limit = &s5p_pix_limit[2], | 1126 | .pix_limit = &s5p_pix_limit[2], |
1136 | }; | 1127 | }; |
1137 | 1128 | ||
1138 | static struct fimc_variant fimc2_variant_s5pv210 = { | 1129 | static const struct fimc_variant fimc2_variant_s5pv210 = { |
1139 | .has_cam_if = 1, | 1130 | .has_cam_if = 1, |
1140 | .pix_hoff = 1, | 1131 | .pix_hoff = 1, |
1141 | .min_inp_pixsize = 16, | 1132 | .min_inp_pixsize = 16, |
@@ -1146,7 +1137,7 @@ static struct fimc_variant fimc2_variant_s5pv210 = { | |||
1146 | .pix_limit = &s5p_pix_limit[2], | 1137 | .pix_limit = &s5p_pix_limit[2], |
1147 | }; | 1138 | }; |
1148 | 1139 | ||
1149 | static struct fimc_variant fimc0_variant_exynos4 = { | 1140 | static const struct fimc_variant fimc0_variant_exynos4210 = { |
1150 | .pix_hoff = 1, | 1141 | .pix_hoff = 1, |
1151 | .has_inp_rot = 1, | 1142 | .has_inp_rot = 1, |
1152 | .has_out_rot = 1, | 1143 | .has_out_rot = 1, |
@@ -1162,9 +1153,8 @@ static struct fimc_variant fimc0_variant_exynos4 = { | |||
1162 | .pix_limit = &s5p_pix_limit[1], | 1153 | .pix_limit = &s5p_pix_limit[1], |
1163 | }; | 1154 | }; |
1164 | 1155 | ||
1165 | static struct fimc_variant fimc3_variant_exynos4 = { | 1156 | static const struct fimc_variant fimc3_variant_exynos4210 = { |
1166 | .pix_hoff = 1, | 1157 | .pix_hoff = 1, |
1167 | .has_cam_if = 1, | ||
1168 | .has_cistatus2 = 1, | 1158 | .has_cistatus2 = 1, |
1169 | .has_mainscaler_ext = 1, | 1159 | .has_mainscaler_ext = 1, |
1170 | .has_alpha = 1, | 1160 | .has_alpha = 1, |
@@ -1176,8 +1166,38 @@ static struct fimc_variant fimc3_variant_exynos4 = { | |||
1176 | .pix_limit = &s5p_pix_limit[3], | 1166 | .pix_limit = &s5p_pix_limit[3], |
1177 | }; | 1167 | }; |
1178 | 1168 | ||
1169 | static const struct fimc_variant fimc0_variant_exynos4x12 = { | ||
1170 | .pix_hoff = 1, | ||
1171 | .has_inp_rot = 1, | ||
1172 | .has_out_rot = 1, | ||
1173 | .has_cam_if = 1, | ||
1174 | .has_isp_wb = 1, | ||
1175 | .has_cistatus2 = 1, | ||
1176 | .has_mainscaler_ext = 1, | ||
1177 | .has_alpha = 1, | ||
1178 | .min_inp_pixsize = 16, | ||
1179 | .min_out_pixsize = 16, | ||
1180 | .hor_offs_align = 2, | ||
1181 | .min_vsize_align = 1, | ||
1182 | .out_buf_count = 32, | ||
1183 | .pix_limit = &s5p_pix_limit[1], | ||
1184 | }; | ||
1185 | |||
1186 | static const struct fimc_variant fimc3_variant_exynos4x12 = { | ||
1187 | .pix_hoff = 1, | ||
1188 | .has_cistatus2 = 1, | ||
1189 | .has_mainscaler_ext = 1, | ||
1190 | .has_alpha = 1, | ||
1191 | .min_inp_pixsize = 16, | ||
1192 | .min_out_pixsize = 16, | ||
1193 | .hor_offs_align = 2, | ||
1194 | .min_vsize_align = 1, | ||
1195 | .out_buf_count = 32, | ||
1196 | .pix_limit = &s5p_pix_limit[3], | ||
1197 | }; | ||
1198 | |||
1179 | /* S5PC100 */ | 1199 | /* S5PC100 */ |
1180 | static struct fimc_drvdata fimc_drvdata_s5p = { | 1200 | static const struct fimc_drvdata fimc_drvdata_s5p = { |
1181 | .variant = { | 1201 | .variant = { |
1182 | [0] = &fimc0_variant_s5p, | 1202 | [0] = &fimc0_variant_s5p, |
1183 | [1] = &fimc0_variant_s5p, | 1203 | [1] = &fimc0_variant_s5p, |
@@ -1188,7 +1208,7 @@ static struct fimc_drvdata fimc_drvdata_s5p = { | |||
1188 | }; | 1208 | }; |
1189 | 1209 | ||
1190 | /* S5PV210, S5PC110 */ | 1210 | /* S5PV210, S5PC110 */ |
1191 | static struct fimc_drvdata fimc_drvdata_s5pv210 = { | 1211 | static const struct fimc_drvdata fimc_drvdata_s5pv210 = { |
1192 | .variant = { | 1212 | .variant = { |
1193 | [0] = &fimc0_variant_s5pv210, | 1213 | [0] = &fimc0_variant_s5pv210, |
1194 | [1] = &fimc1_variant_s5pv210, | 1214 | [1] = &fimc1_variant_s5pv210, |
@@ -1199,18 +1219,30 @@ static struct fimc_drvdata fimc_drvdata_s5pv210 = { | |||
1199 | }; | 1219 | }; |
1200 | 1220 | ||
1201 | /* EXYNOS4210, S5PV310, S5PC210 */ | 1221 | /* EXYNOS4210, S5PV310, S5PC210 */ |
1202 | static struct fimc_drvdata fimc_drvdata_exynos4 = { | 1222 | static const struct fimc_drvdata fimc_drvdata_exynos4210 = { |
1223 | .variant = { | ||
1224 | [0] = &fimc0_variant_exynos4210, | ||
1225 | [1] = &fimc0_variant_exynos4210, | ||
1226 | [2] = &fimc0_variant_exynos4210, | ||
1227 | [3] = &fimc3_variant_exynos4210, | ||
1228 | }, | ||
1229 | .num_entities = 4, | ||
1230 | .lclk_frequency = 166000000UL, | ||
1231 | }; | ||
1232 | |||
1233 | /* EXYNOS4212, EXYNOS4412 */ | ||
1234 | static const struct fimc_drvdata fimc_drvdata_exynos4x12 = { | ||
1203 | .variant = { | 1235 | .variant = { |
1204 | [0] = &fimc0_variant_exynos4, | 1236 | [0] = &fimc0_variant_exynos4x12, |
1205 | [1] = &fimc0_variant_exynos4, | 1237 | [1] = &fimc0_variant_exynos4x12, |
1206 | [2] = &fimc0_variant_exynos4, | 1238 | [2] = &fimc0_variant_exynos4x12, |
1207 | [3] = &fimc3_variant_exynos4, | 1239 | [3] = &fimc3_variant_exynos4x12, |
1208 | }, | 1240 | }, |
1209 | .num_entities = 4, | 1241 | .num_entities = 4, |
1210 | .lclk_frequency = 166000000UL, | 1242 | .lclk_frequency = 166000000UL, |
1211 | }; | 1243 | }; |
1212 | 1244 | ||
1213 | static struct platform_device_id fimc_driver_ids[] = { | 1245 | static const struct platform_device_id fimc_driver_ids[] = { |
1214 | { | 1246 | { |
1215 | .name = "s5p-fimc", | 1247 | .name = "s5p-fimc", |
1216 | .driver_data = (unsigned long)&fimc_drvdata_s5p, | 1248 | .driver_data = (unsigned long)&fimc_drvdata_s5p, |
@@ -1219,7 +1251,10 @@ static struct platform_device_id fimc_driver_ids[] = { | |||
1219 | .driver_data = (unsigned long)&fimc_drvdata_s5pv210, | 1251 | .driver_data = (unsigned long)&fimc_drvdata_s5pv210, |
1220 | }, { | 1252 | }, { |
1221 | .name = "exynos4-fimc", | 1253 | .name = "exynos4-fimc", |
1222 | .driver_data = (unsigned long)&fimc_drvdata_exynos4, | 1254 | .driver_data = (unsigned long)&fimc_drvdata_exynos4210, |
1255 | }, { | ||
1256 | .name = "exynos4x12-fimc", | ||
1257 | .driver_data = (unsigned long)&fimc_drvdata_exynos4x12, | ||
1223 | }, | 1258 | }, |
1224 | {}, | 1259 | {}, |
1225 | }; | 1260 | }; |
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.h b/drivers/media/platform/s5p-fimc/fimc-core.h index c0040d792499..412d50708f75 100644 --- a/drivers/media/platform/s5p-fimc/fimc-core.h +++ b/drivers/media/platform/s5p-fimc/fimc-core.h | |||
@@ -112,9 +112,7 @@ enum fimc_color_fmt { | |||
112 | 112 | ||
113 | /* The hardware context state. */ | 113 | /* The hardware context state. */ |
114 | #define FIMC_PARAMS (1 << 0) | 114 | #define FIMC_PARAMS (1 << 0) |
115 | #define FIMC_SRC_FMT (1 << 3) | 115 | #define FIMC_COMPOSE (1 << 1) |
116 | #define FIMC_DST_FMT (1 << 4) | ||
117 | #define FIMC_COMPOSE (1 << 5) | ||
118 | #define FIMC_CTX_M2M (1 << 16) | 116 | #define FIMC_CTX_M2M (1 << 16) |
119 | #define FIMC_CTX_CAP (1 << 17) | 117 | #define FIMC_CTX_CAP (1 << 17) |
120 | #define FIMC_CTX_SHUT (1 << 18) | 118 | #define FIMC_CTX_SHUT (1 << 18) |
@@ -265,6 +263,7 @@ struct fimc_vid_buffer { | |||
265 | * @width: image pixel width | 263 | * @width: image pixel width |
266 | * @height: image pixel weight | 264 | * @height: image pixel weight |
267 | * @payload: image size in bytes (w x h x bpp) | 265 | * @payload: image size in bytes (w x h x bpp) |
266 | * @bytesperline: bytesperline value for each plane | ||
268 | * @paddr: image frame buffer physical addresses | 267 | * @paddr: image frame buffer physical addresses |
269 | * @dma_offset: DMA offset in bytes | 268 | * @dma_offset: DMA offset in bytes |
270 | * @fmt: fimc color format pointer | 269 | * @fmt: fimc color format pointer |
@@ -279,6 +278,7 @@ struct fimc_frame { | |||
279 | u32 width; | 278 | u32 width; |
280 | u32 height; | 279 | u32 height; |
281 | unsigned int payload[VIDEO_MAX_PLANES]; | 280 | unsigned int payload[VIDEO_MAX_PLANES]; |
281 | unsigned int bytesperline[VIDEO_MAX_PLANES]; | ||
282 | struct fimc_addr paddr; | 282 | struct fimc_addr paddr; |
283 | struct fimc_dma_offset dma_offset; | 283 | struct fimc_dma_offset dma_offset; |
284 | struct fimc_fmt *fmt; | 284 | struct fimc_fmt *fmt; |
@@ -372,6 +372,7 @@ struct fimc_pix_limit { | |||
372 | * @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register | 372 | * @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register |
373 | * are present in this IP revision | 373 | * are present in this IP revision |
374 | * @has_cam_if: set if this instance has a camera input interface | 374 | * @has_cam_if: set if this instance has a camera input interface |
375 | * @has_isp_wb: set if this instance has ISP writeback input | ||
375 | * @pix_limit: pixel size constraints for the scaler | 376 | * @pix_limit: pixel size constraints for the scaler |
376 | * @min_inp_pixsize: minimum input pixel size | 377 | * @min_inp_pixsize: minimum input pixel size |
377 | * @min_out_pixsize: minimum output pixel size | 378 | * @min_out_pixsize: minimum output pixel size |
@@ -386,8 +387,9 @@ struct fimc_variant { | |||
386 | unsigned int has_cistatus2:1; | 387 | unsigned int has_cistatus2:1; |
387 | unsigned int has_mainscaler_ext:1; | 388 | unsigned int has_mainscaler_ext:1; |
388 | unsigned int has_cam_if:1; | 389 | unsigned int has_cam_if:1; |
390 | unsigned int has_isp_wb:1; | ||
389 | unsigned int has_alpha:1; | 391 | unsigned int has_alpha:1; |
390 | struct fimc_pix_limit *pix_limit; | 392 | const struct fimc_pix_limit *pix_limit; |
391 | u16 min_inp_pixsize; | 393 | u16 min_inp_pixsize; |
392 | u16 min_out_pixsize; | 394 | u16 min_out_pixsize; |
393 | u16 hor_offs_align; | 395 | u16 hor_offs_align; |
@@ -402,7 +404,7 @@ struct fimc_variant { | |||
402 | * @lclk_frequency: local bus clock frequency | 404 | * @lclk_frequency: local bus clock frequency |
403 | */ | 405 | */ |
404 | struct fimc_drvdata { | 406 | struct fimc_drvdata { |
405 | struct fimc_variant *variant[FIMC_MAX_DEVS]; | 407 | const struct fimc_variant *variant[FIMC_MAX_DEVS]; |
406 | int num_entities; | 408 | int num_entities; |
407 | unsigned long lclk_frequency; | 409 | unsigned long lclk_frequency; |
408 | }; | 410 | }; |
@@ -435,7 +437,7 @@ struct fimc_dev { | |||
435 | struct mutex lock; | 437 | struct mutex lock; |
436 | struct platform_device *pdev; | 438 | struct platform_device *pdev; |
437 | struct s5p_platform_fimc *pdata; | 439 | struct s5p_platform_fimc *pdata; |
438 | struct fimc_variant *variant; | 440 | const struct fimc_variant *variant; |
439 | u16 id; | 441 | u16 id; |
440 | struct clk *clock[MAX_FIMC_CLOCKS]; | 442 | struct clk *clock[MAX_FIMC_CLOCKS]; |
441 | void __iomem *regs; | 443 | void __iomem *regs; |
@@ -635,7 +637,7 @@ int fimc_ctrls_create(struct fimc_ctx *ctx); | |||
635 | void fimc_ctrls_delete(struct fimc_ctx *ctx); | 637 | void fimc_ctrls_delete(struct fimc_ctx *ctx); |
636 | void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active); | 638 | void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active); |
637 | void fimc_alpha_ctrl_update(struct fimc_ctx *ctx); | 639 | void fimc_alpha_ctrl_update(struct fimc_ctx *ctx); |
638 | int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f); | 640 | void __fimc_get_format(struct fimc_frame *frame, struct v4l2_format *f); |
639 | void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height, | 641 | void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height, |
640 | struct v4l2_pix_format_mplane *pix); | 642 | struct v4l2_pix_format_mplane *pix); |
641 | struct fimc_fmt *fimc_find_format(const u32 *pixelformat, const u32 *mbus_code, | 643 | struct fimc_fmt *fimc_find_format(const u32 *pixelformat, const u32 *mbus_code, |
@@ -650,7 +652,6 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb, | |||
650 | struct fimc_frame *frame, struct fimc_addr *paddr); | 652 | struct fimc_frame *frame, struct fimc_addr *paddr); |
651 | void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f); | 653 | void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f); |
652 | void fimc_set_yuv_order(struct fimc_ctx *ctx); | 654 | void fimc_set_yuv_order(struct fimc_ctx *ctx); |
653 | void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f); | ||
654 | void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf); | 655 | void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf); |
655 | 656 | ||
656 | int fimc_register_m2m_device(struct fimc_dev *fimc, | 657 | int fimc_register_m2m_device(struct fimc_dev *fimc, |
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite-reg.c b/drivers/media/platform/s5p-fimc/fimc-lite-reg.c index a22d7eb05c82..f0af0754a7b4 100644 --- a/drivers/media/platform/s5p-fimc/fimc-lite-reg.c +++ b/drivers/media/platform/s5p-fimc/fimc-lite-reg.c | |||
@@ -65,7 +65,7 @@ void flite_hw_set_interrupt_mask(struct fimc_lite *dev) | |||
65 | u32 cfg, intsrc; | 65 | u32 cfg, intsrc; |
66 | 66 | ||
67 | /* Select interrupts to be enabled for each output mode */ | 67 | /* Select interrupts to be enabled for each output mode */ |
68 | if (dev->out_path == FIMC_IO_DMA) { | 68 | if (atomic_read(&dev->out_path) == FIMC_IO_DMA) { |
69 | intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN | | 69 | intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN | |
70 | FLITE_REG_CIGCTRL_IRQ_LASTEN | | 70 | FLITE_REG_CIGCTRL_IRQ_LASTEN | |
71 | FLITE_REG_CIGCTRL_IRQ_STARTEN; | 71 | FLITE_REG_CIGCTRL_IRQ_STARTEN; |
@@ -187,12 +187,12 @@ static void flite_hw_set_camera_port(struct fimc_lite *dev, int id) | |||
187 | 187 | ||
188 | /* Select serial or parallel bus, camera port (A,B) and set signals polarity */ | 188 | /* Select serial or parallel bus, camera port (A,B) and set signals polarity */ |
189 | void flite_hw_set_camera_bus(struct fimc_lite *dev, | 189 | void flite_hw_set_camera_bus(struct fimc_lite *dev, |
190 | struct s5p_fimc_isp_info *s_info) | 190 | struct fimc_source_info *si) |
191 | { | 191 | { |
192 | u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL); | 192 | u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL); |
193 | unsigned int flags = s_info->flags; | 193 | unsigned int flags = si->flags; |
194 | 194 | ||
195 | if (s_info->bus_type != FIMC_MIPI_CSI2) { | 195 | if (si->sensor_bus_type != FIMC_BUS_TYPE_MIPI_CSI2) { |
196 | cfg &= ~(FLITE_REG_CIGCTRL_SELCAM_MIPI | | 196 | cfg &= ~(FLITE_REG_CIGCTRL_SELCAM_MIPI | |
197 | FLITE_REG_CIGCTRL_INVPOLPCLK | | 197 | FLITE_REG_CIGCTRL_INVPOLPCLK | |
198 | FLITE_REG_CIGCTRL_INVPOLVSYNC | | 198 | FLITE_REG_CIGCTRL_INVPOLVSYNC | |
@@ -212,7 +212,7 @@ void flite_hw_set_camera_bus(struct fimc_lite *dev, | |||
212 | 212 | ||
213 | writel(cfg, dev->regs + FLITE_REG_CIGCTRL); | 213 | writel(cfg, dev->regs + FLITE_REG_CIGCTRL); |
214 | 214 | ||
215 | flite_hw_set_camera_port(dev, s_info->mux_id); | 215 | flite_hw_set_camera_port(dev, si->mux_id); |
216 | } | 216 | } |
217 | 217 | ||
218 | static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f) | 218 | static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f) |
@@ -292,9 +292,11 @@ void flite_hw_dump_regs(struct fimc_lite *dev, const char *label) | |||
292 | }; | 292 | }; |
293 | u32 i; | 293 | u32 i; |
294 | 294 | ||
295 | pr_info("--- %s ---\n", label); | 295 | v4l2_info(&dev->subdev, "--- %s ---\n", label); |
296 | |||
296 | for (i = 0; i < ARRAY_SIZE(registers); i++) { | 297 | for (i = 0; i < ARRAY_SIZE(registers); i++) { |
297 | u32 cfg = readl(dev->regs + registers[i].offset); | 298 | u32 cfg = readl(dev->regs + registers[i].offset); |
298 | pr_info("%s: %s:\t0x%08x\n", __func__, registers[i].name, cfg); | 299 | v4l2_info(&dev->subdev, "%9s: 0x%08x\n", |
300 | registers[i].name, cfg); | ||
299 | } | 301 | } |
300 | } | 302 | } |
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite-reg.h b/drivers/media/platform/s5p-fimc/fimc-lite-reg.h index adb9e9e6f3c2..0e345844c13a 100644 --- a/drivers/media/platform/s5p-fimc/fimc-lite-reg.h +++ b/drivers/media/platform/s5p-fimc/fimc-lite-reg.h | |||
@@ -131,9 +131,9 @@ void flite_hw_set_interrupt_mask(struct fimc_lite *dev); | |||
131 | void flite_hw_capture_start(struct fimc_lite *dev); | 131 | void flite_hw_capture_start(struct fimc_lite *dev); |
132 | void flite_hw_capture_stop(struct fimc_lite *dev); | 132 | void flite_hw_capture_stop(struct fimc_lite *dev); |
133 | void flite_hw_set_camera_bus(struct fimc_lite *dev, | 133 | void flite_hw_set_camera_bus(struct fimc_lite *dev, |
134 | struct s5p_fimc_isp_info *s_info); | 134 | struct fimc_source_info *s_info); |
135 | void flite_hw_set_camera_polarity(struct fimc_lite *dev, | 135 | void flite_hw_set_camera_polarity(struct fimc_lite *dev, |
136 | struct s5p_fimc_isp_info *cam); | 136 | struct fimc_source_info *cam); |
137 | void flite_hw_set_window_offset(struct fimc_lite *dev, struct flite_frame *f); | 137 | void flite_hw_set_window_offset(struct fimc_lite *dev, struct flite_frame *f); |
138 | void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f); | 138 | void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f); |
139 | 139 | ||
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.c b/drivers/media/platform/s5p-fimc/fimc-lite.c index 67db9f8102e4..bfc4206935c8 100644 --- a/drivers/media/platform/s5p-fimc/fimc-lite.c +++ b/drivers/media/platform/s5p-fimc/fimc-lite.c | |||
@@ -120,25 +120,29 @@ static const struct fimc_fmt *fimc_lite_find_format(const u32 *pixelformat, | |||
120 | return def_fmt; | 120 | return def_fmt; |
121 | } | 121 | } |
122 | 122 | ||
123 | static int fimc_lite_hw_init(struct fimc_lite *fimc) | 123 | static int fimc_lite_hw_init(struct fimc_lite *fimc, bool isp_output) |
124 | { | 124 | { |
125 | struct fimc_pipeline *pipeline = &fimc->pipeline; | 125 | struct fimc_pipeline *pipeline = &fimc->pipeline; |
126 | struct fimc_sensor_info *sensor; | 126 | struct v4l2_subdev *sensor; |
127 | struct fimc_sensor_info *si; | ||
127 | unsigned long flags; | 128 | unsigned long flags; |
128 | 129 | ||
129 | if (pipeline->subdevs[IDX_SENSOR] == NULL) | 130 | sensor = isp_output ? fimc->sensor : pipeline->subdevs[IDX_SENSOR]; |
131 | |||
132 | if (sensor == NULL) | ||
130 | return -ENXIO; | 133 | return -ENXIO; |
131 | 134 | ||
132 | if (fimc->fmt == NULL) | 135 | if (fimc->fmt == NULL) |
133 | return -EINVAL; | 136 | return -EINVAL; |
134 | 137 | ||
135 | sensor = v4l2_get_subdev_hostdata(pipeline->subdevs[IDX_SENSOR]); | 138 | /* Get sensor configuration data from the sensor subdev */ |
139 | si = v4l2_get_subdev_hostdata(sensor); | ||
136 | spin_lock_irqsave(&fimc->slock, flags); | 140 | spin_lock_irqsave(&fimc->slock, flags); |
137 | 141 | ||
138 | flite_hw_set_camera_bus(fimc, &sensor->pdata); | 142 | flite_hw_set_camera_bus(fimc, &si->pdata); |
139 | flite_hw_set_source_format(fimc, &fimc->inp_frame); | 143 | flite_hw_set_source_format(fimc, &fimc->inp_frame); |
140 | flite_hw_set_window_offset(fimc, &fimc->inp_frame); | 144 | flite_hw_set_window_offset(fimc, &fimc->inp_frame); |
141 | flite_hw_set_output_dma(fimc, &fimc->out_frame, true); | 145 | flite_hw_set_output_dma(fimc, &fimc->out_frame, !isp_output); |
142 | flite_hw_set_interrupt_mask(fimc); | 146 | flite_hw_set_interrupt_mask(fimc); |
143 | flite_hw_set_test_pattern(fimc, fimc->test_pattern->val); | 147 | flite_hw_set_test_pattern(fimc, fimc->test_pattern->val); |
144 | 148 | ||
@@ -256,7 +260,7 @@ static irqreturn_t flite_irq_handler(int irq, void *priv) | |||
256 | wake_up(&fimc->irq_queue); | 260 | wake_up(&fimc->irq_queue); |
257 | } | 261 | } |
258 | 262 | ||
259 | if (fimc->out_path != FIMC_IO_DMA) | 263 | if (atomic_read(&fimc->out_path) != FIMC_IO_DMA) |
260 | goto done; | 264 | goto done; |
261 | 265 | ||
262 | if ((intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART) && | 266 | if ((intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART) && |
@@ -296,7 +300,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) | |||
296 | 300 | ||
297 | fimc->frame_count = 0; | 301 | fimc->frame_count = 0; |
298 | 302 | ||
299 | ret = fimc_lite_hw_init(fimc); | 303 | ret = fimc_lite_hw_init(fimc, false); |
300 | if (ret) { | 304 | if (ret) { |
301 | fimc_lite_reinit(fimc, false); | 305 | fimc_lite_reinit(fimc, false); |
302 | return ret; | 306 | return ret; |
@@ -455,10 +459,16 @@ static void fimc_lite_clear_event_counters(struct fimc_lite *fimc) | |||
455 | static int fimc_lite_open(struct file *file) | 459 | static int fimc_lite_open(struct file *file) |
456 | { | 460 | { |
457 | struct fimc_lite *fimc = video_drvdata(file); | 461 | struct fimc_lite *fimc = video_drvdata(file); |
462 | struct media_entity *me = &fimc->vfd.entity; | ||
458 | int ret; | 463 | int ret; |
459 | 464 | ||
460 | if (mutex_lock_interruptible(&fimc->lock)) | 465 | mutex_lock(&me->parent->graph_mutex); |
461 | return -ERESTARTSYS; | 466 | |
467 | mutex_lock(&fimc->lock); | ||
468 | if (atomic_read(&fimc->out_path) != FIMC_IO_DMA) { | ||
469 | ret = -EBUSY; | ||
470 | goto done; | ||
471 | } | ||
462 | 472 | ||
463 | set_bit(ST_FLITE_IN_USE, &fimc->state); | 473 | set_bit(ST_FLITE_IN_USE, &fimc->state); |
464 | ret = pm_runtime_get_sync(&fimc->pdev->dev); | 474 | ret = pm_runtime_get_sync(&fimc->pdev->dev); |
@@ -469,7 +479,8 @@ static int fimc_lite_open(struct file *file) | |||
469 | if (ret < 0) | 479 | if (ret < 0) |
470 | goto done; | 480 | goto done; |
471 | 481 | ||
472 | if (++fimc->ref_count == 1 && fimc->out_path == FIMC_IO_DMA) { | 482 | if (++fimc->ref_count == 1 && |
483 | atomic_read(&fimc->out_path) == FIMC_IO_DMA) { | ||
473 | ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, | 484 | ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, |
474 | &fimc->vfd.entity, true); | 485 | &fimc->vfd.entity, true); |
475 | if (ret < 0) { | 486 | if (ret < 0) { |
@@ -483,6 +494,7 @@ static int fimc_lite_open(struct file *file) | |||
483 | } | 494 | } |
484 | done: | 495 | done: |
485 | mutex_unlock(&fimc->lock); | 496 | mutex_unlock(&fimc->lock); |
497 | mutex_unlock(&me->parent->graph_mutex); | ||
486 | return ret; | 498 | return ret; |
487 | } | 499 | } |
488 | 500 | ||
@@ -493,7 +505,8 @@ static int fimc_lite_close(struct file *file) | |||
493 | 505 | ||
494 | mutex_lock(&fimc->lock); | 506 | mutex_lock(&fimc->lock); |
495 | 507 | ||
496 | if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) { | 508 | if (--fimc->ref_count == 0 && |
509 | atomic_read(&fimc->out_path) == FIMC_IO_DMA) { | ||
497 | clear_bit(ST_FLITE_IN_USE, &fimc->state); | 510 | clear_bit(ST_FLITE_IN_USE, &fimc->state); |
498 | fimc_lite_stop_capture(fimc, false); | 511 | fimc_lite_stop_capture(fimc, false); |
499 | fimc_pipeline_call(fimc, close, &fimc->pipeline); | 512 | fimc_pipeline_call(fimc, close, &fimc->pipeline); |
@@ -598,7 +611,7 @@ static void fimc_lite_try_crop(struct fimc_lite *fimc, struct v4l2_rect *r) | |||
598 | r->left = round_down(r->left, fimc->variant->win_hor_offs_align); | 611 | r->left = round_down(r->left, fimc->variant->win_hor_offs_align); |
599 | r->top = clamp_t(u32, r->top, 0, frame->f_height - r->height); | 612 | r->top = clamp_t(u32, r->top, 0, frame->f_height - r->height); |
600 | 613 | ||
601 | v4l2_dbg(1, debug, &fimc->subdev, "(%d,%d)/%dx%d, sink fmt: %dx%d", | 614 | v4l2_dbg(1, debug, &fimc->subdev, "(%d,%d)/%dx%d, sink fmt: %dx%d\n", |
602 | r->left, r->top, r->width, r->height, | 615 | r->left, r->top, r->width, r->height, |
603 | frame->f_width, frame->f_height); | 616 | frame->f_width, frame->f_height); |
604 | } | 617 | } |
@@ -618,7 +631,7 @@ static void fimc_lite_try_compose(struct fimc_lite *fimc, struct v4l2_rect *r) | |||
618 | r->left = round_down(r->left, fimc->variant->out_hor_offs_align); | 631 | r->left = round_down(r->left, fimc->variant->out_hor_offs_align); |
619 | r->top = clamp_t(u32, r->top, 0, fimc->out_frame.f_height - r->height); | 632 | r->top = clamp_t(u32, r->top, 0, fimc->out_frame.f_height - r->height); |
620 | 633 | ||
621 | v4l2_dbg(1, debug, &fimc->subdev, "(%d,%d)/%dx%d, source fmt: %dx%d", | 634 | v4l2_dbg(1, debug, &fimc->subdev, "(%d,%d)/%dx%d, source fmt: %dx%d\n", |
622 | r->left, r->top, r->width, r->height, | 635 | r->left, r->top, r->width, r->height, |
623 | frame->f_width, frame->f_height); | 636 | frame->f_width, frame->f_height); |
624 | } | 637 | } |
@@ -962,6 +975,29 @@ static const struct v4l2_ioctl_ops fimc_lite_ioctl_ops = { | |||
962 | .vidioc_streamoff = fimc_lite_streamoff, | 975 | .vidioc_streamoff = fimc_lite_streamoff, |
963 | }; | 976 | }; |
964 | 977 | ||
978 | /* Called with the media graph mutex held */ | ||
979 | static struct v4l2_subdev *__find_remote_sensor(struct media_entity *me) | ||
980 | { | ||
981 | struct media_pad *pad = &me->pads[0]; | ||
982 | struct v4l2_subdev *sd; | ||
983 | |||
984 | while (pad->flags & MEDIA_PAD_FL_SINK) { | ||
985 | /* source pad */ | ||
986 | pad = media_entity_remote_source(pad); | ||
987 | if (pad == NULL || | ||
988 | media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
989 | break; | ||
990 | |||
991 | sd = media_entity_to_v4l2_subdev(pad->entity); | ||
992 | |||
993 | if (sd->grp_id == GRP_ID_FIMC_IS_SENSOR) | ||
994 | return sd; | ||
995 | /* sink pad */ | ||
996 | pad = &sd->entity.pads[0]; | ||
997 | } | ||
998 | return NULL; | ||
999 | } | ||
1000 | |||
965 | /* Capture subdev media entity operations */ | 1001 | /* Capture subdev media entity operations */ |
966 | static int fimc_lite_link_setup(struct media_entity *entity, | 1002 | static int fimc_lite_link_setup(struct media_entity *entity, |
967 | const struct media_pad *local, | 1003 | const struct media_pad *local, |
@@ -970,46 +1006,60 @@ static int fimc_lite_link_setup(struct media_entity *entity, | |||
970 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 1006 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
971 | struct fimc_lite *fimc = v4l2_get_subdevdata(sd); | 1007 | struct fimc_lite *fimc = v4l2_get_subdevdata(sd); |
972 | unsigned int remote_ent_type = media_entity_type(remote->entity); | 1008 | unsigned int remote_ent_type = media_entity_type(remote->entity); |
1009 | int ret = 0; | ||
973 | 1010 | ||
974 | if (WARN_ON(fimc == NULL)) | 1011 | if (WARN_ON(fimc == NULL)) |
975 | return 0; | 1012 | return 0; |
976 | 1013 | ||
977 | v4l2_dbg(1, debug, sd, "%s: %s --> %s, flags: 0x%x. source_id: 0x%x", | 1014 | v4l2_dbg(1, debug, sd, "%s: %s --> %s, flags: 0x%x. source_id: 0x%x\n", |
978 | __func__, local->entity->name, remote->entity->name, | 1015 | __func__, remote->entity->name, local->entity->name, |
979 | flags, fimc->source_subdev_grp_id); | 1016 | flags, fimc->source_subdev_grp_id); |
980 | 1017 | ||
981 | switch (local->index) { | 1018 | mutex_lock(&fimc->lock); |
982 | case FIMC_SD_PAD_SINK: | ||
983 | if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) | ||
984 | return -EINVAL; | ||
985 | 1019 | ||
1020 | switch (local->index) { | ||
1021 | case FLITE_SD_PAD_SINK: | ||
1022 | if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) { | ||
1023 | ret = -EINVAL; | ||
1024 | break; | ||
1025 | } | ||
986 | if (flags & MEDIA_LNK_FL_ENABLED) { | 1026 | if (flags & MEDIA_LNK_FL_ENABLED) { |
987 | if (fimc->source_subdev_grp_id != 0) | 1027 | if (fimc->source_subdev_grp_id == 0) |
988 | return -EBUSY; | 1028 | fimc->source_subdev_grp_id = sd->grp_id; |
989 | fimc->source_subdev_grp_id = sd->grp_id; | 1029 | else |
990 | return 0; | 1030 | ret = -EBUSY; |
1031 | } else { | ||
1032 | fimc->source_subdev_grp_id = 0; | ||
1033 | fimc->sensor = NULL; | ||
991 | } | 1034 | } |
1035 | break; | ||
992 | 1036 | ||
993 | fimc->source_subdev_grp_id = 0; | 1037 | case FLITE_SD_PAD_SOURCE_DMA: |
1038 | if (!(flags & MEDIA_LNK_FL_ENABLED)) | ||
1039 | atomic_set(&fimc->out_path, FIMC_IO_NONE); | ||
1040 | else if (remote_ent_type == MEDIA_ENT_T_DEVNODE) | ||
1041 | atomic_set(&fimc->out_path, FIMC_IO_DMA); | ||
1042 | else | ||
1043 | ret = -EINVAL; | ||
994 | break; | 1044 | break; |
995 | 1045 | ||
996 | case FIMC_SD_PAD_SOURCE: | 1046 | case FLITE_SD_PAD_SOURCE_ISP: |
997 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 1047 | if (!(flags & MEDIA_LNK_FL_ENABLED)) |
998 | fimc->out_path = FIMC_IO_NONE; | 1048 | atomic_set(&fimc->out_path, FIMC_IO_NONE); |
999 | return 0; | 1049 | else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV) |
1000 | } | 1050 | atomic_set(&fimc->out_path, FIMC_IO_ISP); |
1001 | if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV) | ||
1002 | fimc->out_path = FIMC_IO_ISP; | ||
1003 | else | 1051 | else |
1004 | fimc->out_path = FIMC_IO_DMA; | 1052 | ret = -EINVAL; |
1005 | break; | 1053 | break; |
1006 | 1054 | ||
1007 | default: | 1055 | default: |
1008 | v4l2_err(sd, "Invalid pad index\n"); | 1056 | v4l2_err(sd, "Invalid pad index\n"); |
1009 | return -EINVAL; | 1057 | ret = -EINVAL; |
1010 | } | 1058 | } |
1059 | mb(); | ||
1011 | 1060 | ||
1012 | return 0; | 1061 | mutex_unlock(&fimc->lock); |
1062 | return ret; | ||
1013 | } | 1063 | } |
1014 | 1064 | ||
1015 | static const struct media_entity_operations fimc_lite_subdev_media_ops = { | 1065 | static const struct media_entity_operations fimc_lite_subdev_media_ops = { |
@@ -1070,14 +1120,16 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd, | |||
1070 | struct flite_frame *source = &fimc->out_frame; | 1120 | struct flite_frame *source = &fimc->out_frame; |
1071 | const struct fimc_fmt *ffmt; | 1121 | const struct fimc_fmt *ffmt; |
1072 | 1122 | ||
1073 | v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %dx%d", | 1123 | v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %dx%d\n", |
1074 | fmt->pad, mf->code, mf->width, mf->height); | 1124 | fmt->pad, mf->code, mf->width, mf->height); |
1075 | 1125 | ||
1076 | mf->colorspace = V4L2_COLORSPACE_JPEG; | 1126 | mf->colorspace = V4L2_COLORSPACE_JPEG; |
1077 | mutex_lock(&fimc->lock); | 1127 | mutex_lock(&fimc->lock); |
1078 | 1128 | ||
1079 | if ((fimc->out_path == FIMC_IO_ISP && sd->entity.stream_count > 0) || | 1129 | if ((atomic_read(&fimc->out_path) == FIMC_IO_ISP && |
1080 | (fimc->out_path == FIMC_IO_DMA && vb2_is_busy(&fimc->vb_queue))) { | 1130 | sd->entity.stream_count > 0) || |
1131 | (atomic_read(&fimc->out_path) == FIMC_IO_DMA && | ||
1132 | vb2_is_busy(&fimc->vb_queue))) { | ||
1081 | mutex_unlock(&fimc->lock); | 1133 | mutex_unlock(&fimc->lock); |
1082 | return -EBUSY; | 1134 | return -EBUSY; |
1083 | } | 1135 | } |
@@ -1144,7 +1196,7 @@ static int fimc_lite_subdev_get_selection(struct v4l2_subdev *sd, | |||
1144 | } | 1196 | } |
1145 | mutex_unlock(&fimc->lock); | 1197 | mutex_unlock(&fimc->lock); |
1146 | 1198 | ||
1147 | v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %d, f_h: %d", | 1199 | v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %d, f_h: %d\n", |
1148 | __func__, f->rect.left, f->rect.top, f->rect.width, | 1200 | __func__, f->rect.left, f->rect.top, f->rect.width, |
1149 | f->rect.height, f->f_width, f->f_height); | 1201 | f->rect.height, f->f_width, f->f_height); |
1150 | 1202 | ||
@@ -1178,7 +1230,7 @@ static int fimc_lite_subdev_set_selection(struct v4l2_subdev *sd, | |||
1178 | } | 1230 | } |
1179 | mutex_unlock(&fimc->lock); | 1231 | mutex_unlock(&fimc->lock); |
1180 | 1232 | ||
1181 | v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %d, f_h: %d", | 1233 | v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %d, f_h: %d\n", |
1182 | __func__, f->rect.left, f->rect.top, f->rect.width, | 1234 | __func__, f->rect.left, f->rect.top, f->rect.width, |
1183 | f->rect.height, f->f_width, f->f_height); | 1235 | f->rect.height, f->f_width, f->f_height); |
1184 | 1236 | ||
@@ -1188,25 +1240,47 @@ static int fimc_lite_subdev_set_selection(struct v4l2_subdev *sd, | |||
1188 | static int fimc_lite_subdev_s_stream(struct v4l2_subdev *sd, int on) | 1240 | static int fimc_lite_subdev_s_stream(struct v4l2_subdev *sd, int on) |
1189 | { | 1241 | { |
1190 | struct fimc_lite *fimc = v4l2_get_subdevdata(sd); | 1242 | struct fimc_lite *fimc = v4l2_get_subdevdata(sd); |
1243 | unsigned long flags; | ||
1244 | int ret; | ||
1191 | 1245 | ||
1192 | if (fimc->out_path == FIMC_IO_DMA) | 1246 | /* |
1193 | return -ENOIOCTLCMD; | 1247 | * Find sensor subdev linked to FIMC-LITE directly or through |
1194 | 1248 | * MIPI-CSIS. This is required for configuration where FIMC-LITE | |
1195 | /* TODO: */ | 1249 | * is used as a subdev only and feeds data internally to FIMC-IS. |
1250 | * The pipeline links are protected through entity.stream_count | ||
1251 | * so there is no need to take the media graph mutex here. | ||
1252 | */ | ||
1253 | fimc->sensor = __find_remote_sensor(&sd->entity); | ||
1196 | 1254 | ||
1197 | return 0; | 1255 | if (atomic_read(&fimc->out_path) != FIMC_IO_ISP) |
1198 | } | 1256 | return -ENOIOCTLCMD; |
1199 | 1257 | ||
1200 | static int fimc_lite_subdev_s_power(struct v4l2_subdev *sd, int on) | 1258 | mutex_lock(&fimc->lock); |
1201 | { | 1259 | if (on) { |
1202 | struct fimc_lite *fimc = v4l2_get_subdevdata(sd); | 1260 | flite_hw_reset(fimc); |
1261 | ret = fimc_lite_hw_init(fimc, true); | ||
1262 | if (!ret) { | ||
1263 | spin_lock_irqsave(&fimc->slock, flags); | ||
1264 | flite_hw_capture_start(fimc); | ||
1265 | spin_unlock_irqrestore(&fimc->slock, flags); | ||
1266 | } | ||
1267 | } else { | ||
1268 | set_bit(ST_FLITE_OFF, &fimc->state); | ||
1203 | 1269 | ||
1204 | if (fimc->out_path == FIMC_IO_DMA) | 1270 | spin_lock_irqsave(&fimc->slock, flags); |
1205 | return -ENOIOCTLCMD; | 1271 | flite_hw_capture_stop(fimc); |
1272 | spin_unlock_irqrestore(&fimc->slock, flags); | ||
1206 | 1273 | ||
1207 | /* TODO: */ | 1274 | ret = wait_event_timeout(fimc->irq_queue, |
1275 | !test_bit(ST_FLITE_OFF, &fimc->state), | ||
1276 | msecs_to_jiffies(200)); | ||
1277 | if (ret == 0) | ||
1278 | v4l2_err(sd, "s_stream(0) timeout\n"); | ||
1279 | clear_bit(ST_FLITE_RUN, &fimc->state); | ||
1280 | } | ||
1208 | 1281 | ||
1209 | return 0; | 1282 | mutex_unlock(&fimc->lock); |
1283 | return ret; | ||
1210 | } | 1284 | } |
1211 | 1285 | ||
1212 | static int fimc_lite_log_status(struct v4l2_subdev *sd) | 1286 | static int fimc_lite_log_status(struct v4l2_subdev *sd) |
@@ -1227,7 +1301,7 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) | |||
1227 | memset(vfd, 0, sizeof(*vfd)); | 1301 | memset(vfd, 0, sizeof(*vfd)); |
1228 | 1302 | ||
1229 | fimc->fmt = &fimc_lite_formats[0]; | 1303 | fimc->fmt = &fimc_lite_formats[0]; |
1230 | fimc->out_path = FIMC_IO_DMA; | 1304 | atomic_set(&fimc->out_path, FIMC_IO_DMA); |
1231 | 1305 | ||
1232 | snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture", | 1306 | snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture", |
1233 | fimc->index); | 1307 | fimc->index); |
@@ -1308,7 +1382,6 @@ static const struct v4l2_subdev_video_ops fimc_lite_subdev_video_ops = { | |||
1308 | }; | 1382 | }; |
1309 | 1383 | ||
1310 | static const struct v4l2_subdev_core_ops fimc_lite_core_ops = { | 1384 | static const struct v4l2_subdev_core_ops fimc_lite_core_ops = { |
1311 | .s_power = fimc_lite_subdev_s_power, | ||
1312 | .log_status = fimc_lite_log_status, | 1385 | .log_status = fimc_lite_log_status, |
1313 | }; | 1386 | }; |
1314 | 1387 | ||
@@ -1347,9 +1420,10 @@ static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc) | |||
1347 | sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; | 1420 | sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; |
1348 | snprintf(sd->name, sizeof(sd->name), "FIMC-LITE.%d", fimc->index); | 1421 | snprintf(sd->name, sizeof(sd->name), "FIMC-LITE.%d", fimc->index); |
1349 | 1422 | ||
1350 | fimc->subdev_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; | 1423 | fimc->subdev_pads[FLITE_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; |
1351 | fimc->subdev_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; | 1424 | fimc->subdev_pads[FLITE_SD_PAD_SOURCE_DMA].flags = MEDIA_PAD_FL_SOURCE; |
1352 | ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM, | 1425 | fimc->subdev_pads[FLITE_SD_PAD_SOURCE_ISP].flags = MEDIA_PAD_FL_SOURCE; |
1426 | ret = media_entity_init(&sd->entity, FLITE_SD_PADS_NUM, | ||
1353 | fimc->subdev_pads, 0); | 1427 | fimc->subdev_pads, 0); |
1354 | if (ret) | 1428 | if (ret) |
1355 | return ret; | 1429 | return ret; |
@@ -1516,7 +1590,7 @@ static int fimc_lite_resume(struct device *dev) | |||
1516 | INIT_LIST_HEAD(&fimc->active_buf_q); | 1590 | INIT_LIST_HEAD(&fimc->active_buf_q); |
1517 | fimc_pipeline_call(fimc, open, &fimc->pipeline, | 1591 | fimc_pipeline_call(fimc, open, &fimc->pipeline, |
1518 | &fimc->vfd.entity, false); | 1592 | &fimc->vfd.entity, false); |
1519 | fimc_lite_hw_init(fimc); | 1593 | fimc_lite_hw_init(fimc, atomic_read(&fimc->out_path) == FIMC_IO_ISP); |
1520 | clear_bit(ST_FLITE_SUSPENDED, &fimc->state); | 1594 | clear_bit(ST_FLITE_SUSPENDED, &fimc->state); |
1521 | 1595 | ||
1522 | for (i = 0; i < fimc->reqbufs_count; i++) { | 1596 | for (i = 0; i < fimc->reqbufs_count; i++) { |
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.h b/drivers/media/platform/s5p-fimc/fimc-lite.h index 3081db35c5b0..7085761f8c4b 100644 --- a/drivers/media/platform/s5p-fimc/fimc-lite.h +++ b/drivers/media/platform/s5p-fimc/fimc-lite.h | |||
@@ -45,8 +45,9 @@ enum { | |||
45 | }; | 45 | }; |
46 | 46 | ||
47 | #define FLITE_SD_PAD_SINK 0 | 47 | #define FLITE_SD_PAD_SINK 0 |
48 | #define FLITE_SD_PAD_SOURCE 1 | 48 | #define FLITE_SD_PAD_SOURCE_DMA 1 |
49 | #define FLITE_SD_PADS_NUM 2 | 49 | #define FLITE_SD_PAD_SOURCE_ISP 2 |
50 | #define FLITE_SD_PADS_NUM 3 | ||
50 | 51 | ||
51 | struct flite_variant { | 52 | struct flite_variant { |
52 | unsigned short max_width; | 53 | unsigned short max_width; |
@@ -104,6 +105,7 @@ struct flite_buffer { | |||
104 | * @subdev: FIMC-LITE subdev | 105 | * @subdev: FIMC-LITE subdev |
105 | * @vd_pad: media (sink) pad for the capture video node | 106 | * @vd_pad: media (sink) pad for the capture video node |
106 | * @subdev_pads: the subdev media pads | 107 | * @subdev_pads: the subdev media pads |
108 | * @sensor: sensor subdev attached to FIMC-LITE directly or through MIPI-CSIS | ||
107 | * @ctrl_handler: v4l2 control handler | 109 | * @ctrl_handler: v4l2 control handler |
108 | * @test_pattern: test pattern controls | 110 | * @test_pattern: test pattern controls |
109 | * @index: FIMC-LITE platform device index | 111 | * @index: FIMC-LITE platform device index |
@@ -139,6 +141,7 @@ struct fimc_lite { | |||
139 | struct v4l2_subdev subdev; | 141 | struct v4l2_subdev subdev; |
140 | struct media_pad vd_pad; | 142 | struct media_pad vd_pad; |
141 | struct media_pad subdev_pads[FLITE_SD_PADS_NUM]; | 143 | struct media_pad subdev_pads[FLITE_SD_PADS_NUM]; |
144 | struct v4l2_subdev *sensor; | ||
142 | struct v4l2_ctrl_handler ctrl_handler; | 145 | struct v4l2_ctrl_handler ctrl_handler; |
143 | struct v4l2_ctrl *test_pattern; | 146 | struct v4l2_ctrl *test_pattern; |
144 | u32 index; | 147 | u32 index; |
@@ -156,7 +159,7 @@ struct fimc_lite { | |||
156 | unsigned long payload[FLITE_MAX_PLANES]; | 159 | unsigned long payload[FLITE_MAX_PLANES]; |
157 | struct flite_frame inp_frame; | 160 | struct flite_frame inp_frame; |
158 | struct flite_frame out_frame; | 161 | struct flite_frame out_frame; |
159 | enum fimc_datapath out_path; | 162 | atomic_t out_path; |
160 | unsigned int source_subdev_grp_id; | 163 | unsigned int source_subdev_grp_id; |
161 | 164 | ||
162 | unsigned long state; | 165 | unsigned long state; |
diff --git a/drivers/media/platform/s5p-fimc/fimc-m2m.c b/drivers/media/platform/s5p-fimc/fimc-m2m.c index 1d21da4bd24b..f3d535cdd87f 100644 --- a/drivers/media/platform/s5p-fimc/fimc-m2m.c +++ b/drivers/media/platform/s5p-fimc/fimc-m2m.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Samsung S5P/EXYNOS4 SoC series FIMC (video postprocessor) driver | 2 | * Samsung S5P/EXYNOS4 SoC series FIMC (video postprocessor) driver |
3 | * | 3 | * |
4 | * Copyright (C) 2012 Samsung Electronics Co., Ltd. | 4 | * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. |
5 | * Sylwester Nawrocki, <s.nawrocki@samsung.com> | 5 | * Sylwester Nawrocki <s.nawrocki@samsung.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published | 8 | * it under the terms of the GNU General Public License as published |
@@ -160,8 +160,7 @@ static void fimc_device_run(void *priv) | |||
160 | fimc_hw_set_output_addr(fimc, &df->paddr, -1); | 160 | fimc_hw_set_output_addr(fimc, &df->paddr, -1); |
161 | 161 | ||
162 | fimc_activate_capture(ctx); | 162 | fimc_activate_capture(ctx); |
163 | ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP | | 163 | ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP); |
164 | FIMC_SRC_FMT | FIMC_DST_FMT); | ||
165 | fimc_hw_activate_input_dma(fimc, true); | 164 | fimc_hw_activate_input_dma(fimc, true); |
166 | 165 | ||
167 | dma_unlock: | 166 | dma_unlock: |
@@ -294,13 +293,14 @@ static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh, | |||
294 | if (IS_ERR(frame)) | 293 | if (IS_ERR(frame)) |
295 | return PTR_ERR(frame); | 294 | return PTR_ERR(frame); |
296 | 295 | ||
297 | return fimc_fill_format(frame, f); | 296 | __fimc_get_format(frame, f); |
297 | return 0; | ||
298 | } | 298 | } |
299 | 299 | ||
300 | static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) | 300 | static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) |
301 | { | 301 | { |
302 | struct fimc_dev *fimc = ctx->fimc_dev; | 302 | struct fimc_dev *fimc = ctx->fimc_dev; |
303 | struct fimc_variant *variant = fimc->variant; | 303 | const struct fimc_variant *variant = fimc->variant; |
304 | struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; | 304 | struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; |
305 | struct fimc_fmt *fmt; | 305 | struct fimc_fmt *fmt; |
306 | u32 max_w, mod_x, mod_y; | 306 | u32 max_w, mod_x, mod_y; |
@@ -308,8 +308,6 @@ static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) | |||
308 | if (!IS_M2M(f->type)) | 308 | if (!IS_M2M(f->type)) |
309 | return -EINVAL; | 309 | return -EINVAL; |
310 | 310 | ||
311 | dbg("w: %d, h: %d", pix->width, pix->height); | ||
312 | |||
313 | fmt = fimc_find_format(&pix->pixelformat, NULL, | 311 | fmt = fimc_find_format(&pix->pixelformat, NULL, |
314 | get_m2m_fmt_flags(f->type), 0); | 312 | get_m2m_fmt_flags(f->type), 0); |
315 | if (WARN(fmt == NULL, "Pixel format lookup failed")) | 313 | if (WARN(fmt == NULL, "Pixel format lookup failed")) |
@@ -349,19 +347,39 @@ static int fimc_m2m_try_fmt_mplane(struct file *file, void *fh, | |||
349 | struct v4l2_format *f) | 347 | struct v4l2_format *f) |
350 | { | 348 | { |
351 | struct fimc_ctx *ctx = fh_to_ctx(fh); | 349 | struct fimc_ctx *ctx = fh_to_ctx(fh); |
352 | |||
353 | return fimc_try_fmt_mplane(ctx, f); | 350 | return fimc_try_fmt_mplane(ctx, f); |
354 | } | 351 | } |
355 | 352 | ||
353 | static void __set_frame_format(struct fimc_frame *frame, struct fimc_fmt *fmt, | ||
354 | struct v4l2_pix_format_mplane *pixm) | ||
355 | { | ||
356 | int i; | ||
357 | |||
358 | for (i = 0; i < fmt->colplanes; i++) { | ||
359 | frame->bytesperline[i] = pixm->plane_fmt[i].bytesperline; | ||
360 | frame->payload[i] = pixm->plane_fmt[i].sizeimage; | ||
361 | } | ||
362 | |||
363 | frame->f_width = pixm->width; | ||
364 | frame->f_height = pixm->height; | ||
365 | frame->o_width = pixm->width; | ||
366 | frame->o_height = pixm->height; | ||
367 | frame->width = pixm->width; | ||
368 | frame->height = pixm->height; | ||
369 | frame->offs_h = 0; | ||
370 | frame->offs_v = 0; | ||
371 | frame->fmt = fmt; | ||
372 | } | ||
373 | |||
356 | static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, | 374 | static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, |
357 | struct v4l2_format *f) | 375 | struct v4l2_format *f) |
358 | { | 376 | { |
359 | struct fimc_ctx *ctx = fh_to_ctx(fh); | 377 | struct fimc_ctx *ctx = fh_to_ctx(fh); |
360 | struct fimc_dev *fimc = ctx->fimc_dev; | 378 | struct fimc_dev *fimc = ctx->fimc_dev; |
379 | struct fimc_fmt *fmt; | ||
361 | struct vb2_queue *vq; | 380 | struct vb2_queue *vq; |
362 | struct fimc_frame *frame; | 381 | struct fimc_frame *frame; |
363 | struct v4l2_pix_format_mplane *pix; | 382 | int ret; |
364 | int i, ret = 0; | ||
365 | 383 | ||
366 | ret = fimc_try_fmt_mplane(ctx, f); | 384 | ret = fimc_try_fmt_mplane(ctx, f); |
367 | if (ret) | 385 | if (ret) |
@@ -379,31 +397,16 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, | |||
379 | else | 397 | else |
380 | frame = &ctx->d_frame; | 398 | frame = &ctx->d_frame; |
381 | 399 | ||
382 | pix = &f->fmt.pix_mp; | 400 | fmt = fimc_find_format(&f->fmt.pix_mp.pixelformat, NULL, |
383 | frame->fmt = fimc_find_format(&pix->pixelformat, NULL, | 401 | get_m2m_fmt_flags(f->type), 0); |
384 | get_m2m_fmt_flags(f->type), 0); | 402 | if (!fmt) |
385 | if (!frame->fmt) | ||
386 | return -EINVAL; | 403 | return -EINVAL; |
387 | 404 | ||
405 | __set_frame_format(frame, fmt, &f->fmt.pix_mp); | ||
406 | |||
388 | /* Update RGB Alpha control state and value range */ | 407 | /* Update RGB Alpha control state and value range */ |
389 | fimc_alpha_ctrl_update(ctx); | 408 | fimc_alpha_ctrl_update(ctx); |
390 | 409 | ||
391 | for (i = 0; i < frame->fmt->colplanes; i++) { | ||
392 | frame->payload[i] = | ||
393 | (pix->width * pix->height * frame->fmt->depth[i]) / 8; | ||
394 | } | ||
395 | |||
396 | fimc_fill_frame(frame, f); | ||
397 | |||
398 | ctx->scaler.enabled = 1; | ||
399 | |||
400 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | ||
401 | fimc_ctx_state_set(FIMC_PARAMS | FIMC_DST_FMT, ctx); | ||
402 | else | ||
403 | fimc_ctx_state_set(FIMC_PARAMS | FIMC_SRC_FMT, ctx); | ||
404 | |||
405 | dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height); | ||
406 | |||
407 | return 0; | 410 | return 0; |
408 | } | 411 | } |
409 | 412 | ||
@@ -411,7 +414,6 @@ static int fimc_m2m_reqbufs(struct file *file, void *fh, | |||
411 | struct v4l2_requestbuffers *reqbufs) | 414 | struct v4l2_requestbuffers *reqbufs) |
412 | { | 415 | { |
413 | struct fimc_ctx *ctx = fh_to_ctx(fh); | 416 | struct fimc_ctx *ctx = fh_to_ctx(fh); |
414 | |||
415 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); | 417 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); |
416 | } | 418 | } |
417 | 419 | ||
@@ -419,7 +421,6 @@ static int fimc_m2m_querybuf(struct file *file, void *fh, | |||
419 | struct v4l2_buffer *buf) | 421 | struct v4l2_buffer *buf) |
420 | { | 422 | { |
421 | struct fimc_ctx *ctx = fh_to_ctx(fh); | 423 | struct fimc_ctx *ctx = fh_to_ctx(fh); |
422 | |||
423 | return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); | 424 | return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); |
424 | } | 425 | } |
425 | 426 | ||
@@ -427,7 +428,6 @@ static int fimc_m2m_qbuf(struct file *file, void *fh, | |||
427 | struct v4l2_buffer *buf) | 428 | struct v4l2_buffer *buf) |
428 | { | 429 | { |
429 | struct fimc_ctx *ctx = fh_to_ctx(fh); | 430 | struct fimc_ctx *ctx = fh_to_ctx(fh); |
430 | |||
431 | return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); | 431 | return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); |
432 | } | 432 | } |
433 | 433 | ||
@@ -435,7 +435,6 @@ static int fimc_m2m_dqbuf(struct file *file, void *fh, | |||
435 | struct v4l2_buffer *buf) | 435 | struct v4l2_buffer *buf) |
436 | { | 436 | { |
437 | struct fimc_ctx *ctx = fh_to_ctx(fh); | 437 | struct fimc_ctx *ctx = fh_to_ctx(fh); |
438 | |||
439 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | 438 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); |
440 | } | 439 | } |
441 | 440 | ||
@@ -443,7 +442,6 @@ static int fimc_m2m_expbuf(struct file *file, void *fh, | |||
443 | struct v4l2_exportbuffer *eb) | 442 | struct v4l2_exportbuffer *eb) |
444 | { | 443 | { |
445 | struct fimc_ctx *ctx = fh_to_ctx(fh); | 444 | struct fimc_ctx *ctx = fh_to_ctx(fh); |
446 | |||
447 | return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); | 445 | return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); |
448 | } | 446 | } |
449 | 447 | ||
@@ -452,15 +450,6 @@ static int fimc_m2m_streamon(struct file *file, void *fh, | |||
452 | enum v4l2_buf_type type) | 450 | enum v4l2_buf_type type) |
453 | { | 451 | { |
454 | struct fimc_ctx *ctx = fh_to_ctx(fh); | 452 | struct fimc_ctx *ctx = fh_to_ctx(fh); |
455 | |||
456 | /* The source and target color format need to be set */ | ||
457 | if (V4L2_TYPE_IS_OUTPUT(type)) { | ||
458 | if (!fimc_ctx_state_is_set(FIMC_SRC_FMT, ctx)) | ||
459 | return -EINVAL; | ||
460 | } else if (!fimc_ctx_state_is_set(FIMC_DST_FMT, ctx)) { | ||
461 | return -EINVAL; | ||
462 | } | ||
463 | |||
464 | return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); | 453 | return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); |
465 | } | 454 | } |
466 | 455 | ||
@@ -468,7 +457,6 @@ static int fimc_m2m_streamoff(struct file *file, void *fh, | |||
468 | enum v4l2_buf_type type) | 457 | enum v4l2_buf_type type) |
469 | { | 458 | { |
470 | struct fimc_ctx *ctx = fh_to_ctx(fh); | 459 | struct fimc_ctx *ctx = fh_to_ctx(fh); |
471 | |||
472 | return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | 460 | return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); |
473 | } | 461 | } |
474 | 462 | ||
@@ -576,20 +564,18 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop * | |||
576 | &ctx->s_frame : &ctx->d_frame; | 564 | &ctx->s_frame : &ctx->d_frame; |
577 | 565 | ||
578 | /* Check to see if scaling ratio is within supported range */ | 566 | /* Check to see if scaling ratio is within supported range */ |
579 | if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) { | 567 | if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
580 | if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | 568 | ret = fimc_check_scaler_ratio(ctx, cr.c.width, |
581 | ret = fimc_check_scaler_ratio(ctx, cr.c.width, | 569 | cr.c.height, ctx->d_frame.width, |
582 | cr.c.height, ctx->d_frame.width, | 570 | ctx->d_frame.height, ctx->rotation); |
583 | ctx->d_frame.height, ctx->rotation); | 571 | } else { |
584 | } else { | 572 | ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, |
585 | ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, | 573 | ctx->s_frame.height, cr.c.width, |
586 | ctx->s_frame.height, cr.c.width, | 574 | cr.c.height, ctx->rotation); |
587 | cr.c.height, ctx->rotation); | 575 | } |
588 | } | 576 | if (ret) { |
589 | if (ret) { | 577 | v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n"); |
590 | v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n"); | 578 | return -EINVAL; |
591 | return -EINVAL; | ||
592 | } | ||
593 | } | 579 | } |
594 | 580 | ||
595 | f->offs_h = cr.c.left; | 581 | f->offs_h = cr.c.left; |
@@ -652,6 +638,29 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, | |||
652 | return vb2_queue_init(dst_vq); | 638 | return vb2_queue_init(dst_vq); |
653 | } | 639 | } |
654 | 640 | ||
641 | static int fimc_m2m_set_default_format(struct fimc_ctx *ctx) | ||
642 | { | ||
643 | struct v4l2_pix_format_mplane pixm = { | ||
644 | .pixelformat = V4L2_PIX_FMT_RGB32, | ||
645 | .width = 800, | ||
646 | .height = 600, | ||
647 | .plane_fmt[0] = { | ||
648 | .bytesperline = 800 * 4, | ||
649 | .sizeimage = 800 * 4 * 600, | ||
650 | }, | ||
651 | }; | ||
652 | struct fimc_fmt *fmt; | ||
653 | |||
654 | fmt = fimc_find_format(&pixm.pixelformat, NULL, FMT_FLAGS_M2M, 0); | ||
655 | if (!fmt) | ||
656 | return -EINVAL; | ||
657 | |||
658 | __set_frame_format(&ctx->s_frame, fmt, &pixm); | ||
659 | __set_frame_format(&ctx->d_frame, fmt, &pixm); | ||
660 | |||
661 | return 0; | ||
662 | } | ||
663 | |||
655 | static int fimc_m2m_open(struct file *file) | 664 | static int fimc_m2m_open(struct file *file) |
656 | { | 665 | { |
657 | struct fimc_dev *fimc = video_drvdata(file); | 666 | struct fimc_dev *fimc = video_drvdata(file); |
@@ -696,6 +705,7 @@ static int fimc_m2m_open(struct file *file) | |||
696 | ctx->flags = 0; | 705 | ctx->flags = 0; |
697 | ctx->in_path = FIMC_IO_DMA; | 706 | ctx->in_path = FIMC_IO_DMA; |
698 | ctx->out_path = FIMC_IO_DMA; | 707 | ctx->out_path = FIMC_IO_DMA; |
708 | ctx->scaler.enabled = 1; | ||
699 | 709 | ||
700 | ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); | 710 | ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); |
701 | if (IS_ERR(ctx->m2m_ctx)) { | 711 | if (IS_ERR(ctx->m2m_ctx)) { |
@@ -706,9 +716,15 @@ static int fimc_m2m_open(struct file *file) | |||
706 | if (fimc->m2m.refcnt++ == 0) | 716 | if (fimc->m2m.refcnt++ == 0) |
707 | set_bit(ST_M2M_RUN, &fimc->state); | 717 | set_bit(ST_M2M_RUN, &fimc->state); |
708 | 718 | ||
719 | ret = fimc_m2m_set_default_format(ctx); | ||
720 | if (ret < 0) | ||
721 | goto error_m2m_ctx; | ||
722 | |||
709 | mutex_unlock(&fimc->lock); | 723 | mutex_unlock(&fimc->lock); |
710 | return 0; | 724 | return 0; |
711 | 725 | ||
726 | error_m2m_ctx: | ||
727 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | ||
712 | error_c: | 728 | error_c: |
713 | fimc_ctrls_delete(ctx); | 729 | fimc_ctrls_delete(ctx); |
714 | error_fh: | 730 | error_fh: |
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c index b4a68ecf0ca7..a17fcb2d5d41 100644 --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * S5P/EXYNOS4 SoC series camera host interface media device driver | 2 | * S5P/EXYNOS4 SoC series camera host interface media device driver |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | 4 | * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. |
5 | * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com> | 5 | * Sylwester Nawrocki <s.nawrocki@samsung.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published | 8 | * it under the terms of the GNU General Public License as published |
@@ -62,16 +62,17 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p, | |||
62 | sd = media_entity_to_v4l2_subdev(pad->entity); | 62 | sd = media_entity_to_v4l2_subdev(pad->entity); |
63 | 63 | ||
64 | switch (sd->grp_id) { | 64 | switch (sd->grp_id) { |
65 | case SENSOR_GROUP_ID: | 65 | case GRP_ID_FIMC_IS_SENSOR: |
66 | case GRP_ID_SENSOR: | ||
66 | p->subdevs[IDX_SENSOR] = sd; | 67 | p->subdevs[IDX_SENSOR] = sd; |
67 | break; | 68 | break; |
68 | case CSIS_GROUP_ID: | 69 | case GRP_ID_CSIS: |
69 | p->subdevs[IDX_CSIS] = sd; | 70 | p->subdevs[IDX_CSIS] = sd; |
70 | break; | 71 | break; |
71 | case FLITE_GROUP_ID: | 72 | case GRP_ID_FLITE: |
72 | p->subdevs[IDX_FLITE] = sd; | 73 | p->subdevs[IDX_FLITE] = sd; |
73 | break; | 74 | break; |
74 | case FIMC_GROUP_ID: | 75 | case GRP_ID_FIMC: |
75 | /* No need to control FIMC subdev through subdev ops */ | 76 | /* No need to control FIMC subdev through subdev ops */ |
76 | break; | 77 | break; |
77 | default: | 78 | default: |
@@ -141,7 +142,7 @@ static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state) | |||
141 | * @me: media entity to start graph walk with | 142 | * @me: media entity to start graph walk with |
142 | * @prep: true to acquire sensor (and csis) subdevs | 143 | * @prep: true to acquire sensor (and csis) subdevs |
143 | * | 144 | * |
144 | * This function must be called with the graph mutex held. | 145 | * Called with the graph mutex held. |
145 | */ | 146 | */ |
146 | static int __fimc_pipeline_open(struct fimc_pipeline *p, | 147 | static int __fimc_pipeline_open(struct fimc_pipeline *p, |
147 | struct media_entity *me, bool prep) | 148 | struct media_entity *me, bool prep) |
@@ -161,30 +162,19 @@ static int __fimc_pipeline_open(struct fimc_pipeline *p, | |||
161 | return fimc_pipeline_s_power(p, 1); | 162 | return fimc_pipeline_s_power(p, 1); |
162 | } | 163 | } |
163 | 164 | ||
164 | static int fimc_pipeline_open(struct fimc_pipeline *p, | ||
165 | struct media_entity *me, bool prep) | ||
166 | { | ||
167 | int ret; | ||
168 | |||
169 | mutex_lock(&me->parent->graph_mutex); | ||
170 | ret = __fimc_pipeline_open(p, me, prep); | ||
171 | mutex_unlock(&me->parent->graph_mutex); | ||
172 | |||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | /** | 165 | /** |
177 | * __fimc_pipeline_close - disable the sensor clock and pipeline power | 166 | * __fimc_pipeline_close - disable the sensor clock and pipeline power |
178 | * @fimc: fimc device terminating the pipeline | 167 | * @fimc: fimc device terminating the pipeline |
179 | * | 168 | * |
180 | * Disable power of all subdevs in the pipeline and turn off the external | 169 | * Disable power of all subdevs and turn the external sensor clock off. |
181 | * sensor clock. | ||
182 | * Called with the graph mutex held. | ||
183 | */ | 170 | */ |
184 | static int __fimc_pipeline_close(struct fimc_pipeline *p) | 171 | static int __fimc_pipeline_close(struct fimc_pipeline *p) |
185 | { | 172 | { |
186 | int ret = 0; | 173 | int ret = 0; |
187 | 174 | ||
175 | if (!p || !p->subdevs[IDX_SENSOR]) | ||
176 | return -EINVAL; | ||
177 | |||
188 | if (p->subdevs[IDX_SENSOR]) { | 178 | if (p->subdevs[IDX_SENSOR]) { |
189 | ret = fimc_pipeline_s_power(p, 0); | 179 | ret = fimc_pipeline_s_power(p, 0); |
190 | fimc_md_set_camclk(p->subdevs[IDX_SENSOR], false); | 180 | fimc_md_set_camclk(p->subdevs[IDX_SENSOR], false); |
@@ -192,28 +182,12 @@ static int __fimc_pipeline_close(struct fimc_pipeline *p) | |||
192 | return ret == -ENXIO ? 0 : ret; | 182 | return ret == -ENXIO ? 0 : ret; |
193 | } | 183 | } |
194 | 184 | ||
195 | static int fimc_pipeline_close(struct fimc_pipeline *p) | ||
196 | { | ||
197 | struct media_entity *me; | ||
198 | int ret; | ||
199 | |||
200 | if (!p || !p->subdevs[IDX_SENSOR]) | ||
201 | return -EINVAL; | ||
202 | |||
203 | me = &p->subdevs[IDX_SENSOR]->entity; | ||
204 | mutex_lock(&me->parent->graph_mutex); | ||
205 | ret = __fimc_pipeline_close(p); | ||
206 | mutex_unlock(&me->parent->graph_mutex); | ||
207 | |||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | /** | 185 | /** |
212 | * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs | 186 | * __fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs |
213 | * @pipeline: video pipeline structure | 187 | * @pipeline: video pipeline structure |
214 | * @on: passed as the s_stream call argument | 188 | * @on: passed as the s_stream call argument |
215 | */ | 189 | */ |
216 | static int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on) | 190 | static int __fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on) |
217 | { | 191 | { |
218 | int i, ret; | 192 | int i, ret; |
219 | 193 | ||
@@ -235,9 +209,9 @@ static int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on) | |||
235 | 209 | ||
236 | /* Media pipeline operations for the FIMC/FIMC-LITE video device driver */ | 210 | /* Media pipeline operations for the FIMC/FIMC-LITE video device driver */ |
237 | static const struct fimc_pipeline_ops fimc_pipeline_ops = { | 211 | static const struct fimc_pipeline_ops fimc_pipeline_ops = { |
238 | .open = fimc_pipeline_open, | 212 | .open = __fimc_pipeline_open, |
239 | .close = fimc_pipeline_close, | 213 | .close = __fimc_pipeline_close, |
240 | .set_stream = fimc_pipeline_s_stream, | 214 | .set_stream = __fimc_pipeline_s_stream, |
241 | }; | 215 | }; |
242 | 216 | ||
243 | /* | 217 | /* |
@@ -269,7 +243,7 @@ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd, | |||
269 | return ERR_PTR(-EPROBE_DEFER); | 243 | return ERR_PTR(-EPROBE_DEFER); |
270 | } | 244 | } |
271 | v4l2_set_subdev_hostdata(sd, s_info); | 245 | v4l2_set_subdev_hostdata(sd, s_info); |
272 | sd->grp_id = SENSOR_GROUP_ID; | 246 | sd->grp_id = GRP_ID_SENSOR; |
273 | 247 | ||
274 | v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n", | 248 | v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n", |
275 | s_info->pdata.board_info->type); | 249 | s_info->pdata.board_info->type); |
@@ -316,7 +290,7 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) | |||
316 | for (i = 0; i < num_clients; i++) { | 290 | for (i = 0; i < num_clients; i++) { |
317 | struct v4l2_subdev *sd; | 291 | struct v4l2_subdev *sd; |
318 | 292 | ||
319 | fmd->sensor[i].pdata = pdata->isp_info[i]; | 293 | fmd->sensor[i].pdata = pdata->source_info[i]; |
320 | ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true); | 294 | ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true); |
321 | if (ret) | 295 | if (ret) |
322 | break; | 296 | break; |
@@ -338,138 +312,149 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) | |||
338 | } | 312 | } |
339 | 313 | ||
340 | /* | 314 | /* |
341 | * MIPI CSIS and FIMC platform devices registration. | 315 | * MIPI-CSIS, FIMC and FIMC-LITE platform devices registration. |
342 | */ | 316 | */ |
343 | static int fimc_register_callback(struct device *dev, void *p) | 317 | |
318 | static int register_fimc_lite_entity(struct fimc_md *fmd, | ||
319 | struct fimc_lite *fimc_lite) | ||
344 | { | 320 | { |
345 | struct fimc_dev *fimc = dev_get_drvdata(dev); | ||
346 | struct v4l2_subdev *sd; | 321 | struct v4l2_subdev *sd; |
347 | struct fimc_md *fmd = p; | ||
348 | int ret; | 322 | int ret; |
349 | 323 | ||
350 | if (fimc == NULL || fimc->id >= FIMC_MAX_DEVS) | 324 | if (WARN_ON(fimc_lite->index >= FIMC_LITE_MAX_DEVS || |
351 | return 0; | 325 | fmd->fimc_lite[fimc_lite->index])) |
326 | return -EBUSY; | ||
352 | 327 | ||
353 | sd = &fimc->vid_cap.subdev; | 328 | sd = &fimc_lite->subdev; |
354 | sd->grp_id = FIMC_GROUP_ID; | 329 | sd->grp_id = GRP_ID_FLITE; |
355 | v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops); | 330 | v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops); |
356 | 331 | ||
357 | ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); | 332 | ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); |
358 | if (ret) { | 333 | if (!ret) |
359 | v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n", | 334 | fmd->fimc_lite[fimc_lite->index] = fimc_lite; |
360 | fimc->id, ret); | 335 | else |
361 | return ret; | 336 | v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.LITE%d\n", |
362 | } | 337 | fimc_lite->index); |
363 | 338 | return ret; | |
364 | fmd->fimc[fimc->id] = fimc; | ||
365 | return 0; | ||
366 | } | 339 | } |
367 | 340 | ||
368 | static int fimc_lite_register_callback(struct device *dev, void *p) | 341 | static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc) |
369 | { | 342 | { |
370 | struct fimc_lite *fimc = dev_get_drvdata(dev); | 343 | struct v4l2_subdev *sd; |
371 | struct fimc_md *fmd = p; | ||
372 | int ret; | 344 | int ret; |
373 | 345 | ||
374 | if (fimc == NULL || fimc->index >= FIMC_LITE_MAX_DEVS) | 346 | if (WARN_ON(fimc->id >= FIMC_MAX_DEVS || fmd->fimc[fimc->id])) |
375 | return 0; | 347 | return -EBUSY; |
376 | 348 | ||
377 | fimc->subdev.grp_id = FLITE_GROUP_ID; | 349 | sd = &fimc->vid_cap.subdev; |
378 | v4l2_set_subdev_hostdata(&fimc->subdev, (void *)&fimc_pipeline_ops); | 350 | sd->grp_id = GRP_ID_FIMC; |
351 | v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops); | ||
379 | 352 | ||
380 | ret = v4l2_device_register_subdev(&fmd->v4l2_dev, &fimc->subdev); | 353 | ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); |
381 | if (ret) { | 354 | if (!ret) { |
382 | v4l2_err(&fmd->v4l2_dev, | 355 | fmd->fimc[fimc->id] = fimc; |
383 | "Failed to register FIMC-LITE.%d (%d)\n", | 356 | fimc->vid_cap.user_subdev_api = fmd->user_subdev_api; |
384 | fimc->index, ret); | 357 | } else { |
385 | return ret; | 358 | v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n", |
359 | fimc->id, ret); | ||
386 | } | 360 | } |
387 | 361 | return ret; | |
388 | fmd->fimc_lite[fimc->index] = fimc; | ||
389 | return 0; | ||
390 | } | 362 | } |
391 | 363 | ||
392 | static int csis_register_callback(struct device *dev, void *p) | 364 | static int register_csis_entity(struct fimc_md *fmd, |
365 | struct platform_device *pdev, | ||
366 | struct v4l2_subdev *sd) | ||
393 | { | 367 | { |
394 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | 368 | struct device_node *node = pdev->dev.of_node; |
395 | struct platform_device *pdev; | ||
396 | struct fimc_md *fmd = p; | ||
397 | int id, ret; | 369 | int id, ret; |
398 | 370 | ||
399 | if (!sd) | 371 | id = node ? of_alias_get_id(node, "csis") : max(0, pdev->id); |
400 | return 0; | 372 | |
401 | pdev = v4l2_get_subdevdata(sd); | 373 | if (WARN_ON(id >= CSIS_MAX_ENTITIES || fmd->csis[id].sd)) |
402 | if (!pdev || pdev->id < 0 || pdev->id >= CSIS_MAX_ENTITIES) | 374 | return -EBUSY; |
403 | return 0; | ||
404 | v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name); | ||
405 | 375 | ||
406 | id = pdev->id < 0 ? 0 : pdev->id; | 376 | if (WARN_ON(id >= CSIS_MAX_ENTITIES)) |
407 | sd->grp_id = CSIS_GROUP_ID; | 377 | return 0; |
408 | 378 | ||
379 | sd->grp_id = GRP_ID_CSIS; | ||
409 | ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); | 380 | ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); |
410 | if (!ret) | 381 | if (!ret) |
411 | fmd->csis[id].sd = sd; | 382 | fmd->csis[id].sd = sd; |
412 | else | 383 | else |
413 | v4l2_err(&fmd->v4l2_dev, | 384 | v4l2_err(&fmd->v4l2_dev, |
414 | "Failed to register CSIS subdevice: %d\n", ret); | 385 | "Failed to register MIPI-CSIS.%d (%d)\n", id, ret); |
415 | return ret; | 386 | return ret; |
416 | } | 387 | } |
417 | 388 | ||
418 | /** | 389 | static int fimc_md_register_platform_entity(struct fimc_md *fmd, |
419 | * fimc_md_register_platform_entities - register FIMC and CSIS media entities | 390 | struct platform_device *pdev, |
420 | */ | 391 | int plat_entity) |
421 | static int fimc_md_register_platform_entities(struct fimc_md *fmd) | ||
422 | { | 392 | { |
423 | struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data; | 393 | struct device *dev = &pdev->dev; |
424 | struct device_driver *driver; | 394 | int ret = -EPROBE_DEFER; |
425 | int ret, i; | 395 | void *drvdata; |
426 | 396 | ||
427 | driver = driver_find(FIMC_MODULE_NAME, &platform_bus_type); | 397 | /* Lock to ensure dev->driver won't change. */ |
428 | if (!driver) { | 398 | device_lock(dev); |
429 | v4l2_warn(&fmd->v4l2_dev, | 399 | |
430 | "%s driver not found, deffering probe\n", | 400 | if (!dev->driver || !try_module_get(dev->driver->owner)) |
431 | FIMC_MODULE_NAME); | 401 | goto dev_unlock; |
432 | return -EPROBE_DEFER; | 402 | |
433 | } | 403 | drvdata = dev_get_drvdata(dev); |
434 | 404 | /* Some subdev didn't probe succesfully id drvdata is NULL */ | |
435 | ret = driver_for_each_device(driver, NULL, fmd, | 405 | if (drvdata) { |
436 | fimc_register_callback); | 406 | switch (plat_entity) { |
437 | if (ret) | 407 | case IDX_FIMC: |
438 | return ret; | 408 | ret = register_fimc_entity(fmd, drvdata); |
439 | |||
440 | driver = driver_find(FIMC_LITE_DRV_NAME, &platform_bus_type); | ||
441 | if (driver && try_module_get(driver->owner)) { | ||
442 | ret = driver_for_each_device(driver, NULL, fmd, | ||
443 | fimc_lite_register_callback); | ||
444 | if (ret) | ||
445 | return ret; | ||
446 | module_put(driver->owner); | ||
447 | } | ||
448 | /* | ||
449 | * Check if there is any sensor on the MIPI-CSI2 bus and | ||
450 | * if not skip the s5p-csis module loading. | ||
451 | */ | ||
452 | if (pdata == NULL) | ||
453 | return 0; | ||
454 | for (i = 0; i < pdata->num_clients; i++) { | ||
455 | if (pdata->isp_info[i].bus_type == FIMC_MIPI_CSI2) { | ||
456 | ret = 1; | ||
457 | break; | 409 | break; |
410 | case IDX_FLITE: | ||
411 | ret = register_fimc_lite_entity(fmd, drvdata); | ||
412 | break; | ||
413 | case IDX_CSIS: | ||
414 | ret = register_csis_entity(fmd, pdev, drvdata); | ||
415 | break; | ||
416 | default: | ||
417 | ret = -ENODEV; | ||
458 | } | 418 | } |
459 | } | 419 | } |
460 | if (!ret) | ||
461 | return 0; | ||
462 | 420 | ||
463 | driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); | 421 | module_put(dev->driver->owner); |
464 | if (!driver || !try_module_get(driver->owner)) { | 422 | dev_unlock: |
465 | v4l2_warn(&fmd->v4l2_dev, | 423 | device_unlock(dev); |
466 | "%s driver not found, deffering probe\n", | 424 | if (ret == -EPROBE_DEFER) |
467 | CSIS_DRIVER_NAME); | 425 | dev_info(&fmd->pdev->dev, "deferring %s device registration\n", |
468 | return -EPROBE_DEFER; | 426 | dev_name(dev)); |
427 | else if (ret < 0) | ||
428 | dev_err(&fmd->pdev->dev, "%s device registration failed (%d)\n", | ||
429 | dev_name(dev), ret); | ||
430 | return ret; | ||
431 | } | ||
432 | |||
433 | static int fimc_md_pdev_match(struct device *dev, void *data) | ||
434 | { | ||
435 | struct platform_device *pdev = to_platform_device(dev); | ||
436 | int plat_entity = -1; | ||
437 | int ret; | ||
438 | char *p; | ||
439 | |||
440 | if (!get_device(dev)) | ||
441 | return -ENODEV; | ||
442 | |||
443 | if (!strcmp(pdev->name, CSIS_DRIVER_NAME)) { | ||
444 | plat_entity = IDX_CSIS; | ||
445 | } else if (!strcmp(pdev->name, FIMC_LITE_DRV_NAME)) { | ||
446 | plat_entity = IDX_FLITE; | ||
447 | } else { | ||
448 | p = strstr(pdev->name, "fimc"); | ||
449 | if (p && *(p + 4) == 0) | ||
450 | plat_entity = IDX_FIMC; | ||
469 | } | 451 | } |
470 | 452 | ||
471 | return driver_for_each_device(driver, NULL, fmd, | 453 | if (plat_entity >= 0) |
472 | csis_register_callback); | 454 | ret = fimc_md_register_platform_entity(data, pdev, |
455 | plat_entity); | ||
456 | put_device(dev); | ||
457 | return 0; | ||
473 | } | 458 | } |
474 | 459 | ||
475 | static void fimc_md_unregister_entities(struct fimc_md *fmd) | 460 | static void fimc_md_unregister_entities(struct fimc_md *fmd) |
@@ -487,7 +472,7 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) | |||
487 | if (fmd->fimc_lite[i] == NULL) | 472 | if (fmd->fimc_lite[i] == NULL) |
488 | continue; | 473 | continue; |
489 | v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev); | 474 | v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev); |
490 | fmd->fimc[i]->pipeline_ops = NULL; | 475 | fmd->fimc_lite[i]->pipeline_ops = NULL; |
491 | fmd->fimc_lite[i] = NULL; | 476 | fmd->fimc_lite[i] = NULL; |
492 | } | 477 | } |
493 | for (i = 0; i < CSIS_MAX_ENTITIES; i++) { | 478 | for (i = 0; i < CSIS_MAX_ENTITIES; i++) { |
@@ -503,6 +488,7 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) | |||
503 | fimc_md_unregister_sensor(fmd->sensor[i].subdev); | 488 | fimc_md_unregister_sensor(fmd->sensor[i].subdev); |
504 | fmd->sensor[i].subdev = NULL; | 489 | fmd->sensor[i].subdev = NULL; |
505 | } | 490 | } |
491 | v4l2_info(&fmd->v4l2_dev, "Unregistered all entities\n"); | ||
506 | } | 492 | } |
507 | 493 | ||
508 | /** | 494 | /** |
@@ -518,7 +504,7 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, | |||
518 | struct v4l2_subdev *sensor, | 504 | struct v4l2_subdev *sensor, |
519 | int pad, int link_mask) | 505 | int pad, int link_mask) |
520 | { | 506 | { |
521 | struct fimc_sensor_info *s_info; | 507 | struct fimc_sensor_info *s_info = NULL; |
522 | struct media_entity *sink; | 508 | struct media_entity *sink; |
523 | unsigned int flags = 0; | 509 | unsigned int flags = 0; |
524 | int ret, i; | 510 | int ret, i; |
@@ -582,7 +568,7 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, | |||
582 | if (ret) | 568 | if (ret) |
583 | break; | 569 | break; |
584 | 570 | ||
585 | v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", | 571 | v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]\n", |
586 | source->name, flags ? '=' : '-', sink->name); | 572 | source->name, flags ? '=' : '-', sink->name); |
587 | } | 573 | } |
588 | return 0; | 574 | return 0; |
@@ -602,7 +588,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) | |||
602 | source = &fimc->subdev.entity; | 588 | source = &fimc->subdev.entity; |
603 | sink = &fimc->vfd.entity; | 589 | sink = &fimc->vfd.entity; |
604 | /* FIMC-LITE's subdev and video node */ | 590 | /* FIMC-LITE's subdev and video node */ |
605 | ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, | 591 | ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE_DMA, |
606 | sink, 0, flags); | 592 | sink, 0, flags); |
607 | if (ret) | 593 | if (ret) |
608 | break; | 594 | break; |
@@ -626,9 +612,9 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) | |||
626 | */ | 612 | */ |
627 | static int fimc_md_create_links(struct fimc_md *fmd) | 613 | static int fimc_md_create_links(struct fimc_md *fmd) |
628 | { | 614 | { |
629 | struct v4l2_subdev *csi_sensors[2] = { NULL }; | 615 | struct v4l2_subdev *csi_sensors[CSIS_MAX_ENTITIES] = { NULL }; |
630 | struct v4l2_subdev *sensor, *csis; | 616 | struct v4l2_subdev *sensor, *csis; |
631 | struct s5p_fimc_isp_info *pdata; | 617 | struct fimc_source_info *pdata; |
632 | struct fimc_sensor_info *s_info; | 618 | struct fimc_sensor_info *s_info; |
633 | struct media_entity *source, *sink; | 619 | struct media_entity *source, *sink; |
634 | int i, pad, fimc_id = 0, ret = 0; | 620 | int i, pad, fimc_id = 0, ret = 0; |
@@ -646,8 +632,8 @@ static int fimc_md_create_links(struct fimc_md *fmd) | |||
646 | source = NULL; | 632 | source = NULL; |
647 | pdata = &s_info->pdata; | 633 | pdata = &s_info->pdata; |
648 | 634 | ||
649 | switch (pdata->bus_type) { | 635 | switch (pdata->sensor_bus_type) { |
650 | case FIMC_MIPI_CSI2: | 636 | case FIMC_BUS_TYPE_MIPI_CSI2: |
651 | if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES, | 637 | if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES, |
652 | "Wrong CSI channel id: %d\n", pdata->mux_id)) | 638 | "Wrong CSI channel id: %d\n", pdata->mux_id)) |
653 | return -EINVAL; | 639 | return -EINVAL; |
@@ -658,28 +644,29 @@ static int fimc_md_create_links(struct fimc_md *fmd) | |||
658 | "but s5p-csis module is not loaded!\n")) | 644 | "but s5p-csis module is not loaded!\n")) |
659 | return -EINVAL; | 645 | return -EINVAL; |
660 | 646 | ||
661 | ret = media_entity_create_link(&sensor->entity, 0, | 647 | pad = sensor->entity.num_pads - 1; |
648 | ret = media_entity_create_link(&sensor->entity, pad, | ||
662 | &csis->entity, CSIS_PAD_SINK, | 649 | &csis->entity, CSIS_PAD_SINK, |
663 | MEDIA_LNK_FL_IMMUTABLE | | 650 | MEDIA_LNK_FL_IMMUTABLE | |
664 | MEDIA_LNK_FL_ENABLED); | 651 | MEDIA_LNK_FL_ENABLED); |
665 | if (ret) | 652 | if (ret) |
666 | return ret; | 653 | return ret; |
667 | 654 | ||
668 | v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]", | 655 | v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]\n", |
669 | sensor->entity.name, csis->entity.name); | 656 | sensor->entity.name, csis->entity.name); |
670 | 657 | ||
671 | source = NULL; | 658 | source = NULL; |
672 | csi_sensors[pdata->mux_id] = sensor; | 659 | csi_sensors[pdata->mux_id] = sensor; |
673 | break; | 660 | break; |
674 | 661 | ||
675 | case FIMC_ITU_601...FIMC_ITU_656: | 662 | case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656: |
676 | source = &sensor->entity; | 663 | source = &sensor->entity; |
677 | pad = 0; | 664 | pad = 0; |
678 | break; | 665 | break; |
679 | 666 | ||
680 | default: | 667 | default: |
681 | v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n", | 668 | v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n", |
682 | pdata->bus_type); | 669 | pdata->sensor_bus_type); |
683 | return -EINVAL; | 670 | return -EINVAL; |
684 | } | 671 | } |
685 | if (source == NULL) | 672 | if (source == NULL) |
@@ -690,7 +677,7 @@ static int fimc_md_create_links(struct fimc_md *fmd) | |||
690 | pad, link_mask); | 677 | pad, link_mask); |
691 | } | 678 | } |
692 | 679 | ||
693 | for (i = 0; i < ARRAY_SIZE(fmd->csis); i++) { | 680 | for (i = 0; i < CSIS_MAX_ENTITIES; i++) { |
694 | if (fmd->csis[i].sd == NULL) | 681 | if (fmd->csis[i].sd == NULL) |
695 | continue; | 682 | continue; |
696 | source = &fmd->csis[i].sd->entity; | 683 | source = &fmd->csis[i].sd->entity; |
@@ -721,42 +708,61 @@ static int fimc_md_create_links(struct fimc_md *fmd) | |||
721 | /* | 708 | /* |
722 | * The peripheral sensor clock management. | 709 | * The peripheral sensor clock management. |
723 | */ | 710 | */ |
711 | static void fimc_md_put_clocks(struct fimc_md *fmd) | ||
712 | { | ||
713 | int i = FIMC_MAX_CAMCLKS; | ||
714 | |||
715 | while (--i >= 0) { | ||
716 | if (IS_ERR(fmd->camclk[i].clock)) | ||
717 | continue; | ||
718 | clk_unprepare(fmd->camclk[i].clock); | ||
719 | clk_put(fmd->camclk[i].clock); | ||
720 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); | ||
721 | } | ||
722 | } | ||
723 | |||
724 | static int fimc_md_get_clocks(struct fimc_md *fmd) | 724 | static int fimc_md_get_clocks(struct fimc_md *fmd) |
725 | { | 725 | { |
726 | struct device *dev = NULL; | ||
726 | char clk_name[32]; | 727 | char clk_name[32]; |
727 | struct clk *clock; | 728 | struct clk *clock; |
728 | int i; | 729 | int ret, i; |
730 | |||
731 | for (i = 0; i < FIMC_MAX_CAMCLKS; i++) | ||
732 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); | ||
733 | |||
734 | if (fmd->pdev->dev.of_node) | ||
735 | dev = &fmd->pdev->dev; | ||
729 | 736 | ||
730 | for (i = 0; i < FIMC_MAX_CAMCLKS; i++) { | 737 | for (i = 0; i < FIMC_MAX_CAMCLKS; i++) { |
731 | snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i); | 738 | snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i); |
732 | clock = clk_get(NULL, clk_name); | 739 | clock = clk_get(dev, clk_name); |
733 | if (IS_ERR_OR_NULL(clock)) { | 740 | |
734 | v4l2_err(&fmd->v4l2_dev, "Failed to get clock: %s", | 741 | if (IS_ERR(clock)) { |
735 | clk_name); | 742 | dev_err(&fmd->pdev->dev, "Failed to get clock: %s\n", |
736 | return -ENXIO; | 743 | clk_name); |
744 | ret = PTR_ERR(clock); | ||
745 | break; | ||
746 | } | ||
747 | ret = clk_prepare(clock); | ||
748 | if (ret < 0) { | ||
749 | clk_put(clock); | ||
750 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); | ||
751 | break; | ||
737 | } | 752 | } |
738 | fmd->camclk[i].clock = clock; | 753 | fmd->camclk[i].clock = clock; |
739 | } | 754 | } |
740 | return 0; | 755 | if (ret) |
741 | } | 756 | fimc_md_put_clocks(fmd); |
742 | |||
743 | static void fimc_md_put_clocks(struct fimc_md *fmd) | ||
744 | { | ||
745 | int i = FIMC_MAX_CAMCLKS; | ||
746 | 757 | ||
747 | while (--i >= 0) { | 758 | return ret; |
748 | if (IS_ERR_OR_NULL(fmd->camclk[i].clock)) | ||
749 | continue; | ||
750 | clk_put(fmd->camclk[i].clock); | ||
751 | fmd->camclk[i].clock = NULL; | ||
752 | } | ||
753 | } | 759 | } |
754 | 760 | ||
755 | static int __fimc_md_set_camclk(struct fimc_md *fmd, | 761 | static int __fimc_md_set_camclk(struct fimc_md *fmd, |
756 | struct fimc_sensor_info *s_info, | 762 | struct fimc_sensor_info *s_info, |
757 | bool on) | 763 | bool on) |
758 | { | 764 | { |
759 | struct s5p_fimc_isp_info *pdata = &s_info->pdata; | 765 | struct fimc_source_info *pdata = &s_info->pdata; |
760 | struct fimc_camclk_info *camclk; | 766 | struct fimc_camclk_info *camclk; |
761 | int ret = 0; | 767 | int ret = 0; |
762 | 768 | ||
@@ -820,7 +826,9 @@ static int fimc_md_link_notify(struct media_pad *source, | |||
820 | struct fimc_dev *fimc = NULL; | 826 | struct fimc_dev *fimc = NULL; |
821 | struct fimc_pipeline *pipeline; | 827 | struct fimc_pipeline *pipeline; |
822 | struct v4l2_subdev *sd; | 828 | struct v4l2_subdev *sd; |
829 | struct mutex *lock; | ||
823 | int ret = 0; | 830 | int ret = 0; |
831 | int ref_count; | ||
824 | 832 | ||
825 | if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | 833 | if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) |
826 | return 0; | 834 | return 0; |
@@ -828,28 +836,33 @@ static int fimc_md_link_notify(struct media_pad *source, | |||
828 | sd = media_entity_to_v4l2_subdev(sink->entity); | 836 | sd = media_entity_to_v4l2_subdev(sink->entity); |
829 | 837 | ||
830 | switch (sd->grp_id) { | 838 | switch (sd->grp_id) { |
831 | case FLITE_GROUP_ID: | 839 | case GRP_ID_FLITE: |
832 | fimc_lite = v4l2_get_subdevdata(sd); | 840 | fimc_lite = v4l2_get_subdevdata(sd); |
841 | if (WARN_ON(fimc_lite == NULL)) | ||
842 | return 0; | ||
833 | pipeline = &fimc_lite->pipeline; | 843 | pipeline = &fimc_lite->pipeline; |
844 | lock = &fimc_lite->lock; | ||
834 | break; | 845 | break; |
835 | case FIMC_GROUP_ID: | 846 | case GRP_ID_FIMC: |
836 | fimc = v4l2_get_subdevdata(sd); | 847 | fimc = v4l2_get_subdevdata(sd); |
848 | if (WARN_ON(fimc == NULL)) | ||
849 | return 0; | ||
837 | pipeline = &fimc->pipeline; | 850 | pipeline = &fimc->pipeline; |
851 | lock = &fimc->lock; | ||
838 | break; | 852 | break; |
839 | default: | 853 | default: |
840 | return 0; | 854 | return 0; |
841 | } | 855 | } |
842 | 856 | ||
843 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 857 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
858 | int i; | ||
859 | mutex_lock(lock); | ||
844 | ret = __fimc_pipeline_close(pipeline); | 860 | ret = __fimc_pipeline_close(pipeline); |
845 | pipeline->subdevs[IDX_SENSOR] = NULL; | 861 | for (i = 0; i < IDX_MAX; i++) |
846 | pipeline->subdevs[IDX_CSIS] = NULL; | 862 | pipeline->subdevs[i] = NULL; |
847 | 863 | if (fimc) | |
848 | if (fimc) { | ||
849 | mutex_lock(&fimc->lock); | ||
850 | fimc_ctrls_delete(fimc->vid_cap.ctx); | 864 | fimc_ctrls_delete(fimc->vid_cap.ctx); |
851 | mutex_unlock(&fimc->lock); | 865 | mutex_unlock(lock); |
852 | } | ||
853 | return ret; | 866 | return ret; |
854 | } | 867 | } |
855 | /* | 868 | /* |
@@ -857,23 +870,15 @@ static int fimc_md_link_notify(struct media_pad *source, | |||
857 | * pipeline is already in use, i.e. its video node is opened. | 870 | * pipeline is already in use, i.e. its video node is opened. |
858 | * Recreate the controls destroyed during the link deactivation. | 871 | * Recreate the controls destroyed during the link deactivation. |
859 | */ | 872 | */ |
860 | if (fimc) { | 873 | mutex_lock(lock); |
861 | mutex_lock(&fimc->lock); | 874 | |
862 | if (fimc->vid_cap.refcnt > 0) { | 875 | ref_count = fimc ? fimc->vid_cap.refcnt : fimc_lite->ref_count; |
863 | ret = __fimc_pipeline_open(pipeline, | 876 | if (ref_count > 0) |
864 | source->entity, true); | 877 | ret = __fimc_pipeline_open(pipeline, source->entity, true); |
865 | if (!ret) | 878 | if (!ret && fimc) |
866 | ret = fimc_capture_ctrls_create(fimc); | 879 | ret = fimc_capture_ctrls_create(fimc); |
867 | } | 880 | |
868 | mutex_unlock(&fimc->lock); | 881 | mutex_unlock(lock); |
869 | } else { | ||
870 | mutex_lock(&fimc_lite->lock); | ||
871 | if (fimc_lite->ref_count > 0) { | ||
872 | ret = __fimc_pipeline_open(pipeline, | ||
873 | source->entity, true); | ||
874 | } | ||
875 | mutex_unlock(&fimc_lite->lock); | ||
876 | } | ||
877 | return ret ? -EPIPE : ret; | 882 | return ret ? -EPIPE : ret; |
878 | } | 883 | } |
879 | 884 | ||
@@ -965,7 +970,8 @@ static int fimc_md_probe(struct platform_device *pdev) | |||
965 | /* Protect the media graph while we're registering entities */ | 970 | /* Protect the media graph while we're registering entities */ |
966 | mutex_lock(&fmd->media_dev.graph_mutex); | 971 | mutex_lock(&fmd->media_dev.graph_mutex); |
967 | 972 | ||
968 | ret = fimc_md_register_platform_entities(fmd); | 973 | ret = bus_for_each_dev(&platform_bus_type, NULL, fmd, |
974 | fimc_md_pdev_match); | ||
969 | if (ret) | 975 | if (ret) |
970 | goto err_unlock; | 976 | goto err_unlock; |
971 | 977 | ||
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.h b/drivers/media/platform/s5p-fimc/fimc-mdevice.h index 2d8d41d82620..06b0d8276fd2 100644 --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.h +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.h | |||
@@ -22,11 +22,13 @@ | |||
22 | #include "mipi-csis.h" | 22 | #include "mipi-csis.h" |
23 | 23 | ||
24 | /* Group IDs of sensor, MIPI-CSIS, FIMC-LITE and the writeback subdevs. */ | 24 | /* Group IDs of sensor, MIPI-CSIS, FIMC-LITE and the writeback subdevs. */ |
25 | #define SENSOR_GROUP_ID (1 << 8) | 25 | #define GRP_ID_SENSOR (1 << 8) |
26 | #define CSIS_GROUP_ID (1 << 9) | 26 | #define GRP_ID_FIMC_IS_SENSOR (1 << 9) |
27 | #define WRITEBACK_GROUP_ID (1 << 10) | 27 | #define GRP_ID_WRITEBACK (1 << 10) |
28 | #define FIMC_GROUP_ID (1 << 11) | 28 | #define GRP_ID_CSIS (1 << 11) |
29 | #define FLITE_GROUP_ID (1 << 12) | 29 | #define GRP_ID_FIMC (1 << 12) |
30 | #define GRP_ID_FLITE (1 << 13) | ||
31 | #define GRP_ID_FIMC_IS (1 << 14) | ||
30 | 32 | ||
31 | #define FIMC_MAX_SENSORS 8 | 33 | #define FIMC_MAX_SENSORS 8 |
32 | #define FIMC_MAX_CAMCLKS 2 | 34 | #define FIMC_MAX_CAMCLKS 2 |
@@ -51,7 +53,7 @@ struct fimc_camclk_info { | |||
51 | * This data structure applies to image sensor and the writeback subdevs. | 53 | * This data structure applies to image sensor and the writeback subdevs. |
52 | */ | 54 | */ |
53 | struct fimc_sensor_info { | 55 | struct fimc_sensor_info { |
54 | struct s5p_fimc_isp_info pdata; | 56 | struct fimc_source_info pdata; |
55 | struct v4l2_subdev *subdev; | 57 | struct v4l2_subdev *subdev; |
56 | struct fimc_dev *host; | 58 | struct fimc_dev *host; |
57 | }; | 59 | }; |
diff --git a/drivers/media/platform/s5p-fimc/fimc-reg.c b/drivers/media/platform/s5p-fimc/fimc-reg.c index 2c9d0c06c9e8..50b97c75b956 100644 --- a/drivers/media/platform/s5p-fimc/fimc-reg.c +++ b/drivers/media/platform/s5p-fimc/fimc-reg.c | |||
@@ -44,9 +44,9 @@ static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx) | |||
44 | u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL; | 44 | u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL; |
45 | 45 | ||
46 | if (ctx->hflip) | 46 | if (ctx->hflip) |
47 | flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR; | ||
48 | if (ctx->vflip) | ||
49 | flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR; | 47 | flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR; |
48 | if (ctx->vflip) | ||
49 | flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR; | ||
50 | 50 | ||
51 | if (ctx->rotation <= 90) | 51 | if (ctx->rotation <= 90) |
52 | return flip; | 52 | return flip; |
@@ -59,9 +59,9 @@ static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx) | |||
59 | u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL; | 59 | u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL; |
60 | 60 | ||
61 | if (ctx->hflip) | 61 | if (ctx->hflip) |
62 | flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR; | ||
63 | if (ctx->vflip) | ||
64 | flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR; | 62 | flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR; |
63 | if (ctx->vflip) | ||
64 | flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR; | ||
65 | 65 | ||
66 | if (ctx->rotation <= 90) | 66 | if (ctx->rotation <= 90) |
67 | return flip; | 67 | return flip; |
@@ -312,7 +312,7 @@ static void fimc_hw_set_scaler(struct fimc_ctx *ctx) | |||
312 | void fimc_hw_set_mainscaler(struct fimc_ctx *ctx) | 312 | void fimc_hw_set_mainscaler(struct fimc_ctx *ctx) |
313 | { | 313 | { |
314 | struct fimc_dev *dev = ctx->fimc_dev; | 314 | struct fimc_dev *dev = ctx->fimc_dev; |
315 | struct fimc_variant *variant = dev->variant; | 315 | const struct fimc_variant *variant = dev->variant; |
316 | struct fimc_scaler *sc = &ctx->scaler; | 316 | struct fimc_scaler *sc = &ctx->scaler; |
317 | u32 cfg; | 317 | u32 cfg; |
318 | 318 | ||
@@ -344,30 +344,31 @@ void fimc_hw_set_mainscaler(struct fimc_ctx *ctx) | |||
344 | } | 344 | } |
345 | } | 345 | } |
346 | 346 | ||
347 | void fimc_hw_en_capture(struct fimc_ctx *ctx) | 347 | void fimc_hw_enable_capture(struct fimc_ctx *ctx) |
348 | { | 348 | { |
349 | struct fimc_dev *dev = ctx->fimc_dev; | 349 | struct fimc_dev *dev = ctx->fimc_dev; |
350 | u32 cfg; | ||
350 | 351 | ||
351 | u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT); | 352 | cfg = readl(dev->regs + FIMC_REG_CIIMGCPT); |
352 | 353 | cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE; | |
353 | if (ctx->out_path == FIMC_IO_DMA) { | ||
354 | /* one shot mode */ | ||
355 | cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE | | ||
356 | FIMC_REG_CIIMGCPT_IMGCPTEN; | ||
357 | } else { | ||
358 | /* Continuous frame capture mode (freerun). */ | ||
359 | cfg &= ~(FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE | | ||
360 | FIMC_REG_CIIMGCPT_CPT_FRMOD_CNT); | ||
361 | cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN; | ||
362 | } | ||
363 | 354 | ||
364 | if (ctx->scaler.enabled) | 355 | if (ctx->scaler.enabled) |
365 | cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC; | 356 | cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC; |
357 | else | ||
358 | cfg &= FIMC_REG_CIIMGCPT_IMGCPTEN_SC; | ||
366 | 359 | ||
367 | cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN; | 360 | cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN; |
368 | writel(cfg, dev->regs + FIMC_REG_CIIMGCPT); | 361 | writel(cfg, dev->regs + FIMC_REG_CIIMGCPT); |
369 | } | 362 | } |
370 | 363 | ||
364 | void fimc_hw_disable_capture(struct fimc_dev *dev) | ||
365 | { | ||
366 | u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT); | ||
367 | cfg &= ~(FIMC_REG_CIIMGCPT_IMGCPTEN | | ||
368 | FIMC_REG_CIIMGCPT_IMGCPTEN_SC); | ||
369 | writel(cfg, dev->regs + FIMC_REG_CIIMGCPT); | ||
370 | } | ||
371 | |||
371 | void fimc_hw_set_effect(struct fimc_ctx *ctx) | 372 | void fimc_hw_set_effect(struct fimc_ctx *ctx) |
372 | { | 373 | { |
373 | struct fimc_dev *dev = ctx->fimc_dev; | 374 | struct fimc_dev *dev = ctx->fimc_dev; |
@@ -553,7 +554,7 @@ void fimc_hw_set_output_addr(struct fimc_dev *dev, | |||
553 | } | 554 | } |
554 | 555 | ||
555 | int fimc_hw_set_camera_polarity(struct fimc_dev *fimc, | 556 | int fimc_hw_set_camera_polarity(struct fimc_dev *fimc, |
556 | struct s5p_fimc_isp_info *cam) | 557 | struct fimc_source_info *cam) |
557 | { | 558 | { |
558 | u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL); | 559 | u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL); |
559 | 560 | ||
@@ -595,14 +596,15 @@ static const struct mbus_pixfmt_desc pix_desc[] = { | |||
595 | }; | 596 | }; |
596 | 597 | ||
597 | int fimc_hw_set_camera_source(struct fimc_dev *fimc, | 598 | int fimc_hw_set_camera_source(struct fimc_dev *fimc, |
598 | struct s5p_fimc_isp_info *cam) | 599 | struct fimc_source_info *source) |
599 | { | 600 | { |
600 | struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; | 601 | struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; |
601 | u32 cfg = 0; | 602 | u32 bus_width, cfg = 0; |
602 | u32 bus_width; | ||
603 | int i; | 603 | int i; |
604 | 604 | ||
605 | if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) { | 605 | switch (source->fimc_bus_type) { |
606 | case FIMC_BUS_TYPE_ITU_601: | ||
607 | case FIMC_BUS_TYPE_ITU_656: | ||
606 | for (i = 0; i < ARRAY_SIZE(pix_desc); i++) { | 608 | for (i = 0; i < ARRAY_SIZE(pix_desc); i++) { |
607 | if (fimc->vid_cap.mf.code == pix_desc[i].pixelcode) { | 609 | if (fimc->vid_cap.mf.code == pix_desc[i].pixelcode) { |
608 | cfg = pix_desc[i].cisrcfmt; | 610 | cfg = pix_desc[i].cisrcfmt; |
@@ -618,15 +620,17 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc, | |||
618 | return -EINVAL; | 620 | return -EINVAL; |
619 | } | 621 | } |
620 | 622 | ||
621 | if (cam->bus_type == FIMC_ITU_601) { | 623 | if (source->fimc_bus_type == FIMC_BUS_TYPE_ITU_601) { |
622 | if (bus_width == 8) | 624 | if (bus_width == 8) |
623 | cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; | 625 | cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; |
624 | else if (bus_width == 16) | 626 | else if (bus_width == 16) |
625 | cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT; | 627 | cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT; |
626 | } /* else defaults to ITU-R BT.656 8-bit */ | 628 | } /* else defaults to ITU-R BT.656 8-bit */ |
627 | } else if (cam->bus_type == FIMC_MIPI_CSI2) { | 629 | break; |
630 | case FIMC_BUS_TYPE_MIPI_CSI2: | ||
628 | if (fimc_fmt_is_user_defined(f->fmt->color)) | 631 | if (fimc_fmt_is_user_defined(f->fmt->color)) |
629 | cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; | 632 | cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; |
633 | break; | ||
630 | } | 634 | } |
631 | 635 | ||
632 | cfg |= (f->o_width << 16) | f->o_height; | 636 | cfg |= (f->o_width << 16) | f->o_height; |
@@ -654,7 +658,7 @@ void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f) | |||
654 | } | 658 | } |
655 | 659 | ||
656 | int fimc_hw_set_camera_type(struct fimc_dev *fimc, | 660 | int fimc_hw_set_camera_type(struct fimc_dev *fimc, |
657 | struct s5p_fimc_isp_info *cam) | 661 | struct fimc_source_info *source) |
658 | { | 662 | { |
659 | u32 cfg, tmp; | 663 | u32 cfg, tmp; |
660 | struct fimc_vid_cap *vid_cap = &fimc->vid_cap; | 664 | struct fimc_vid_cap *vid_cap = &fimc->vid_cap; |
@@ -667,11 +671,11 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, | |||
667 | FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB | | 671 | FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB | |
668 | FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG); | 672 | FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG); |
669 | 673 | ||
670 | switch (cam->bus_type) { | 674 | switch (source->fimc_bus_type) { |
671 | case FIMC_MIPI_CSI2: | 675 | case FIMC_BUS_TYPE_MIPI_CSI2: |
672 | cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI; | 676 | cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI; |
673 | 677 | ||
674 | if (cam->mux_id == 0) | 678 | if (source->mux_id == 0) |
675 | cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A; | 679 | cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A; |
676 | 680 | ||
677 | /* TODO: add remaining supported formats. */ | 681 | /* TODO: add remaining supported formats. */ |
@@ -694,15 +698,16 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, | |||
694 | 698 | ||
695 | writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT); | 699 | writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT); |
696 | break; | 700 | break; |
697 | case FIMC_ITU_601...FIMC_ITU_656: | 701 | case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656: |
698 | if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */ | 702 | if (source->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */ |
699 | cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A; | 703 | cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A; |
700 | break; | 704 | break; |
701 | case FIMC_LCD_WB: | 705 | case FIMC_BUS_TYPE_LCD_WRITEBACK_A: |
702 | cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB; | 706 | cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB; |
703 | break; | 707 | break; |
704 | default: | 708 | default: |
705 | v4l2_err(&vid_cap->vfd, "Invalid camera bus type selected\n"); | 709 | v4l2_err(&vid_cap->vfd, "Invalid FIMC bus type selected: %d\n", |
710 | source->fimc_bus_type); | ||
706 | return -EINVAL; | 711 | return -EINVAL; |
707 | } | 712 | } |
708 | writel(cfg, fimc->regs + FIMC_REG_CIGCTRL); | 713 | writel(cfg, fimc->regs + FIMC_REG_CIGCTRL); |
@@ -737,13 +742,6 @@ void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on) | |||
737 | writel(cfg, dev->regs + FIMC_REG_MSCTRL); | 742 | writel(cfg, dev->regs + FIMC_REG_MSCTRL); |
738 | } | 743 | } |
739 | 744 | ||
740 | void fimc_hw_dis_capture(struct fimc_dev *dev) | ||
741 | { | ||
742 | u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT); | ||
743 | cfg &= ~(FIMC_REG_CIIMGCPT_IMGCPTEN | FIMC_REG_CIIMGCPT_IMGCPTEN_SC); | ||
744 | writel(cfg, dev->regs + FIMC_REG_CIIMGCPT); | ||
745 | } | ||
746 | |||
747 | /* Return an index to the buffer actually being written. */ | 745 | /* Return an index to the buffer actually being written. */ |
748 | s32 fimc_hw_get_frame_index(struct fimc_dev *dev) | 746 | s32 fimc_hw_get_frame_index(struct fimc_dev *dev) |
749 | { | 747 | { |
@@ -776,13 +774,13 @@ s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev) | |||
776 | void fimc_activate_capture(struct fimc_ctx *ctx) | 774 | void fimc_activate_capture(struct fimc_ctx *ctx) |
777 | { | 775 | { |
778 | fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled); | 776 | fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled); |
779 | fimc_hw_en_capture(ctx); | 777 | fimc_hw_enable_capture(ctx); |
780 | } | 778 | } |
781 | 779 | ||
782 | void fimc_deactivate_capture(struct fimc_dev *fimc) | 780 | void fimc_deactivate_capture(struct fimc_dev *fimc) |
783 | { | 781 | { |
784 | fimc_hw_en_lastirq(fimc, true); | 782 | fimc_hw_en_lastirq(fimc, true); |
785 | fimc_hw_dis_capture(fimc); | 783 | fimc_hw_disable_capture(fimc); |
786 | fimc_hw_enable_scaler(fimc, false); | 784 | fimc_hw_enable_scaler(fimc, false); |
787 | fimc_hw_en_lastirq(fimc, false); | 785 | fimc_hw_en_lastirq(fimc, false); |
788 | } | 786 | } |
diff --git a/drivers/media/platform/s5p-fimc/fimc-reg.h b/drivers/media/platform/s5p-fimc/fimc-reg.h index b6abfc7b72ac..1a40df6d1a80 100644 --- a/drivers/media/platform/s5p-fimc/fimc-reg.h +++ b/drivers/media/platform/s5p-fimc/fimc-reg.h | |||
@@ -287,7 +287,7 @@ void fimc_hw_en_lastirq(struct fimc_dev *fimc, int enable); | |||
287 | void fimc_hw_en_irq(struct fimc_dev *fimc, int enable); | 287 | void fimc_hw_en_irq(struct fimc_dev *fimc, int enable); |
288 | void fimc_hw_set_prescaler(struct fimc_ctx *ctx); | 288 | void fimc_hw_set_prescaler(struct fimc_ctx *ctx); |
289 | void fimc_hw_set_mainscaler(struct fimc_ctx *ctx); | 289 | void fimc_hw_set_mainscaler(struct fimc_ctx *ctx); |
290 | void fimc_hw_en_capture(struct fimc_ctx *ctx); | 290 | void fimc_hw_enable_capture(struct fimc_ctx *ctx); |
291 | void fimc_hw_set_effect(struct fimc_ctx *ctx); | 291 | void fimc_hw_set_effect(struct fimc_ctx *ctx); |
292 | void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx); | 292 | void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx); |
293 | void fimc_hw_set_in_dma(struct fimc_ctx *ctx); | 293 | void fimc_hw_set_in_dma(struct fimc_ctx *ctx); |
@@ -297,16 +297,16 @@ void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr); | |||
297 | void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr, | 297 | void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr, |
298 | int index); | 298 | int index); |
299 | int fimc_hw_set_camera_source(struct fimc_dev *fimc, | 299 | int fimc_hw_set_camera_source(struct fimc_dev *fimc, |
300 | struct s5p_fimc_isp_info *cam); | 300 | struct fimc_source_info *cam); |
301 | void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f); | 301 | void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f); |
302 | int fimc_hw_set_camera_polarity(struct fimc_dev *fimc, | 302 | int fimc_hw_set_camera_polarity(struct fimc_dev *fimc, |
303 | struct s5p_fimc_isp_info *cam); | 303 | struct fimc_source_info *cam); |
304 | int fimc_hw_set_camera_type(struct fimc_dev *fimc, | 304 | int fimc_hw_set_camera_type(struct fimc_dev *fimc, |
305 | struct s5p_fimc_isp_info *cam); | 305 | struct fimc_source_info *cam); |
306 | void fimc_hw_clear_irq(struct fimc_dev *dev); | 306 | void fimc_hw_clear_irq(struct fimc_dev *dev); |
307 | void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on); | 307 | void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on); |
308 | void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on); | 308 | void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on); |
309 | void fimc_hw_dis_capture(struct fimc_dev *dev); | 309 | void fimc_hw_disable_capture(struct fimc_dev *dev); |
310 | s32 fimc_hw_get_frame_index(struct fimc_dev *dev); | 310 | s32 fimc_hw_get_frame_index(struct fimc_dev *dev); |
311 | s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev); | 311 | s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev); |
312 | void fimc_activate_capture(struct fimc_ctx *ctx); | 312 | void fimc_activate_capture(struct fimc_ctx *ctx); |
diff --git a/drivers/media/platform/s5p-fimc/mipi-csis.c b/drivers/media/platform/s5p-fimc/mipi-csis.c index 7abae012f55e..981863d05aaa 100644 --- a/drivers/media/platform/s5p-fimc/mipi-csis.c +++ b/drivers/media/platform/s5p-fimc/mipi-csis.c | |||
@@ -187,7 +187,7 @@ struct csis_state { | |||
187 | const struct csis_pix_format *csis_fmt; | 187 | const struct csis_pix_format *csis_fmt; |
188 | struct v4l2_mbus_framefmt format; | 188 | struct v4l2_mbus_framefmt format; |
189 | 189 | ||
190 | struct spinlock slock; | 190 | spinlock_t slock; |
191 | struct csis_pktbuf pkt_buf; | 191 | struct csis_pktbuf pkt_buf; |
192 | struct s5pcsis_event events[S5PCSIS_NUM_EVENTS]; | 192 | struct s5pcsis_event events[S5PCSIS_NUM_EVENTS]; |
193 | }; | 193 | }; |
@@ -220,6 +220,18 @@ static const struct csis_pix_format s5pcsis_formats[] = { | |||
220 | .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8, | 220 | .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8, |
221 | .fmt_reg = S5PCSIS_CFG_FMT_USER(1), | 221 | .fmt_reg = S5PCSIS_CFG_FMT_USER(1), |
222 | .data_alignment = 32, | 222 | .data_alignment = 32, |
223 | }, { | ||
224 | .code = V4L2_MBUS_FMT_SGRBG8_1X8, | ||
225 | .fmt_reg = S5PCSIS_CFG_FMT_RAW8, | ||
226 | .data_alignment = 24, | ||
227 | }, { | ||
228 | .code = V4L2_MBUS_FMT_SGRBG10_1X10, | ||
229 | .fmt_reg = S5PCSIS_CFG_FMT_RAW10, | ||
230 | .data_alignment = 24, | ||
231 | }, { | ||
232 | .code = V4L2_MBUS_FMT_SGRBG12_1X12, | ||
233 | .fmt_reg = S5PCSIS_CFG_FMT_RAW12, | ||
234 | .data_alignment = 24, | ||
223 | } | 235 | } |
224 | }; | 236 | }; |
225 | 237 | ||
@@ -261,7 +273,8 @@ static void s5pcsis_reset(struct csis_state *state) | |||
261 | 273 | ||
262 | static void s5pcsis_system_enable(struct csis_state *state, int on) | 274 | static void s5pcsis_system_enable(struct csis_state *state, int on) |
263 | { | 275 | { |
264 | u32 val; | 276 | struct s5p_platform_mipi_csis *pdata = state->pdev->dev.platform_data; |
277 | u32 val, mask; | ||
265 | 278 | ||
266 | val = s5pcsis_read(state, S5PCSIS_CTRL); | 279 | val = s5pcsis_read(state, S5PCSIS_CTRL); |
267 | if (on) | 280 | if (on) |
@@ -271,10 +284,11 @@ static void s5pcsis_system_enable(struct csis_state *state, int on) | |||
271 | s5pcsis_write(state, S5PCSIS_CTRL, val); | 284 | s5pcsis_write(state, S5PCSIS_CTRL, val); |
272 | 285 | ||
273 | val = s5pcsis_read(state, S5PCSIS_DPHYCTRL); | 286 | val = s5pcsis_read(state, S5PCSIS_DPHYCTRL); |
274 | if (on) | 287 | val &= ~S5PCSIS_DPHYCTRL_ENABLE; |
275 | val |= S5PCSIS_DPHYCTRL_ENABLE; | 288 | if (on) { |
276 | else | 289 | mask = (1 << (pdata->lanes + 1)) - 1; |
277 | val &= ~S5PCSIS_DPHYCTRL_ENABLE; | 290 | val |= (mask & S5PCSIS_DPHYCTRL_ENABLE); |
291 | } | ||
278 | s5pcsis_write(state, S5PCSIS_DPHYCTRL, val); | 292 | s5pcsis_write(state, S5PCSIS_DPHYCTRL, val); |
279 | } | 293 | } |
280 | 294 | ||
@@ -338,11 +352,11 @@ static void s5pcsis_clk_put(struct csis_state *state) | |||
338 | int i; | 352 | int i; |
339 | 353 | ||
340 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) { | 354 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) { |
341 | if (IS_ERR_OR_NULL(state->clock[i])) | 355 | if (IS_ERR(state->clock[i])) |
342 | continue; | 356 | continue; |
343 | clk_unprepare(state->clock[i]); | 357 | clk_unprepare(state->clock[i]); |
344 | clk_put(state->clock[i]); | 358 | clk_put(state->clock[i]); |
345 | state->clock[i] = NULL; | 359 | state->clock[i] = ERR_PTR(-EINVAL); |
346 | } | 360 | } |
347 | } | 361 | } |
348 | 362 | ||
@@ -351,14 +365,19 @@ static int s5pcsis_clk_get(struct csis_state *state) | |||
351 | struct device *dev = &state->pdev->dev; | 365 | struct device *dev = &state->pdev->dev; |
352 | int i, ret; | 366 | int i, ret; |
353 | 367 | ||
368 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) | ||
369 | state->clock[i] = ERR_PTR(-EINVAL); | ||
370 | |||
354 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) { | 371 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) { |
355 | state->clock[i] = clk_get(dev, csi_clock_name[i]); | 372 | state->clock[i] = clk_get(dev, csi_clock_name[i]); |
356 | if (IS_ERR(state->clock[i])) | 373 | if (IS_ERR(state->clock[i])) { |
374 | ret = PTR_ERR(state->clock[i]); | ||
357 | goto err; | 375 | goto err; |
376 | } | ||
358 | ret = clk_prepare(state->clock[i]); | 377 | ret = clk_prepare(state->clock[i]); |
359 | if (ret < 0) { | 378 | if (ret < 0) { |
360 | clk_put(state->clock[i]); | 379 | clk_put(state->clock[i]); |
361 | state->clock[i] = NULL; | 380 | state->clock[i] = ERR_PTR(-EINVAL); |
362 | goto err; | 381 | goto err; |
363 | } | 382 | } |
364 | } | 383 | } |
@@ -366,7 +385,31 @@ static int s5pcsis_clk_get(struct csis_state *state) | |||
366 | err: | 385 | err: |
367 | s5pcsis_clk_put(state); | 386 | s5pcsis_clk_put(state); |
368 | dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]); | 387 | dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]); |
369 | return -ENXIO; | 388 | return ret; |
389 | } | ||
390 | |||
391 | static void dump_regs(struct csis_state *state, const char *label) | ||
392 | { | ||
393 | struct { | ||
394 | u32 offset; | ||
395 | const char * const name; | ||
396 | } registers[] = { | ||
397 | { 0x00, "CTRL" }, | ||
398 | { 0x04, "DPHYCTRL" }, | ||
399 | { 0x08, "CONFIG" }, | ||
400 | { 0x0c, "DPHYSTS" }, | ||
401 | { 0x10, "INTMSK" }, | ||
402 | { 0x2c, "RESOL" }, | ||
403 | { 0x38, "SDW_CONFIG" }, | ||
404 | }; | ||
405 | u32 i; | ||
406 | |||
407 | v4l2_info(&state->sd, "--- %s ---\n", label); | ||
408 | |||
409 | for (i = 0; i < ARRAY_SIZE(registers); i++) { | ||
410 | u32 cfg = s5pcsis_read(state, registers[i].offset); | ||
411 | v4l2_info(&state->sd, "%10s: 0x%08x\n", registers[i].name, cfg); | ||
412 | } | ||
370 | } | 413 | } |
371 | 414 | ||
372 | static void s5pcsis_start_stream(struct csis_state *state) | 415 | static void s5pcsis_start_stream(struct csis_state *state) |
@@ -401,12 +444,12 @@ static void s5pcsis_log_counters(struct csis_state *state, bool non_errors) | |||
401 | 444 | ||
402 | spin_lock_irqsave(&state->slock, flags); | 445 | spin_lock_irqsave(&state->slock, flags); |
403 | 446 | ||
404 | for (i--; i >= 0; i--) | 447 | for (i--; i >= 0; i--) { |
405 | if (state->events[i].counter >= 0) | 448 | if (state->events[i].counter > 0 || debug) |
406 | v4l2_info(&state->sd, "%s events: %d\n", | 449 | v4l2_info(&state->sd, "%s events: %d\n", |
407 | state->events[i].name, | 450 | state->events[i].name, |
408 | state->events[i].counter); | 451 | state->events[i].counter); |
409 | 452 | } | |
410 | spin_unlock_irqrestore(&state->slock, flags); | 453 | spin_unlock_irqrestore(&state->slock, flags); |
411 | } | 454 | } |
412 | 455 | ||
@@ -569,7 +612,11 @@ static int s5pcsis_log_status(struct v4l2_subdev *sd) | |||
569 | { | 612 | { |
570 | struct csis_state *state = sd_to_csis_state(sd); | 613 | struct csis_state *state = sd_to_csis_state(sd); |
571 | 614 | ||
615 | mutex_lock(&state->lock); | ||
572 | s5pcsis_log_counters(state, true); | 616 | s5pcsis_log_counters(state, true); |
617 | if (debug && (state->flags & ST_POWERED)) | ||
618 | dump_regs(state, __func__); | ||
619 | mutex_unlock(&state->lock); | ||
573 | return 0; | 620 | return 0; |
574 | } | 621 | } |
575 | 622 | ||
@@ -699,26 +746,32 @@ static int s5pcsis_probe(struct platform_device *pdev) | |||
699 | for (i = 0; i < CSIS_NUM_SUPPLIES; i++) | 746 | for (i = 0; i < CSIS_NUM_SUPPLIES; i++) |
700 | state->supplies[i].supply = csis_supply_name[i]; | 747 | state->supplies[i].supply = csis_supply_name[i]; |
701 | 748 | ||
702 | ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, | 749 | ret = devm_regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, |
703 | state->supplies); | 750 | state->supplies); |
704 | if (ret) | 751 | if (ret) |
705 | return ret; | 752 | return ret; |
706 | 753 | ||
707 | ret = s5pcsis_clk_get(state); | 754 | ret = s5pcsis_clk_get(state); |
708 | if (ret) | 755 | if (ret < 0) |
709 | goto e_clkput; | 756 | return ret; |
710 | 757 | ||
711 | clk_enable(state->clock[CSIS_CLK_MUX]); | ||
712 | if (pdata->clk_rate) | 758 | if (pdata->clk_rate) |
713 | clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); | 759 | ret = clk_set_rate(state->clock[CSIS_CLK_MUX], |
760 | pdata->clk_rate); | ||
714 | else | 761 | else |
715 | dev_WARN(&pdev->dev, "No clock frequency specified!\n"); | 762 | dev_WARN(&pdev->dev, "No clock frequency specified!\n"); |
763 | if (ret < 0) | ||
764 | goto e_clkput; | ||
765 | |||
766 | ret = clk_enable(state->clock[CSIS_CLK_MUX]); | ||
767 | if (ret < 0) | ||
768 | goto e_clkput; | ||
716 | 769 | ||
717 | ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler, | 770 | ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler, |
718 | 0, dev_name(&pdev->dev), state); | 771 | 0, dev_name(&pdev->dev), state); |
719 | if (ret) { | 772 | if (ret) { |
720 | dev_err(&pdev->dev, "Interrupt request failed\n"); | 773 | dev_err(&pdev->dev, "Interrupt request failed\n"); |
721 | goto e_regput; | 774 | goto e_clkdis; |
722 | } | 775 | } |
723 | 776 | ||
724 | v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops); | 777 | v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops); |
@@ -736,7 +789,7 @@ static int s5pcsis_probe(struct platform_device *pdev) | |||
736 | ret = media_entity_init(&state->sd.entity, | 789 | ret = media_entity_init(&state->sd.entity, |
737 | CSIS_PADS_NUM, state->pads, 0); | 790 | CSIS_PADS_NUM, state->pads, 0); |
738 | if (ret < 0) | 791 | if (ret < 0) |
739 | goto e_clkput; | 792 | goto e_clkdis; |
740 | 793 | ||
741 | /* This allows to retrieve the platform device id by the host driver */ | 794 | /* This allows to retrieve the platform device id by the host driver */ |
742 | v4l2_set_subdevdata(&state->sd, pdev); | 795 | v4l2_set_subdevdata(&state->sd, pdev); |
@@ -749,10 +802,9 @@ static int s5pcsis_probe(struct platform_device *pdev) | |||
749 | pm_runtime_enable(&pdev->dev); | 802 | pm_runtime_enable(&pdev->dev); |
750 | return 0; | 803 | return 0; |
751 | 804 | ||
752 | e_regput: | 805 | e_clkdis: |
753 | regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); | ||
754 | e_clkput: | ||
755 | clk_disable(state->clock[CSIS_CLK_MUX]); | 806 | clk_disable(state->clock[CSIS_CLK_MUX]); |
807 | e_clkput: | ||
756 | s5pcsis_clk_put(state); | 808 | s5pcsis_clk_put(state); |
757 | return ret; | 809 | return ret; |
758 | } | 810 | } |
@@ -859,7 +911,6 @@ static int s5pcsis_remove(struct platform_device *pdev) | |||
859 | clk_disable(state->clock[CSIS_CLK_MUX]); | 911 | clk_disable(state->clock[CSIS_CLK_MUX]); |
860 | pm_runtime_set_suspended(&pdev->dev); | 912 | pm_runtime_set_suspended(&pdev->dev); |
861 | s5pcsis_clk_put(state); | 913 | s5pcsis_clk_put(state); |
862 | regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); | ||
863 | 914 | ||
864 | media_entity_cleanup(&state->sd.entity); | 915 | media_entity_cleanup(&state->sd.entity); |
865 | 916 | ||
diff --git a/drivers/media/platform/s5p-g2d/g2d-hw.c b/drivers/media/platform/s5p-g2d/g2d-hw.c index 5b86cbe408e2..e87bd93811d4 100644 --- a/drivers/media/platform/s5p-g2d/g2d-hw.c +++ b/drivers/media/platform/s5p-g2d/g2d-hw.c | |||
@@ -28,6 +28,7 @@ void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f) | |||
28 | { | 28 | { |
29 | u32 n; | 29 | u32 n; |
30 | 30 | ||
31 | w(0, SRC_SELECT_REG); | ||
31 | w(f->stride & 0xFFFF, SRC_STRIDE_REG); | 32 | w(f->stride & 0xFFFF, SRC_STRIDE_REG); |
32 | 33 | ||
33 | n = f->o_height & 0xFFF; | 34 | n = f->o_height & 0xFFF; |
@@ -52,6 +53,7 @@ void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f) | |||
52 | { | 53 | { |
53 | u32 n; | 54 | u32 n; |
54 | 55 | ||
56 | w(0, DST_SELECT_REG); | ||
55 | w(f->stride & 0xFFFF, DST_STRIDE_REG); | 57 | w(f->stride & 0xFFFF, DST_STRIDE_REG); |
56 | 58 | ||
57 | n = f->o_height & 0xFFF; | 59 | n = f->o_height & 0xFFF; |
@@ -82,10 +84,14 @@ void g2d_set_flip(struct g2d_dev *d, u32 r) | |||
82 | w(r, SRC_MSK_DIRECT_REG); | 84 | w(r, SRC_MSK_DIRECT_REG); |
83 | } | 85 | } |
84 | 86 | ||
85 | u32 g2d_cmd_stretch(u32 e) | 87 | void g2d_set_v41_stretch(struct g2d_dev *d, struct g2d_frame *src, |
88 | struct g2d_frame *dst) | ||
86 | { | 89 | { |
87 | e &= 1; | 90 | w(DEFAULT_SCALE_MODE, SRC_SCALE_CTRL_REG); |
88 | return e << 4; | 91 | |
92 | /* inversed scaling factor: src is numerator */ | ||
93 | w((src->c_width << 16) / dst->c_width, SRC_XSCALE_REG); | ||
94 | w((src->c_height << 16) / dst->c_height, SRC_YSCALE_REG); | ||
89 | } | 95 | } |
90 | 96 | ||
91 | void g2d_set_cmd(struct g2d_dev *d, u32 c) | 97 | void g2d_set_cmd(struct g2d_dev *d, u32 c) |
@@ -96,7 +102,9 @@ void g2d_set_cmd(struct g2d_dev *d, u32 c) | |||
96 | void g2d_start(struct g2d_dev *d) | 102 | void g2d_start(struct g2d_dev *d) |
97 | { | 103 | { |
98 | /* Clear cache */ | 104 | /* Clear cache */ |
99 | w(0x7, CACHECTL_REG); | 105 | if (d->variant->hw_rev == TYPE_G2D_3X) |
106 | w(0x7, CACHECTL_REG); | ||
107 | |||
100 | /* Enable interrupt */ | 108 | /* Enable interrupt */ |
101 | w(1, INTEN_REG); | 109 | w(1, INTEN_REG); |
102 | /* Start G2D engine */ | 110 | /* Start G2D engine */ |
diff --git a/drivers/media/platform/s5p-g2d/g2d-regs.h b/drivers/media/platform/s5p-g2d/g2d-regs.h index 02e1cf50da4e..9bf31ad35d47 100644 --- a/drivers/media/platform/s5p-g2d/g2d-regs.h +++ b/drivers/media/platform/s5p-g2d/g2d-regs.h | |||
@@ -35,6 +35,9 @@ | |||
35 | #define SRC_COLOR_MODE_REG 0x030C /* Src Image Color Mode reg */ | 35 | #define SRC_COLOR_MODE_REG 0x030C /* Src Image Color Mode reg */ |
36 | #define SRC_LEFT_TOP_REG 0x0310 /* Src Left Top Coordinate reg */ | 36 | #define SRC_LEFT_TOP_REG 0x0310 /* Src Left Top Coordinate reg */ |
37 | #define SRC_RIGHT_BOTTOM_REG 0x0314 /* Src Right Bottom Coordinate reg */ | 37 | #define SRC_RIGHT_BOTTOM_REG 0x0314 /* Src Right Bottom Coordinate reg */ |
38 | #define SRC_SCALE_CTRL_REG 0x0328 /* Src Scaling type select */ | ||
39 | #define SRC_XSCALE_REG 0x032c /* Src X Scaling ratio */ | ||
40 | #define SRC_YSCALE_REG 0x0330 /* Src Y Scaling ratio */ | ||
38 | 41 | ||
39 | /* Parameter Setting Registers (Dest) */ | 42 | /* Parameter Setting Registers (Dest) */ |
40 | #define DST_SELECT_REG 0x0400 /* Dest Image Selection reg */ | 43 | #define DST_SELECT_REG 0x0400 /* Dest Image Selection reg */ |
@@ -113,3 +116,7 @@ | |||
113 | #define DEFAULT_WIDTH 100 | 116 | #define DEFAULT_WIDTH 100 |
114 | #define DEFAULT_HEIGHT 100 | 117 | #define DEFAULT_HEIGHT 100 |
115 | 118 | ||
119 | #define DEFAULT_SCALE_MODE (2 << 0) | ||
120 | |||
121 | /* Command mode register values */ | ||
122 | #define CMD_V3_ENABLE_STRETCH (1 << 4) | ||
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 6ed259fb1046..aaaf276a5a6c 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c | |||
@@ -604,8 +604,13 @@ static void device_run(void *prv) | |||
604 | g2d_set_flip(dev, ctx->flip); | 604 | g2d_set_flip(dev, ctx->flip); |
605 | 605 | ||
606 | if (ctx->in.c_width != ctx->out.c_width || | 606 | if (ctx->in.c_width != ctx->out.c_width || |
607 | ctx->in.c_height != ctx->out.c_height) | 607 | ctx->in.c_height != ctx->out.c_height) { |
608 | cmd |= g2d_cmd_stretch(1); | 608 | if (dev->variant->hw_rev == TYPE_G2D_3X) |
609 | cmd |= CMD_V3_ENABLE_STRETCH; | ||
610 | else | ||
611 | g2d_set_v41_stretch(dev, &ctx->in, &ctx->out); | ||
612 | } | ||
613 | |||
609 | g2d_set_cmd(dev, cmd); | 614 | g2d_set_cmd(dev, cmd); |
610 | g2d_start(dev); | 615 | g2d_start(dev); |
611 | 616 | ||
@@ -713,7 +718,7 @@ static int g2d_probe(struct platform_device *pdev) | |||
713 | return PTR_ERR(dev->regs); | 718 | return PTR_ERR(dev->regs); |
714 | 719 | ||
715 | dev->clk = clk_get(&pdev->dev, "sclk_fimg2d"); | 720 | dev->clk = clk_get(&pdev->dev, "sclk_fimg2d"); |
716 | if (IS_ERR_OR_NULL(dev->clk)) { | 721 | if (IS_ERR(dev->clk)) { |
717 | dev_err(&pdev->dev, "failed to get g2d clock\n"); | 722 | dev_err(&pdev->dev, "failed to get g2d clock\n"); |
718 | return -ENXIO; | 723 | return -ENXIO; |
719 | } | 724 | } |
@@ -725,7 +730,7 @@ static int g2d_probe(struct platform_device *pdev) | |||
725 | } | 730 | } |
726 | 731 | ||
727 | dev->gate = clk_get(&pdev->dev, "fimg2d"); | 732 | dev->gate = clk_get(&pdev->dev, "fimg2d"); |
728 | if (IS_ERR_OR_NULL(dev->gate)) { | 733 | if (IS_ERR(dev->gate)) { |
729 | dev_err(&pdev->dev, "failed to get g2d clock gate\n"); | 734 | dev_err(&pdev->dev, "failed to get g2d clock gate\n"); |
730 | ret = -ENXIO; | 735 | ret = -ENXIO; |
731 | goto unprep_clk; | 736 | goto unprep_clk; |
@@ -789,6 +794,7 @@ static int g2d_probe(struct platform_device *pdev) | |||
789 | } | 794 | } |
790 | 795 | ||
791 | def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; | 796 | def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; |
797 | dev->variant = g2d_get_drv_data(pdev); | ||
792 | 798 | ||
793 | return 0; | 799 | return 0; |
794 | 800 | ||
@@ -828,9 +834,30 @@ static int g2d_remove(struct platform_device *pdev) | |||
828 | return 0; | 834 | return 0; |
829 | } | 835 | } |
830 | 836 | ||
837 | static struct g2d_variant g2d_drvdata_v3x = { | ||
838 | .hw_rev = TYPE_G2D_3X, | ||
839 | }; | ||
840 | |||
841 | static struct g2d_variant g2d_drvdata_v4x = { | ||
842 | .hw_rev = TYPE_G2D_4X, /* Revision 4.1 for Exynos4X12 and Exynos5 */ | ||
843 | }; | ||
844 | |||
845 | static struct platform_device_id g2d_driver_ids[] = { | ||
846 | { | ||
847 | .name = "s5p-g2d", | ||
848 | .driver_data = (unsigned long)&g2d_drvdata_v3x, | ||
849 | }, { | ||
850 | .name = "s5p-g2d-v4x", | ||
851 | .driver_data = (unsigned long)&g2d_drvdata_v4x, | ||
852 | }, | ||
853 | {}, | ||
854 | }; | ||
855 | MODULE_DEVICE_TABLE(platform, g2d_driver_ids); | ||
856 | |||
831 | static struct platform_driver g2d_pdrv = { | 857 | static struct platform_driver g2d_pdrv = { |
832 | .probe = g2d_probe, | 858 | .probe = g2d_probe, |
833 | .remove = g2d_remove, | 859 | .remove = g2d_remove, |
860 | .id_table = g2d_driver_ids, | ||
834 | .driver = { | 861 | .driver = { |
835 | .name = G2D_NAME, | 862 | .name = G2D_NAME, |
836 | .owner = THIS_MODULE, | 863 | .owner = THIS_MODULE, |
diff --git a/drivers/media/platform/s5p-g2d/g2d.h b/drivers/media/platform/s5p-g2d/g2d.h index 6b765b0216c5..300ca05ba404 100644 --- a/drivers/media/platform/s5p-g2d/g2d.h +++ b/drivers/media/platform/s5p-g2d/g2d.h | |||
@@ -10,10 +10,13 @@ | |||
10 | * License, or (at your option) any later version | 10 | * License, or (at your option) any later version |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/platform_device.h> | ||
13 | #include <media/v4l2-device.h> | 14 | #include <media/v4l2-device.h> |
14 | #include <media/v4l2-ctrls.h> | 15 | #include <media/v4l2-ctrls.h> |
15 | 16 | ||
16 | #define G2D_NAME "s5p-g2d" | 17 | #define G2D_NAME "s5p-g2d" |
18 | #define TYPE_G2D_3X 3 | ||
19 | #define TYPE_G2D_4X 4 | ||
17 | 20 | ||
18 | struct g2d_dev { | 21 | struct g2d_dev { |
19 | struct v4l2_device v4l2_dev; | 22 | struct v4l2_device v4l2_dev; |
@@ -27,6 +30,7 @@ struct g2d_dev { | |||
27 | struct clk *clk; | 30 | struct clk *clk; |
28 | struct clk *gate; | 31 | struct clk *gate; |
29 | struct g2d_ctx *curr; | 32 | struct g2d_ctx *curr; |
33 | struct g2d_variant *variant; | ||
30 | int irq; | 34 | int irq; |
31 | wait_queue_head_t irq_queue; | 35 | wait_queue_head_t irq_queue; |
32 | }; | 36 | }; |
@@ -53,7 +57,7 @@ struct g2d_frame { | |||
53 | struct g2d_ctx { | 57 | struct g2d_ctx { |
54 | struct v4l2_fh fh; | 58 | struct v4l2_fh fh; |
55 | struct g2d_dev *dev; | 59 | struct g2d_dev *dev; |
56 | struct v4l2_m2m_ctx *m2m_ctx; | 60 | struct v4l2_m2m_ctx *m2m_ctx; |
57 | struct g2d_frame in; | 61 | struct g2d_frame in; |
58 | struct g2d_frame out; | 62 | struct g2d_frame out; |
59 | struct v4l2_ctrl *ctrl_hflip; | 63 | struct v4l2_ctrl *ctrl_hflip; |
@@ -70,6 +74,9 @@ struct g2d_fmt { | |||
70 | u32 hw; | 74 | u32 hw; |
71 | }; | 75 | }; |
72 | 76 | ||
77 | struct g2d_variant { | ||
78 | unsigned short hw_rev; | ||
79 | }; | ||
73 | 80 | ||
74 | void g2d_reset(struct g2d_dev *d); | 81 | void g2d_reset(struct g2d_dev *d); |
75 | void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f); | 82 | void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f); |
@@ -80,7 +87,11 @@ void g2d_start(struct g2d_dev *d); | |||
80 | void g2d_clear_int(struct g2d_dev *d); | 87 | void g2d_clear_int(struct g2d_dev *d); |
81 | void g2d_set_rop4(struct g2d_dev *d, u32 r); | 88 | void g2d_set_rop4(struct g2d_dev *d, u32 r); |
82 | void g2d_set_flip(struct g2d_dev *d, u32 r); | 89 | void g2d_set_flip(struct g2d_dev *d, u32 r); |
83 | u32 g2d_cmd_stretch(u32 e); | 90 | void g2d_set_v41_stretch(struct g2d_dev *d, |
91 | struct g2d_frame *src, struct g2d_frame *dst); | ||
84 | void g2d_set_cmd(struct g2d_dev *d, u32 c); | 92 | void g2d_set_cmd(struct g2d_dev *d, u32 c); |
85 | 93 | ||
86 | 94 | static inline struct g2d_variant *g2d_get_drv_data(struct platform_device *pdev) | |
95 | { | ||
96 | return (struct g2d_variant *)platform_get_device_id(pdev)->driver_data; | ||
97 | } | ||
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h index 022b9b9baff9..8a4013e3aee7 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.h | |||
@@ -62,7 +62,7 @@ | |||
62 | */ | 62 | */ |
63 | struct s5p_jpeg { | 63 | struct s5p_jpeg { |
64 | struct mutex lock; | 64 | struct mutex lock; |
65 | struct spinlock slock; | 65 | spinlock_t slock; |
66 | 66 | ||
67 | struct v4l2_device v4l2_dev; | 67 | struct v4l2_device v4l2_dev; |
68 | struct video_device *vfd_encoder; | 68 | struct video_device *vfd_encoder; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 8b7fbc7cc04d..e84703c314ce 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/videodev2.h> | 21 | #include <linux/videodev2.h> |
22 | #include <media/v4l2-event.h> | 22 | #include <media/v4l2-event.h> |
23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
24 | #include <linux/of.h> | ||
24 | #include <media/videobuf2-core.h> | 25 | #include <media/videobuf2-core.h> |
25 | #include "s5p_mfc_common.h" | 26 | #include "s5p_mfc_common.h" |
26 | #include "s5p_mfc_ctrl.h" | 27 | #include "s5p_mfc_ctrl.h" |
@@ -273,7 +274,6 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) | |||
273 | struct s5p_mfc_buf *dst_buf; | 274 | struct s5p_mfc_buf *dst_buf; |
274 | size_t dspl_y_addr; | 275 | size_t dspl_y_addr; |
275 | unsigned int frame_type; | 276 | unsigned int frame_type; |
276 | unsigned int index; | ||
277 | 277 | ||
278 | dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev); | 278 | dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev); |
279 | frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); | 279 | frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); |
@@ -310,7 +310,6 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) | |||
310 | vb2_buffer_done(dst_buf->b, | 310 | vb2_buffer_done(dst_buf->b, |
311 | err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); | 311 | err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); |
312 | 312 | ||
313 | index = dst_buf->b->v4l2_buf.index; | ||
314 | break; | 313 | break; |
315 | } | 314 | } |
316 | } | 315 | } |
@@ -326,8 +325,6 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, | |||
326 | unsigned long flags; | 325 | unsigned long flags; |
327 | unsigned int res_change; | 326 | unsigned int res_change; |
328 | 327 | ||
329 | unsigned int index; | ||
330 | |||
331 | dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) | 328 | dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) |
332 | & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK; | 329 | & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK; |
333 | res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) | 330 | res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) |
@@ -387,7 +384,6 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, | |||
387 | mfc_debug(2, "Running again the same buffer\n"); | 384 | mfc_debug(2, "Running again the same buffer\n"); |
388 | ctx->after_packed_pb = 1; | 385 | ctx->after_packed_pb = 1; |
389 | } else { | 386 | } else { |
390 | index = src_buf->b->v4l2_buf.index; | ||
391 | mfc_debug(2, "MFC needs next buffer\n"); | 387 | mfc_debug(2, "MFC needs next buffer\n"); |
392 | ctx->consumed_stream = 0; | 388 | ctx->consumed_stream = 0; |
393 | list_del(&src_buf->list); | 389 | list_del(&src_buf->list); |
@@ -586,8 +582,7 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, | |||
586 | 582 | ||
587 | clear_work_bit(ctx); | 583 | clear_work_bit(ctx); |
588 | 584 | ||
589 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | 585 | WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); |
590 | WARN_ON(1); | ||
591 | 586 | ||
592 | s5p_mfc_clock_off(); | 587 | s5p_mfc_clock_off(); |
593 | wake_up(&ctx->queue); | 588 | wake_up(&ctx->queue); |
@@ -676,6 +671,12 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) | |||
676 | s5p_mfc_handle_stream_complete(ctx, reason, err); | 671 | s5p_mfc_handle_stream_complete(ctx, reason, err); |
677 | break; | 672 | break; |
678 | 673 | ||
674 | case S5P_MFC_R2H_CMD_DPB_FLUSH_RET: | ||
675 | clear_work_bit(ctx); | ||
676 | ctx->state = MFCINST_RUNNING; | ||
677 | wake_up(&ctx->queue); | ||
678 | goto irq_cleanup_hw; | ||
679 | |||
679 | default: | 680 | default: |
680 | mfc_debug(2, "Unknown int reason\n"); | 681 | mfc_debug(2, "Unknown int reason\n"); |
681 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); | 682 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
@@ -777,14 +778,16 @@ static int s5p_mfc_open(struct file *file) | |||
777 | goto err_pwr_enable; | 778 | goto err_pwr_enable; |
778 | } | 779 | } |
779 | s5p_mfc_clock_on(); | 780 | s5p_mfc_clock_on(); |
780 | ret = s5p_mfc_alloc_and_load_firmware(dev); | 781 | ret = s5p_mfc_load_firmware(dev); |
781 | if (ret) | 782 | if (ret) { |
782 | goto err_alloc_fw; | 783 | s5p_mfc_clock_off(); |
784 | goto err_load_fw; | ||
785 | } | ||
783 | /* Init the FW */ | 786 | /* Init the FW */ |
784 | ret = s5p_mfc_init_hw(dev); | 787 | ret = s5p_mfc_init_hw(dev); |
788 | s5p_mfc_clock_off(); | ||
785 | if (ret) | 789 | if (ret) |
786 | goto err_init_hw; | 790 | goto err_init_hw; |
787 | s5p_mfc_clock_off(); | ||
788 | } | 791 | } |
789 | /* Init videobuf2 queue for CAPTURE */ | 792 | /* Init videobuf2 queue for CAPTURE */ |
790 | q = &ctx->vq_dst; | 793 | q = &ctx->vq_dst; |
@@ -833,21 +836,20 @@ static int s5p_mfc_open(struct file *file) | |||
833 | return ret; | 836 | return ret; |
834 | /* Deinit when failure occured */ | 837 | /* Deinit when failure occured */ |
835 | err_queue_init: | 838 | err_queue_init: |
839 | if (dev->num_inst == 1) | ||
840 | s5p_mfc_deinit_hw(dev); | ||
836 | err_init_hw: | 841 | err_init_hw: |
837 | s5p_mfc_release_firmware(dev); | 842 | err_load_fw: |
838 | err_alloc_fw: | ||
839 | dev->ctx[ctx->num] = NULL; | ||
840 | del_timer_sync(&dev->watchdog_timer); | ||
841 | s5p_mfc_clock_off(); | ||
842 | err_pwr_enable: | 843 | err_pwr_enable: |
843 | if (dev->num_inst == 1) { | 844 | if (dev->num_inst == 1) { |
844 | if (s5p_mfc_power_off() < 0) | 845 | if (s5p_mfc_power_off() < 0) |
845 | mfc_err("power off failed\n"); | 846 | mfc_err("power off failed\n"); |
846 | s5p_mfc_release_firmware(dev); | 847 | del_timer_sync(&dev->watchdog_timer); |
847 | } | 848 | } |
848 | err_ctrls_setup: | 849 | err_ctrls_setup: |
849 | s5p_mfc_dec_ctrls_delete(ctx); | 850 | s5p_mfc_dec_ctrls_delete(ctx); |
850 | err_bad_node: | 851 | err_bad_node: |
852 | dev->ctx[ctx->num] = NULL; | ||
851 | err_no_ctx: | 853 | err_no_ctx: |
852 | v4l2_fh_del(&ctx->fh); | 854 | v4l2_fh_del(&ctx->fh); |
853 | v4l2_fh_exit(&ctx->fh); | 855 | v4l2_fh_exit(&ctx->fh); |
@@ -901,11 +903,8 @@ static int s5p_mfc_release(struct file *file) | |||
901 | clear_bit(0, &dev->hw_lock); | 903 | clear_bit(0, &dev->hw_lock); |
902 | dev->num_inst--; | 904 | dev->num_inst--; |
903 | if (dev->num_inst == 0) { | 905 | if (dev->num_inst == 0) { |
904 | mfc_debug(2, "Last instance - release firmware\n"); | 906 | mfc_debug(2, "Last instance\n"); |
905 | /* reset <-> F/W release */ | ||
906 | s5p_mfc_reset(dev); | ||
907 | s5p_mfc_deinit_hw(dev); | 907 | s5p_mfc_deinit_hw(dev); |
908 | s5p_mfc_release_firmware(dev); | ||
909 | del_timer_sync(&dev->watchdog_timer); | 908 | del_timer_sync(&dev->watchdog_timer); |
910 | if (s5p_mfc_power_off() < 0) | 909 | if (s5p_mfc_power_off() < 0) |
911 | mfc_err("Power off failed\n"); | 910 | mfc_err("Power off failed\n"); |
@@ -1013,6 +1012,48 @@ static int match_child(struct device *dev, void *data) | |||
1013 | return !strcmp(dev_name(dev), (char *)data); | 1012 | return !strcmp(dev_name(dev), (char *)data); |
1014 | } | 1013 | } |
1015 | 1014 | ||
1015 | static void *mfc_get_drv_data(struct platform_device *pdev); | ||
1016 | |||
1017 | static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev) | ||
1018 | { | ||
1019 | unsigned int mem_info[2]; | ||
1020 | |||
1021 | dev->mem_dev_l = devm_kzalloc(&dev->plat_dev->dev, | ||
1022 | sizeof(struct device), GFP_KERNEL); | ||
1023 | if (!dev->mem_dev_l) { | ||
1024 | mfc_err("Not enough memory\n"); | ||
1025 | return -ENOMEM; | ||
1026 | } | ||
1027 | device_initialize(dev->mem_dev_l); | ||
1028 | of_property_read_u32_array(dev->plat_dev->dev.of_node, | ||
1029 | "samsung,mfc-l", mem_info, 2); | ||
1030 | if (dma_declare_coherent_memory(dev->mem_dev_l, mem_info[0], | ||
1031 | mem_info[0], mem_info[1], | ||
1032 | DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) { | ||
1033 | mfc_err("Failed to declare coherent memory for\n" | ||
1034 | "MFC device\n"); | ||
1035 | return -ENOMEM; | ||
1036 | } | ||
1037 | |||
1038 | dev->mem_dev_r = devm_kzalloc(&dev->plat_dev->dev, | ||
1039 | sizeof(struct device), GFP_KERNEL); | ||
1040 | if (!dev->mem_dev_r) { | ||
1041 | mfc_err("Not enough memory\n"); | ||
1042 | return -ENOMEM; | ||
1043 | } | ||
1044 | device_initialize(dev->mem_dev_r); | ||
1045 | of_property_read_u32_array(dev->plat_dev->dev.of_node, | ||
1046 | "samsung,mfc-r", mem_info, 2); | ||
1047 | if (dma_declare_coherent_memory(dev->mem_dev_r, mem_info[0], | ||
1048 | mem_info[0], mem_info[1], | ||
1049 | DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) { | ||
1050 | pr_err("Failed to declare coherent memory for\n" | ||
1051 | "MFC device\n"); | ||
1052 | return -ENOMEM; | ||
1053 | } | ||
1054 | return 0; | ||
1055 | } | ||
1056 | |||
1016 | /* MFC probe function */ | 1057 | /* MFC probe function */ |
1017 | static int s5p_mfc_probe(struct platform_device *pdev) | 1058 | static int s5p_mfc_probe(struct platform_device *pdev) |
1018 | { | 1059 | { |
@@ -1036,8 +1077,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1036 | return -ENODEV; | 1077 | return -ENODEV; |
1037 | } | 1078 | } |
1038 | 1079 | ||
1039 | dev->variant = (struct s5p_mfc_variant *) | 1080 | dev->variant = mfc_get_drv_data(pdev); |
1040 | platform_get_device_id(pdev)->driver_data; | ||
1041 | 1081 | ||
1042 | ret = s5p_mfc_init_pm(dev); | 1082 | ret = s5p_mfc_init_pm(dev); |
1043 | if (ret < 0) { | 1083 | if (ret < 0) { |
@@ -1065,35 +1105,43 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1065 | goto err_res; | 1105 | goto err_res; |
1066 | } | 1106 | } |
1067 | 1107 | ||
1068 | dev->mem_dev_l = device_find_child(&dev->plat_dev->dev, "s5p-mfc-l", | 1108 | if (pdev->dev.of_node) { |
1069 | match_child); | 1109 | if (s5p_mfc_alloc_memdevs(dev) < 0) |
1070 | if (!dev->mem_dev_l) { | 1110 | goto err_res; |
1071 | mfc_err("Mem child (L) device get failed\n"); | 1111 | } else { |
1072 | ret = -ENODEV; | 1112 | dev->mem_dev_l = device_find_child(&dev->plat_dev->dev, |
1073 | goto err_res; | 1113 | "s5p-mfc-l", match_child); |
1074 | } | 1114 | if (!dev->mem_dev_l) { |
1075 | 1115 | mfc_err("Mem child (L) device get failed\n"); | |
1076 | dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r", | 1116 | ret = -ENODEV; |
1077 | match_child); | 1117 | goto err_res; |
1078 | if (!dev->mem_dev_r) { | 1118 | } |
1079 | mfc_err("Mem child (R) device get failed\n"); | 1119 | dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, |
1080 | ret = -ENODEV; | 1120 | "s5p-mfc-r", match_child); |
1081 | goto err_res; | 1121 | if (!dev->mem_dev_r) { |
1122 | mfc_err("Mem child (R) device get failed\n"); | ||
1123 | ret = -ENODEV; | ||
1124 | goto err_res; | ||
1125 | } | ||
1082 | } | 1126 | } |
1083 | 1127 | ||
1084 | dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l); | 1128 | dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l); |
1085 | if (IS_ERR_OR_NULL(dev->alloc_ctx[0])) { | 1129 | if (IS_ERR(dev->alloc_ctx[0])) { |
1086 | ret = PTR_ERR(dev->alloc_ctx[0]); | 1130 | ret = PTR_ERR(dev->alloc_ctx[0]); |
1087 | goto err_res; | 1131 | goto err_res; |
1088 | } | 1132 | } |
1089 | dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r); | 1133 | dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r); |
1090 | if (IS_ERR_OR_NULL(dev->alloc_ctx[1])) { | 1134 | if (IS_ERR(dev->alloc_ctx[1])) { |
1091 | ret = PTR_ERR(dev->alloc_ctx[1]); | 1135 | ret = PTR_ERR(dev->alloc_ctx[1]); |
1092 | goto err_mem_init_ctx_1; | 1136 | goto err_mem_init_ctx_1; |
1093 | } | 1137 | } |
1094 | 1138 | ||
1095 | mutex_init(&dev->mfc_mutex); | 1139 | mutex_init(&dev->mfc_mutex); |
1096 | 1140 | ||
1141 | ret = s5p_mfc_alloc_firmware(dev); | ||
1142 | if (ret) | ||
1143 | goto err_alloc_fw; | ||
1144 | |||
1097 | ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); | 1145 | ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); |
1098 | if (ret) | 1146 | if (ret) |
1099 | goto err_v4l2_dev_reg; | 1147 | goto err_v4l2_dev_reg; |
@@ -1175,6 +1223,8 @@ err_dec_reg: | |||
1175 | err_dec_alloc: | 1223 | err_dec_alloc: |
1176 | v4l2_device_unregister(&dev->v4l2_dev); | 1224 | v4l2_device_unregister(&dev->v4l2_dev); |
1177 | err_v4l2_dev_reg: | 1225 | err_v4l2_dev_reg: |
1226 | s5p_mfc_release_firmware(dev); | ||
1227 | err_alloc_fw: | ||
1178 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); | 1228 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); |
1179 | err_mem_init_ctx_1: | 1229 | err_mem_init_ctx_1: |
1180 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); | 1230 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); |
@@ -1200,8 +1250,13 @@ static int s5p_mfc_remove(struct platform_device *pdev) | |||
1200 | video_unregister_device(dev->vfd_enc); | 1250 | video_unregister_device(dev->vfd_enc); |
1201 | video_unregister_device(dev->vfd_dec); | 1251 | video_unregister_device(dev->vfd_dec); |
1202 | v4l2_device_unregister(&dev->v4l2_dev); | 1252 | v4l2_device_unregister(&dev->v4l2_dev); |
1253 | s5p_mfc_release_firmware(dev); | ||
1203 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); | 1254 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); |
1204 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); | 1255 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); |
1256 | if (pdev->dev.of_node) { | ||
1257 | put_device(dev->mem_dev_l); | ||
1258 | put_device(dev->mem_dev_r); | ||
1259 | } | ||
1205 | 1260 | ||
1206 | s5p_mfc_final_pm(dev); | 1261 | s5p_mfc_final_pm(dev); |
1207 | return 0; | 1262 | return 0; |
@@ -1350,6 +1405,35 @@ static struct platform_device_id mfc_driver_ids[] = { | |||
1350 | }; | 1405 | }; |
1351 | MODULE_DEVICE_TABLE(platform, mfc_driver_ids); | 1406 | MODULE_DEVICE_TABLE(platform, mfc_driver_ids); |
1352 | 1407 | ||
1408 | static const struct of_device_id exynos_mfc_match[] = { | ||
1409 | { | ||
1410 | .compatible = "samsung,mfc-v5", | ||
1411 | .data = &mfc_drvdata_v5, | ||
1412 | }, { | ||
1413 | .compatible = "samsung,mfc-v6", | ||
1414 | .data = &mfc_drvdata_v6, | ||
1415 | }, | ||
1416 | {}, | ||
1417 | }; | ||
1418 | MODULE_DEVICE_TABLE(of, exynos_mfc_match); | ||
1419 | |||
1420 | static void *mfc_get_drv_data(struct platform_device *pdev) | ||
1421 | { | ||
1422 | struct s5p_mfc_variant *driver_data = NULL; | ||
1423 | |||
1424 | if (pdev->dev.of_node) { | ||
1425 | const struct of_device_id *match; | ||
1426 | match = of_match_node(of_match_ptr(exynos_mfc_match), | ||
1427 | pdev->dev.of_node); | ||
1428 | if (match) | ||
1429 | driver_data = (struct s5p_mfc_variant *)match->data; | ||
1430 | } else { | ||
1431 | driver_data = (struct s5p_mfc_variant *) | ||
1432 | platform_get_device_id(pdev)->driver_data; | ||
1433 | } | ||
1434 | return driver_data; | ||
1435 | } | ||
1436 | |||
1353 | static struct platform_driver s5p_mfc_driver = { | 1437 | static struct platform_driver s5p_mfc_driver = { |
1354 | .probe = s5p_mfc_probe, | 1438 | .probe = s5p_mfc_probe, |
1355 | .remove = s5p_mfc_remove, | 1439 | .remove = s5p_mfc_remove, |
@@ -1357,7 +1441,8 @@ static struct platform_driver s5p_mfc_driver = { | |||
1357 | .driver = { | 1441 | .driver = { |
1358 | .name = S5P_MFC_NAME, | 1442 | .name = S5P_MFC_NAME, |
1359 | .owner = THIS_MODULE, | 1443 | .owner = THIS_MODULE, |
1360 | .pm = &s5p_mfc_pm_ops | 1444 | .pm = &s5p_mfc_pm_ops, |
1445 | .of_match_table = exynos_mfc_match, | ||
1361 | }, | 1446 | }, |
1362 | }; | 1447 | }; |
1363 | 1448 | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index f02e0497ca98..202d1d7a37a8 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h | |||
@@ -145,6 +145,7 @@ enum s5p_mfc_inst_state { | |||
145 | MFCINST_RETURN_INST, | 145 | MFCINST_RETURN_INST, |
146 | MFCINST_ERROR, | 146 | MFCINST_ERROR, |
147 | MFCINST_ABORT, | 147 | MFCINST_ABORT, |
148 | MFCINST_FLUSH, | ||
148 | MFCINST_RES_CHANGE_INIT, | 149 | MFCINST_RES_CHANGE_INIT, |
149 | MFCINST_RES_CHANGE_FLUSH, | 150 | MFCINST_RES_CHANGE_FLUSH, |
150 | MFCINST_RES_CHANGE_END, | 151 | MFCINST_RES_CHANGE_END, |
@@ -277,8 +278,9 @@ struct s5p_mfc_priv_buf { | |||
277 | * @int_err: error number for last interrupt | 278 | * @int_err: error number for last interrupt |
278 | * @queue: waitqueue for waiting for completion of device commands | 279 | * @queue: waitqueue for waiting for completion of device commands |
279 | * @fw_size: size of firmware | 280 | * @fw_size: size of firmware |
280 | * @bank1: address of the beggining of bank 1 memory | 281 | * @fw_virt_addr: virtual firmware address |
281 | * @bank2: address of the beggining of bank 2 memory | 282 | * @bank1: address of the beginning of bank 1 memory |
283 | * @bank2: address of the beginning of bank 2 memory | ||
282 | * @hw_lock: used for hardware locking | 284 | * @hw_lock: used for hardware locking |
283 | * @ctx: array of driver contexts | 285 | * @ctx: array of driver contexts |
284 | * @curr_ctx: number of the currently running context | 286 | * @curr_ctx: number of the currently running context |
@@ -317,8 +319,9 @@ struct s5p_mfc_dev { | |||
317 | unsigned int int_err; | 319 | unsigned int int_err; |
318 | wait_queue_head_t queue; | 320 | wait_queue_head_t queue; |
319 | size_t fw_size; | 321 | size_t fw_size; |
320 | size_t bank1; | 322 | void *fw_virt_addr; |
321 | size_t bank2; | 323 | dma_addr_t bank1; |
324 | dma_addr_t bank2; | ||
322 | unsigned long hw_lock; | 325 | unsigned long hw_lock; |
323 | struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; | 326 | struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; |
324 | int curr_ctx; | 327 | int curr_ctx; |
@@ -493,15 +496,9 @@ struct s5p_mfc_codec_ops { | |||
493 | * flushed | 496 | * flushed |
494 | * @head_processed: flag mentioning whether the header data is processed | 497 | * @head_processed: flag mentioning whether the header data is processed |
495 | * completely or not | 498 | * completely or not |
496 | * @bank1_buf: handle to memory allocated for temporary buffers from | 499 | * @bank1: handle to memory allocated for temporary buffers from |
497 | * memory bank 1 | 500 | * memory bank 1 |
498 | * @bank1_phys: address of the temporary buffers from memory bank 1 | 501 | * @bank2: handle to memory allocated for temporary buffers from |
499 | * @bank1_size: size of the memory allocated for temporary buffers from | ||
500 | * memory bank 1 | ||
501 | * @bank2_buf: handle to memory allocated for temporary buffers from | ||
502 | * memory bank 2 | ||
503 | * @bank2_phys: address of the temporary buffers from memory bank 2 | ||
504 | * @bank2_size: size of the memory allocated for temporary buffers from | ||
505 | * memory bank 2 | 502 | * memory bank 2 |
506 | * @capture_state: state of the capture buffers queue | 503 | * @capture_state: state of the capture buffers queue |
507 | * @output_state: state of the output buffers queue | 504 | * @output_state: state of the output buffers queue |
@@ -581,14 +578,8 @@ struct s5p_mfc_ctx { | |||
581 | unsigned int dpb_flush_flag; | 578 | unsigned int dpb_flush_flag; |
582 | unsigned int head_processed; | 579 | unsigned int head_processed; |
583 | 580 | ||
584 | /* Buffers */ | 581 | struct s5p_mfc_priv_buf bank1; |
585 | void *bank1_buf; | 582 | struct s5p_mfc_priv_buf bank2; |
586 | size_t bank1_phys; | ||
587 | size_t bank1_size; | ||
588 | |||
589 | void *bank2_buf; | ||
590 | size_t bank2_phys; | ||
591 | size_t bank2_size; | ||
592 | 583 | ||
593 | enum s5p_mfc_queue_state capture_state; | 584 | enum s5p_mfc_queue_state capture_state; |
594 | enum s5p_mfc_queue_state output_state; | 585 | enum s5p_mfc_queue_state output_state; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 585b7b0ed8ec..2e5f30b40dea 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | |||
@@ -22,16 +22,64 @@ | |||
22 | #include "s5p_mfc_opr.h" | 22 | #include "s5p_mfc_opr.h" |
23 | #include "s5p_mfc_pm.h" | 23 | #include "s5p_mfc_pm.h" |
24 | 24 | ||
25 | static void *s5p_mfc_bitproc_buf; | 25 | /* Allocate memory for firmware */ |
26 | static size_t s5p_mfc_bitproc_phys; | 26 | int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) |
27 | static unsigned char *s5p_mfc_bitproc_virt; | 27 | { |
28 | void *bank2_virt; | ||
29 | dma_addr_t bank2_dma_addr; | ||
30 | |||
31 | dev->fw_size = dev->variant->buf_size->fw; | ||
32 | |||
33 | if (dev->fw_virt_addr) { | ||
34 | mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); | ||
35 | return -ENOMEM; | ||
36 | } | ||
37 | |||
38 | dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size, | ||
39 | &dev->bank1, GFP_KERNEL); | ||
40 | |||
41 | if (IS_ERR(dev->fw_virt_addr)) { | ||
42 | dev->fw_virt_addr = NULL; | ||
43 | mfc_err("Allocating bitprocessor buffer failed\n"); | ||
44 | return -ENOMEM; | ||
45 | } | ||
46 | |||
47 | dev->bank1 = dev->bank1; | ||
48 | |||
49 | if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { | ||
50 | bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, | ||
51 | &bank2_dma_addr, GFP_KERNEL); | ||
52 | |||
53 | if (IS_ERR(dev->fw_virt_addr)) { | ||
54 | mfc_err("Allocating bank2 base failed\n"); | ||
55 | dma_free_coherent(dev->mem_dev_l, dev->fw_size, | ||
56 | dev->fw_virt_addr, dev->bank1); | ||
57 | dev->fw_virt_addr = NULL; | ||
58 | return -ENOMEM; | ||
59 | } | ||
60 | |||
61 | /* Valid buffers passed to MFC encoder with LAST_FRAME command | ||
62 | * should not have address of bank2 - MFC will treat it as a null frame. | ||
63 | * To avoid such situation we set bank2 address below the pool address. | ||
64 | */ | ||
65 | dev->bank2 = bank2_dma_addr - (1 << MFC_BASE_ALIGN_ORDER); | ||
66 | |||
67 | dma_free_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, | ||
68 | bank2_virt, bank2_dma_addr); | ||
69 | |||
70 | } else { | ||
71 | /* In this case bank2 can point to the same address as bank1. | ||
72 | * Firmware will always occupy the beggining of this area so it is | ||
73 | * impossible having a video frame buffer with zero address. */ | ||
74 | dev->bank2 = dev->bank1; | ||
75 | } | ||
76 | return 0; | ||
77 | } | ||
28 | 78 | ||
29 | /* Allocate and load firmware */ | 79 | /* Load firmware */ |
30 | int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) | 80 | int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev) |
31 | { | 81 | { |
32 | struct firmware *fw_blob; | 82 | struct firmware *fw_blob; |
33 | size_t bank2_base_phys; | ||
34 | void *b_base; | ||
35 | int err; | 83 | int err; |
36 | 84 | ||
37 | /* Firmare has to be present as a separate file or compiled | 85 | /* Firmare has to be present as a separate file or compiled |
@@ -44,77 +92,17 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) | |||
44 | mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); | 92 | mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); |
45 | return -EINVAL; | 93 | return -EINVAL; |
46 | } | 94 | } |
47 | dev->fw_size = dev->variant->buf_size->fw; | ||
48 | if (fw_blob->size > dev->fw_size) { | 95 | if (fw_blob->size > dev->fw_size) { |
49 | mfc_err("MFC firmware is too big to be loaded\n"); | 96 | mfc_err("MFC firmware is too big to be loaded\n"); |
50 | release_firmware(fw_blob); | 97 | release_firmware(fw_blob); |
51 | return -ENOMEM; | 98 | return -ENOMEM; |
52 | } | 99 | } |
53 | if (s5p_mfc_bitproc_buf) { | 100 | if (!dev->fw_virt_addr) { |
54 | mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); | 101 | mfc_err("MFC firmware is not allocated\n"); |
55 | release_firmware(fw_blob); | ||
56 | return -ENOMEM; | ||
57 | } | ||
58 | s5p_mfc_bitproc_buf = vb2_dma_contig_memops.alloc( | ||
59 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], dev->fw_size); | ||
60 | if (IS_ERR(s5p_mfc_bitproc_buf)) { | ||
61 | s5p_mfc_bitproc_buf = NULL; | ||
62 | mfc_err("Allocating bitprocessor buffer failed\n"); | ||
63 | release_firmware(fw_blob); | 102 | release_firmware(fw_blob); |
64 | return -ENOMEM; | 103 | return -EINVAL; |
65 | } | ||
66 | s5p_mfc_bitproc_phys = s5p_mfc_mem_cookie( | ||
67 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], s5p_mfc_bitproc_buf); | ||
68 | if (s5p_mfc_bitproc_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) { | ||
69 | mfc_err("The base memory for bank 1 is not aligned to 128KB\n"); | ||
70 | vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); | ||
71 | s5p_mfc_bitproc_phys = 0; | ||
72 | s5p_mfc_bitproc_buf = NULL; | ||
73 | release_firmware(fw_blob); | ||
74 | return -EIO; | ||
75 | } | ||
76 | s5p_mfc_bitproc_virt = vb2_dma_contig_memops.vaddr(s5p_mfc_bitproc_buf); | ||
77 | if (!s5p_mfc_bitproc_virt) { | ||
78 | mfc_err("Bitprocessor memory remap failed\n"); | ||
79 | vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); | ||
80 | s5p_mfc_bitproc_phys = 0; | ||
81 | s5p_mfc_bitproc_buf = NULL; | ||
82 | release_firmware(fw_blob); | ||
83 | return -EIO; | ||
84 | } | ||
85 | dev->bank1 = s5p_mfc_bitproc_phys; | ||
86 | if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { | ||
87 | b_base = vb2_dma_contig_memops.alloc( | ||
88 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], | ||
89 | 1 << MFC_BASE_ALIGN_ORDER); | ||
90 | if (IS_ERR(b_base)) { | ||
91 | vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); | ||
92 | s5p_mfc_bitproc_phys = 0; | ||
93 | s5p_mfc_bitproc_buf = NULL; | ||
94 | mfc_err("Allocating bank2 base failed\n"); | ||
95 | release_firmware(fw_blob); | ||
96 | return -ENOMEM; | ||
97 | } | ||
98 | bank2_base_phys = s5p_mfc_mem_cookie( | ||
99 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base); | ||
100 | vb2_dma_contig_memops.put(b_base); | ||
101 | if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) { | ||
102 | mfc_err("The base memory for bank 2 is not aligned to 128KB\n"); | ||
103 | vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); | ||
104 | s5p_mfc_bitproc_phys = 0; | ||
105 | s5p_mfc_bitproc_buf = NULL; | ||
106 | release_firmware(fw_blob); | ||
107 | return -EIO; | ||
108 | } | ||
109 | /* Valid buffers passed to MFC encoder with LAST_FRAME command | ||
110 | * should not have address of bank2 - MFC will treat it as a null frame. | ||
111 | * To avoid such situation we set bank2 address below the pool address. | ||
112 | */ | ||
113 | dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER); | ||
114 | } else { | ||
115 | dev->bank2 = dev->bank1; | ||
116 | } | 104 | } |
117 | memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); | 105 | memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size); |
118 | wmb(); | 106 | wmb(); |
119 | release_firmware(fw_blob); | 107 | release_firmware(fw_blob); |
120 | mfc_debug_leave(); | 108 | mfc_debug_leave(); |
@@ -142,12 +130,12 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev) | |||
142 | release_firmware(fw_blob); | 130 | release_firmware(fw_blob); |
143 | return -ENOMEM; | 131 | return -ENOMEM; |
144 | } | 132 | } |
145 | if (s5p_mfc_bitproc_buf == NULL || s5p_mfc_bitproc_phys == 0) { | 133 | if (!dev->fw_virt_addr) { |
146 | mfc_err("MFC firmware is not allocated or was not mapped correctly\n"); | 134 | mfc_err("MFC firmware is not allocated\n"); |
147 | release_firmware(fw_blob); | 135 | release_firmware(fw_blob); |
148 | return -EINVAL; | 136 | return -EINVAL; |
149 | } | 137 | } |
150 | memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); | 138 | memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size); |
151 | wmb(); | 139 | wmb(); |
152 | release_firmware(fw_blob); | 140 | release_firmware(fw_blob); |
153 | mfc_debug_leave(); | 141 | mfc_debug_leave(); |
@@ -159,12 +147,11 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev) | |||
159 | { | 147 | { |
160 | /* Before calling this function one has to make sure | 148 | /* Before calling this function one has to make sure |
161 | * that MFC is no longer processing */ | 149 | * that MFC is no longer processing */ |
162 | if (!s5p_mfc_bitproc_buf) | 150 | if (!dev->fw_virt_addr) |
163 | return -EINVAL; | 151 | return -EINVAL; |
164 | vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); | 152 | dma_free_coherent(dev->mem_dev_l, dev->fw_size, dev->fw_virt_addr, |
165 | s5p_mfc_bitproc_virt = NULL; | 153 | dev->bank1); |
166 | s5p_mfc_bitproc_phys = 0; | 154 | dev->fw_virt_addr = NULL; |
167 | s5p_mfc_bitproc_buf = NULL; | ||
168 | return 0; | 155 | return 0; |
169 | } | 156 | } |
170 | 157 | ||
@@ -257,8 +244,10 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
257 | int ret; | 244 | int ret; |
258 | 245 | ||
259 | mfc_debug_enter(); | 246 | mfc_debug_enter(); |
260 | if (!s5p_mfc_bitproc_buf) | 247 | if (!dev->fw_virt_addr) { |
248 | mfc_err("Firmware memory is not allocated.\n"); | ||
261 | return -EINVAL; | 249 | return -EINVAL; |
250 | } | ||
262 | 251 | ||
263 | /* 0. MFC reset */ | 252 | /* 0. MFC reset */ |
264 | mfc_debug(2, "MFC reset..\n"); | 253 | mfc_debug(2, "MFC reset..\n"); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h index 90aa9b9886d5..6a9b6f8606bb 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h | |||
@@ -16,7 +16,8 @@ | |||
16 | #include "s5p_mfc_common.h" | 16 | #include "s5p_mfc_common.h" |
17 | 17 | ||
18 | int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev); | 18 | int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev); |
19 | int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev); | 19 | int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev); |
20 | int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev); | ||
20 | int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev); | 21 | int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev); |
21 | 22 | ||
22 | int s5p_mfc_init_hw(struct s5p_mfc_dev *dev); | 23 | int s5p_mfc_init_hw(struct s5p_mfc_dev *dev); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 6dad9a74f61c..4582473978ca 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | |||
@@ -991,24 +991,35 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q) | |||
991 | S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0); | 991 | S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0); |
992 | aborted = 1; | 992 | aborted = 1; |
993 | } | 993 | } |
994 | spin_lock_irqsave(&dev->irqlock, flags); | ||
995 | if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | 994 | if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
995 | spin_lock_irqsave(&dev->irqlock, flags); | ||
996 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, | 996 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, |
997 | &ctx->vq_dst); | 997 | &ctx->vq_dst); |
998 | INIT_LIST_HEAD(&ctx->dst_queue); | 998 | INIT_LIST_HEAD(&ctx->dst_queue); |
999 | ctx->dst_queue_cnt = 0; | 999 | ctx->dst_queue_cnt = 0; |
1000 | ctx->dpb_flush_flag = 1; | 1000 | ctx->dpb_flush_flag = 1; |
1001 | ctx->dec_dst_flag = 0; | 1001 | ctx->dec_dst_flag = 0; |
1002 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1003 | if (IS_MFCV6(dev) && (ctx->state == MFCINST_RUNNING)) { | ||
1004 | ctx->state = MFCINST_FLUSH; | ||
1005 | set_work_bit_irqsave(ctx); | ||
1006 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1007 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | ||
1008 | if (s5p_mfc_wait_for_done_ctx(ctx, | ||
1009 | S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0)) | ||
1010 | mfc_err("Err flushing buffers\n"); | ||
1011 | } | ||
1002 | } | 1012 | } |
1003 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | 1013 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
1014 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1004 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, | 1015 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, |
1005 | &ctx->vq_src); | 1016 | &ctx->vq_src); |
1006 | INIT_LIST_HEAD(&ctx->src_queue); | 1017 | INIT_LIST_HEAD(&ctx->src_queue); |
1007 | ctx->src_queue_cnt = 0; | 1018 | ctx->src_queue_cnt = 0; |
1019 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1008 | } | 1020 | } |
1009 | if (aborted) | 1021 | if (aborted) |
1010 | ctx->state = MFCINST_RUNNING; | 1022 | ctx->state = MFCINST_RUNNING; |
1011 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1012 | return 0; | 1023 | return 0; |
1013 | } | 1024 | } |
1014 | 1025 | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index f92f6ddd739f..2356fd52a169 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | |||
@@ -1534,6 +1534,8 @@ int vidioc_encoder_cmd(struct file *file, void *priv, | |||
1534 | if (list_empty(&ctx->src_queue)) { | 1534 | if (list_empty(&ctx->src_queue)) { |
1535 | mfc_debug(2, "EOS: empty src queue, entering finishing state"); | 1535 | mfc_debug(2, "EOS: empty src queue, entering finishing state"); |
1536 | ctx->state = MFCINST_FINISHING; | 1536 | ctx->state = MFCINST_FINISHING; |
1537 | if (s5p_mfc_ctx_ready(ctx)) | ||
1538 | set_work_bit_irqsave(ctx); | ||
1537 | spin_unlock_irqrestore(&dev->irqlock, flags); | 1539 | spin_unlock_irqrestore(&dev->irqlock, flags); |
1538 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | 1540 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
1539 | } else { | 1541 | } else { |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 6932e90d4065..10f8ac37cecd 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include "s5p_mfc_debug.h" | ||
15 | #include "s5p_mfc_opr.h" | 16 | #include "s5p_mfc_opr.h" |
16 | #include "s5p_mfc_opr_v5.h" | 17 | #include "s5p_mfc_opr_v5.h" |
17 | #include "s5p_mfc_opr_v6.h" | 18 | #include "s5p_mfc_opr_v6.h" |
@@ -29,3 +30,32 @@ void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev) | |||
29 | } | 30 | } |
30 | dev->mfc_ops = s5p_mfc_ops; | 31 | dev->mfc_ops = s5p_mfc_ops; |
31 | } | 32 | } |
33 | |||
34 | int s5p_mfc_alloc_priv_buf(struct device *dev, | ||
35 | struct s5p_mfc_priv_buf *b) | ||
36 | { | ||
37 | |||
38 | mfc_debug(3, "Allocating priv: %d\n", b->size); | ||
39 | |||
40 | b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL); | ||
41 | |||
42 | if (!b->virt) { | ||
43 | mfc_err("Allocating private buffer failed\n"); | ||
44 | return -ENOMEM; | ||
45 | } | ||
46 | |||
47 | mfc_debug(3, "Allocated addr %p %08x\n", b->virt, b->dma); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | void s5p_mfc_release_priv_buf(struct device *dev, | ||
52 | struct s5p_mfc_priv_buf *b) | ||
53 | { | ||
54 | if (b->virt) { | ||
55 | dma_free_coherent(dev, b->size, b->virt, b->dma); | ||
56 | b->virt = NULL; | ||
57 | b->dma = 0; | ||
58 | b->size = 0; | ||
59 | } | ||
60 | } | ||
61 | |||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h index 420abecafec0..754c540e7a7e 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | |||
@@ -80,5 +80,10 @@ struct s5p_mfc_hw_ops { | |||
80 | }; | 80 | }; |
81 | 81 | ||
82 | void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev); | 82 | void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev); |
83 | int s5p_mfc_alloc_priv_buf(struct device *dev, | ||
84 | struct s5p_mfc_priv_buf *b); | ||
85 | void s5p_mfc_release_priv_buf(struct device *dev, | ||
86 | struct s5p_mfc_priv_buf *b); | ||
87 | |||
83 | 88 | ||
84 | #endif /* S5P_MFC_OPR_H_ */ | 89 | #endif /* S5P_MFC_OPR_H_ */ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index bf7d010a4107..f61dba837899 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | |||
@@ -38,39 +38,26 @@ int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) | |||
38 | { | 38 | { |
39 | struct s5p_mfc_dev *dev = ctx->dev; | 39 | struct s5p_mfc_dev *dev = ctx->dev; |
40 | struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv; | 40 | struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv; |
41 | int ret; | ||
41 | 42 | ||
42 | ctx->dsc.alloc = vb2_dma_contig_memops.alloc( | 43 | ctx->dsc.size = buf_size->dsc; |
43 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], | 44 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->dsc); |
44 | buf_size->dsc); | 45 | if (ret) { |
45 | if (IS_ERR_VALUE((int)ctx->dsc.alloc)) { | 46 | mfc_err("Failed to allocate temporary buffer\n"); |
46 | ctx->dsc.alloc = NULL; | 47 | return ret; |
47 | mfc_err("Allocating DESC buffer failed\n"); | ||
48 | return -ENOMEM; | ||
49 | } | 48 | } |
50 | ctx->dsc.dma = s5p_mfc_mem_cookie( | 49 | |
51 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->dsc.alloc); | ||
52 | BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | 50 | BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); |
53 | ctx->dsc.virt = vb2_dma_contig_memops.vaddr(ctx->dsc.alloc); | 51 | memset(ctx->dsc.virt, 0, ctx->dsc.size); |
54 | if (ctx->dsc.virt == NULL) { | ||
55 | vb2_dma_contig_memops.put(ctx->dsc.alloc); | ||
56 | ctx->dsc.dma = 0; | ||
57 | ctx->dsc.alloc = NULL; | ||
58 | mfc_err("Remapping DESC buffer failed\n"); | ||
59 | return -ENOMEM; | ||
60 | } | ||
61 | memset(ctx->dsc.virt, 0, buf_size->dsc); | ||
62 | wmb(); | 52 | wmb(); |
63 | return 0; | 53 | return 0; |
64 | } | 54 | } |
65 | 55 | ||
56 | |||
66 | /* Release temporary buffers for decoding */ | 57 | /* Release temporary buffers for decoding */ |
67 | void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx) | 58 | void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx) |
68 | { | 59 | { |
69 | if (ctx->dsc.dma) { | 60 | s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->dsc); |
70 | vb2_dma_contig_memops.put(ctx->dsc.alloc); | ||
71 | ctx->dsc.alloc = NULL; | ||
72 | ctx->dsc.dma = 0; | ||
73 | } | ||
74 | } | 61 | } |
75 | 62 | ||
76 | /* Allocate codec buffers */ | 63 | /* Allocate codec buffers */ |
@@ -80,6 +67,7 @@ int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) | |||
80 | unsigned int enc_ref_y_size = 0; | 67 | unsigned int enc_ref_y_size = 0; |
81 | unsigned int enc_ref_c_size = 0; | 68 | unsigned int enc_ref_c_size = 0; |
82 | unsigned int guard_width, guard_height; | 69 | unsigned int guard_width, guard_height; |
70 | int ret; | ||
83 | 71 | ||
84 | if (ctx->type == MFCINST_DECODER) { | 72 | if (ctx->type == MFCINST_DECODER) { |
85 | mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n", | 73 | mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n", |
@@ -113,100 +101,93 @@ int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) | |||
113 | /* Codecs have different memory requirements */ | 101 | /* Codecs have different memory requirements */ |
114 | switch (ctx->codec_mode) { | 102 | switch (ctx->codec_mode) { |
115 | case S5P_MFC_CODEC_H264_DEC: | 103 | case S5P_MFC_CODEC_H264_DEC: |
116 | ctx->bank1_size = | 104 | ctx->bank1.size = |
117 | ALIGN(S5P_FIMV_DEC_NB_IP_SIZE + | 105 | ALIGN(S5P_FIMV_DEC_NB_IP_SIZE + |
118 | S5P_FIMV_DEC_VERT_NB_MV_SIZE, | 106 | S5P_FIMV_DEC_VERT_NB_MV_SIZE, |
119 | S5P_FIMV_DEC_BUF_ALIGN); | 107 | S5P_FIMV_DEC_BUF_ALIGN); |
120 | ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size; | 108 | ctx->bank2.size = ctx->total_dpb_count * ctx->mv_size; |
121 | break; | 109 | break; |
122 | case S5P_MFC_CODEC_MPEG4_DEC: | 110 | case S5P_MFC_CODEC_MPEG4_DEC: |
123 | ctx->bank1_size = | 111 | ctx->bank1.size = |
124 | ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE + | 112 | ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE + |
125 | S5P_FIMV_DEC_UPNB_MV_SIZE + | 113 | S5P_FIMV_DEC_UPNB_MV_SIZE + |
126 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + | 114 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + |
127 | S5P_FIMV_DEC_STX_PARSER_SIZE + | 115 | S5P_FIMV_DEC_STX_PARSER_SIZE + |
128 | S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE, | 116 | S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE, |
129 | S5P_FIMV_DEC_BUF_ALIGN); | 117 | S5P_FIMV_DEC_BUF_ALIGN); |
130 | ctx->bank2_size = 0; | 118 | ctx->bank2.size = 0; |
131 | break; | 119 | break; |
132 | case S5P_MFC_CODEC_VC1RCV_DEC: | 120 | case S5P_MFC_CODEC_VC1RCV_DEC: |
133 | case S5P_MFC_CODEC_VC1_DEC: | 121 | case S5P_MFC_CODEC_VC1_DEC: |
134 | ctx->bank1_size = | 122 | ctx->bank1.size = |
135 | ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE + | 123 | ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE + |
136 | S5P_FIMV_DEC_UPNB_MV_SIZE + | 124 | S5P_FIMV_DEC_UPNB_MV_SIZE + |
137 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + | 125 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + |
138 | S5P_FIMV_DEC_NB_DCAC_SIZE + | 126 | S5P_FIMV_DEC_NB_DCAC_SIZE + |
139 | 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE, | 127 | 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE, |
140 | S5P_FIMV_DEC_BUF_ALIGN); | 128 | S5P_FIMV_DEC_BUF_ALIGN); |
141 | ctx->bank2_size = 0; | 129 | ctx->bank2.size = 0; |
142 | break; | 130 | break; |
143 | case S5P_MFC_CODEC_MPEG2_DEC: | 131 | case S5P_MFC_CODEC_MPEG2_DEC: |
144 | ctx->bank1_size = 0; | 132 | ctx->bank1.size = 0; |
145 | ctx->bank2_size = 0; | 133 | ctx->bank2.size = 0; |
146 | break; | 134 | break; |
147 | case S5P_MFC_CODEC_H263_DEC: | 135 | case S5P_MFC_CODEC_H263_DEC: |
148 | ctx->bank1_size = | 136 | ctx->bank1.size = |
149 | ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE + | 137 | ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE + |
150 | S5P_FIMV_DEC_UPNB_MV_SIZE + | 138 | S5P_FIMV_DEC_UPNB_MV_SIZE + |
151 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + | 139 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + |
152 | S5P_FIMV_DEC_NB_DCAC_SIZE, | 140 | S5P_FIMV_DEC_NB_DCAC_SIZE, |
153 | S5P_FIMV_DEC_BUF_ALIGN); | 141 | S5P_FIMV_DEC_BUF_ALIGN); |
154 | ctx->bank2_size = 0; | 142 | ctx->bank2.size = 0; |
155 | break; | 143 | break; |
156 | case S5P_MFC_CODEC_H264_ENC: | 144 | case S5P_MFC_CODEC_H264_ENC: |
157 | ctx->bank1_size = (enc_ref_y_size * 2) + | 145 | ctx->bank1.size = (enc_ref_y_size * 2) + |
158 | S5P_FIMV_ENC_UPMV_SIZE + | 146 | S5P_FIMV_ENC_UPMV_SIZE + |
159 | S5P_FIMV_ENC_COLFLG_SIZE + | 147 | S5P_FIMV_ENC_COLFLG_SIZE + |
160 | S5P_FIMV_ENC_INTRAMD_SIZE + | 148 | S5P_FIMV_ENC_INTRAMD_SIZE + |
161 | S5P_FIMV_ENC_NBORINFO_SIZE; | 149 | S5P_FIMV_ENC_NBORINFO_SIZE; |
162 | ctx->bank2_size = (enc_ref_y_size * 2) + | 150 | ctx->bank2.size = (enc_ref_y_size * 2) + |
163 | (enc_ref_c_size * 4) + | 151 | (enc_ref_c_size * 4) + |
164 | S5P_FIMV_ENC_INTRAPRED_SIZE; | 152 | S5P_FIMV_ENC_INTRAPRED_SIZE; |
165 | break; | 153 | break; |
166 | case S5P_MFC_CODEC_MPEG4_ENC: | 154 | case S5P_MFC_CODEC_MPEG4_ENC: |
167 | ctx->bank1_size = (enc_ref_y_size * 2) + | 155 | ctx->bank1.size = (enc_ref_y_size * 2) + |
168 | S5P_FIMV_ENC_UPMV_SIZE + | 156 | S5P_FIMV_ENC_UPMV_SIZE + |
169 | S5P_FIMV_ENC_COLFLG_SIZE + | 157 | S5P_FIMV_ENC_COLFLG_SIZE + |
170 | S5P_FIMV_ENC_ACDCCOEF_SIZE; | 158 | S5P_FIMV_ENC_ACDCCOEF_SIZE; |
171 | ctx->bank2_size = (enc_ref_y_size * 2) + | 159 | ctx->bank2.size = (enc_ref_y_size * 2) + |
172 | (enc_ref_c_size * 4); | 160 | (enc_ref_c_size * 4); |
173 | break; | 161 | break; |
174 | case S5P_MFC_CODEC_H263_ENC: | 162 | case S5P_MFC_CODEC_H263_ENC: |
175 | ctx->bank1_size = (enc_ref_y_size * 2) + | 163 | ctx->bank1.size = (enc_ref_y_size * 2) + |
176 | S5P_FIMV_ENC_UPMV_SIZE + | 164 | S5P_FIMV_ENC_UPMV_SIZE + |
177 | S5P_FIMV_ENC_ACDCCOEF_SIZE; | 165 | S5P_FIMV_ENC_ACDCCOEF_SIZE; |
178 | ctx->bank2_size = (enc_ref_y_size * 2) + | 166 | ctx->bank2.size = (enc_ref_y_size * 2) + |
179 | (enc_ref_c_size * 4); | 167 | (enc_ref_c_size * 4); |
180 | break; | 168 | break; |
181 | default: | 169 | default: |
182 | break; | 170 | break; |
183 | } | 171 | } |
184 | /* Allocate only if memory from bank 1 is necessary */ | 172 | /* Allocate only if memory from bank 1 is necessary */ |
185 | if (ctx->bank1_size > 0) { | 173 | if (ctx->bank1.size > 0) { |
186 | ctx->bank1_buf = vb2_dma_contig_memops.alloc( | 174 | |
187 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size); | 175 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->bank1); |
188 | if (IS_ERR(ctx->bank1_buf)) { | 176 | if (ret) { |
189 | ctx->bank1_buf = NULL; | 177 | mfc_err("Failed to allocate Bank1 temporary buffer\n"); |
190 | printk(KERN_ERR | 178 | return ret; |
191 | "Buf alloc for decoding failed (port A)\n"); | ||
192 | return -ENOMEM; | ||
193 | } | 179 | } |
194 | ctx->bank1_phys = s5p_mfc_mem_cookie( | 180 | BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); |
195 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf); | ||
196 | BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
197 | } | 181 | } |
198 | /* Allocate only if memory from bank 2 is necessary */ | 182 | /* Allocate only if memory from bank 2 is necessary */ |
199 | if (ctx->bank2_size > 0) { | 183 | if (ctx->bank2.size > 0) { |
200 | ctx->bank2_buf = vb2_dma_contig_memops.alloc( | 184 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_r, &ctx->bank2); |
201 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size); | 185 | if (ret) { |
202 | if (IS_ERR(ctx->bank2_buf)) { | 186 | mfc_err("Failed to allocate Bank2 temporary buffer\n"); |
203 | ctx->bank2_buf = NULL; | 187 | s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); |
204 | mfc_err("Buf alloc for decoding failed (port B)\n"); | 188 | return ret; |
205 | return -ENOMEM; | ||
206 | } | 189 | } |
207 | ctx->bank2_phys = s5p_mfc_mem_cookie( | 190 | BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1)); |
208 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf); | ||
209 | BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1)); | ||
210 | } | 191 | } |
211 | return 0; | 192 | return 0; |
212 | } | 193 | } |
@@ -214,18 +195,8 @@ int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) | |||
214 | /* Release buffers allocated for codec */ | 195 | /* Release buffers allocated for codec */ |
215 | void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx) | 196 | void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx) |
216 | { | 197 | { |
217 | if (ctx->bank1_buf) { | 198 | s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); |
218 | vb2_dma_contig_memops.put(ctx->bank1_buf); | 199 | s5p_mfc_release_priv_buf(ctx->dev->mem_dev_r, &ctx->bank2); |
219 | ctx->bank1_buf = NULL; | ||
220 | ctx->bank1_phys = 0; | ||
221 | ctx->bank1_size = 0; | ||
222 | } | ||
223 | if (ctx->bank2_buf) { | ||
224 | vb2_dma_contig_memops.put(ctx->bank2_buf); | ||
225 | ctx->bank2_buf = NULL; | ||
226 | ctx->bank2_phys = 0; | ||
227 | ctx->bank2_size = 0; | ||
228 | } | ||
229 | } | 200 | } |
230 | 201 | ||
231 | /* Allocate memory for instance data buffer */ | 202 | /* Allocate memory for instance data buffer */ |
@@ -233,58 +204,38 @@ int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) | |||
233 | { | 204 | { |
234 | struct s5p_mfc_dev *dev = ctx->dev; | 205 | struct s5p_mfc_dev *dev = ctx->dev; |
235 | struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv; | 206 | struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv; |
207 | int ret; | ||
236 | 208 | ||
237 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || | 209 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || |
238 | ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) | 210 | ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) |
239 | ctx->ctx.size = buf_size->h264_ctx; | 211 | ctx->ctx.size = buf_size->h264_ctx; |
240 | else | 212 | else |
241 | ctx->ctx.size = buf_size->non_h264_ctx; | 213 | ctx->ctx.size = buf_size->non_h264_ctx; |
242 | ctx->ctx.alloc = vb2_dma_contig_memops.alloc( | 214 | |
243 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size); | 215 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->ctx); |
244 | if (IS_ERR(ctx->ctx.alloc)) { | 216 | if (ret) { |
245 | mfc_err("Allocating context buffer failed\n"); | 217 | mfc_err("Failed to allocate instance buffer\n"); |
246 | ctx->ctx.alloc = NULL; | 218 | return ret; |
247 | return -ENOMEM; | ||
248 | } | 219 | } |
249 | ctx->ctx.dma = s5p_mfc_mem_cookie( | ||
250 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc); | ||
251 | BUG_ON(ctx->ctx.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
252 | ctx->ctx.ofs = OFFSETA(ctx->ctx.dma); | 220 | ctx->ctx.ofs = OFFSETA(ctx->ctx.dma); |
253 | ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc); | 221 | |
254 | if (!ctx->ctx.virt) { | ||
255 | mfc_err("Remapping instance buffer failed\n"); | ||
256 | vb2_dma_contig_memops.put(ctx->ctx.alloc); | ||
257 | ctx->ctx.alloc = NULL; | ||
258 | ctx->ctx.ofs = 0; | ||
259 | ctx->ctx.dma = 0; | ||
260 | return -ENOMEM; | ||
261 | } | ||
262 | /* Zero content of the allocated memory */ | 222 | /* Zero content of the allocated memory */ |
263 | memset(ctx->ctx.virt, 0, ctx->ctx.size); | 223 | memset(ctx->ctx.virt, 0, ctx->ctx.size); |
264 | wmb(); | 224 | wmb(); |
265 | 225 | ||
266 | /* Initialize shared memory */ | 226 | /* Initialize shared memory */ |
267 | ctx->shm.alloc = vb2_dma_contig_memops.alloc( | 227 | ctx->shm.size = buf_size->shm; |
268 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->shm); | 228 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->shm); |
269 | if (IS_ERR(ctx->shm.alloc)) { | 229 | if (ret) { |
270 | mfc_err("failed to allocate shared memory\n"); | 230 | mfc_err("Failed to allocate shared memory buffer\n"); |
271 | return PTR_ERR(ctx->shm.alloc); | 231 | return ret; |
272 | } | 232 | } |
233 | |||
273 | /* shared memory offset only keeps the offset from base (port a) */ | 234 | /* shared memory offset only keeps the offset from base (port a) */ |
274 | ctx->shm.ofs = s5p_mfc_mem_cookie( | 235 | ctx->shm.ofs = ctx->shm.dma - dev->bank1; |
275 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm.alloc) | ||
276 | - dev->bank1; | ||
277 | BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | 236 | BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); |
278 | 237 | ||
279 | ctx->shm.virt = vb2_dma_contig_memops.vaddr(ctx->shm.alloc); | 238 | memset(ctx->shm.virt, 0, buf_size->shm); |
280 | if (!ctx->shm.virt) { | ||
281 | vb2_dma_contig_memops.put(ctx->shm.alloc); | ||
282 | ctx->shm.alloc = NULL; | ||
283 | ctx->shm.ofs = 0; | ||
284 | mfc_err("failed to virt addr of shared memory\n"); | ||
285 | return -ENOMEM; | ||
286 | } | ||
287 | memset((void *)ctx->shm.virt, 0, buf_size->shm); | ||
288 | wmb(); | 239 | wmb(); |
289 | return 0; | 240 | return 0; |
290 | } | 241 | } |
@@ -292,19 +243,8 @@ int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) | |||
292 | /* Release instance buffer */ | 243 | /* Release instance buffer */ |
293 | void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx) | 244 | void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx) |
294 | { | 245 | { |
295 | if (ctx->ctx.alloc) { | 246 | s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx); |
296 | vb2_dma_contig_memops.put(ctx->ctx.alloc); | 247 | s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->shm); |
297 | ctx->ctx.alloc = NULL; | ||
298 | ctx->ctx.ofs = 0; | ||
299 | ctx->ctx.virt = NULL; | ||
300 | ctx->ctx.dma = 0; | ||
301 | } | ||
302 | if (ctx->shm.alloc) { | ||
303 | vb2_dma_contig_memops.put(ctx->shm.alloc); | ||
304 | ctx->shm.alloc = NULL; | ||
305 | ctx->shm.ofs = 0; | ||
306 | ctx->shm.virt = NULL; | ||
307 | } | ||
308 | } | 248 | } |
309 | 249 | ||
310 | int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev) | 250 | int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev) |
@@ -443,10 +383,10 @@ int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx) | |||
443 | size_t buf_addr1, buf_addr2; | 383 | size_t buf_addr1, buf_addr2; |
444 | int buf_size1, buf_size2; | 384 | int buf_size1, buf_size2; |
445 | 385 | ||
446 | buf_addr1 = ctx->bank1_phys; | 386 | buf_addr1 = ctx->bank1.dma; |
447 | buf_size1 = ctx->bank1_size; | 387 | buf_size1 = ctx->bank1.size; |
448 | buf_addr2 = ctx->bank2_phys; | 388 | buf_addr2 = ctx->bank2.dma; |
449 | buf_size2 = ctx->bank2_size; | 389 | buf_size2 = ctx->bank2.size; |
450 | dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & | 390 | dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & |
451 | ~S5P_FIMV_DPB_COUNT_MASK; | 391 | ~S5P_FIMV_DPB_COUNT_MASK; |
452 | mfc_write(dev, ctx->total_dpb_count | dpb, | 392 | mfc_write(dev, ctx->total_dpb_count | dpb, |
@@ -523,7 +463,6 @@ int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx) | |||
523 | mfc_err("Unknown codec for decoding (%x)\n", | 463 | mfc_err("Unknown codec for decoding (%x)\n", |
524 | ctx->codec_mode); | 464 | ctx->codec_mode); |
525 | return -EINVAL; | 465 | return -EINVAL; |
526 | break; | ||
527 | } | 466 | } |
528 | frame_size = ctx->luma_size; | 467 | frame_size = ctx->luma_size; |
529 | frame_size_ch = ctx->chroma_size; | 468 | frame_size_ch = ctx->chroma_size; |
@@ -607,10 +546,10 @@ int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx) | |||
607 | unsigned int guard_width, guard_height; | 546 | unsigned int guard_width, guard_height; |
608 | int i; | 547 | int i; |
609 | 548 | ||
610 | buf_addr1 = ctx->bank1_phys; | 549 | buf_addr1 = ctx->bank1.dma; |
611 | buf_size1 = ctx->bank1_size; | 550 | buf_size1 = ctx->bank1.size; |
612 | buf_addr2 = ctx->bank2_phys; | 551 | buf_addr2 = ctx->bank2.dma; |
613 | buf_size2 = ctx->bank2_size; | 552 | buf_size2 = ctx->bank2.size; |
614 | enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) | 553 | enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) |
615 | * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN); | 554 | * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN); |
616 | enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN); | 555 | enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 3a8cfd9fc1bd..beb6dbacebd9 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | |||
@@ -73,6 +73,7 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
73 | { | 73 | { |
74 | struct s5p_mfc_dev *dev = ctx->dev; | 74 | struct s5p_mfc_dev *dev = ctx->dev; |
75 | unsigned int mb_width, mb_height; | 75 | unsigned int mb_width, mb_height; |
76 | int ret; | ||
76 | 77 | ||
77 | mb_width = MB_WIDTH(ctx->img_width); | 78 | mb_width = MB_WIDTH(ctx->img_width); |
78 | mb_height = MB_HEIGHT(ctx->img_height); | 79 | mb_height = MB_HEIGHT(ctx->img_height); |
@@ -112,7 +113,7 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
112 | mb_height); | 113 | mb_height); |
113 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | 114 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
114 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 115 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
115 | ctx->bank1_size = | 116 | ctx->bank1.size = |
116 | ctx->scratch_buf_size + | 117 | ctx->scratch_buf_size + |
117 | (ctx->mv_count * ctx->mv_size); | 118 | (ctx->mv_count * ctx->mv_size); |
118 | break; | 119 | break; |
@@ -123,7 +124,7 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
123 | mb_height); | 124 | mb_height); |
124 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | 125 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
125 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 126 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
126 | ctx->bank1_size = ctx->scratch_buf_size; | 127 | ctx->bank1.size = ctx->scratch_buf_size; |
127 | break; | 128 | break; |
128 | case S5P_MFC_CODEC_VC1RCV_DEC: | 129 | case S5P_MFC_CODEC_VC1RCV_DEC: |
129 | case S5P_MFC_CODEC_VC1_DEC: | 130 | case S5P_MFC_CODEC_VC1_DEC: |
@@ -133,11 +134,11 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
133 | mb_height); | 134 | mb_height); |
134 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | 135 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
135 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 136 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
136 | ctx->bank1_size = ctx->scratch_buf_size; | 137 | ctx->bank1.size = ctx->scratch_buf_size; |
137 | break; | 138 | break; |
138 | case S5P_MFC_CODEC_MPEG2_DEC: | 139 | case S5P_MFC_CODEC_MPEG2_DEC: |
139 | ctx->bank1_size = 0; | 140 | ctx->bank1.size = 0; |
140 | ctx->bank2_size = 0; | 141 | ctx->bank2.size = 0; |
141 | break; | 142 | break; |
142 | case S5P_MFC_CODEC_H263_DEC: | 143 | case S5P_MFC_CODEC_H263_DEC: |
143 | ctx->scratch_buf_size = | 144 | ctx->scratch_buf_size = |
@@ -146,7 +147,7 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
146 | mb_height); | 147 | mb_height); |
147 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | 148 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
148 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 149 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
149 | ctx->bank1_size = ctx->scratch_buf_size; | 150 | ctx->bank1.size = ctx->scratch_buf_size; |
150 | break; | 151 | break; |
151 | case S5P_MFC_CODEC_VP8_DEC: | 152 | case S5P_MFC_CODEC_VP8_DEC: |
152 | ctx->scratch_buf_size = | 153 | ctx->scratch_buf_size = |
@@ -155,7 +156,7 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
155 | mb_height); | 156 | mb_height); |
156 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | 157 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
157 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 158 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
158 | ctx->bank1_size = ctx->scratch_buf_size; | 159 | ctx->bank1.size = ctx->scratch_buf_size; |
159 | break; | 160 | break; |
160 | case S5P_MFC_CODEC_H264_ENC: | 161 | case S5P_MFC_CODEC_H264_ENC: |
161 | ctx->scratch_buf_size = | 162 | ctx->scratch_buf_size = |
@@ -164,11 +165,11 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
164 | mb_height); | 165 | mb_height); |
165 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | 166 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
166 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 167 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
167 | ctx->bank1_size = | 168 | ctx->bank1.size = |
168 | ctx->scratch_buf_size + ctx->tmv_buffer_size + | 169 | ctx->scratch_buf_size + ctx->tmv_buffer_size + |
169 | (ctx->dpb_count * (ctx->luma_dpb_size + | 170 | (ctx->dpb_count * (ctx->luma_dpb_size + |
170 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | 171 | ctx->chroma_dpb_size + ctx->me_buffer_size)); |
171 | ctx->bank2_size = 0; | 172 | ctx->bank2.size = 0; |
172 | break; | 173 | break; |
173 | case S5P_MFC_CODEC_MPEG4_ENC: | 174 | case S5P_MFC_CODEC_MPEG4_ENC: |
174 | case S5P_MFC_CODEC_H263_ENC: | 175 | case S5P_MFC_CODEC_H263_ENC: |
@@ -178,28 +179,24 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
178 | mb_height); | 179 | mb_height); |
179 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | 180 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
180 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 181 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
181 | ctx->bank1_size = | 182 | ctx->bank1.size = |
182 | ctx->scratch_buf_size + ctx->tmv_buffer_size + | 183 | ctx->scratch_buf_size + ctx->tmv_buffer_size + |
183 | (ctx->dpb_count * (ctx->luma_dpb_size + | 184 | (ctx->dpb_count * (ctx->luma_dpb_size + |
184 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | 185 | ctx->chroma_dpb_size + ctx->me_buffer_size)); |
185 | ctx->bank2_size = 0; | 186 | ctx->bank2.size = 0; |
186 | break; | 187 | break; |
187 | default: | 188 | default: |
188 | break; | 189 | break; |
189 | } | 190 | } |
190 | 191 | ||
191 | /* Allocate only if memory from bank 1 is necessary */ | 192 | /* Allocate only if memory from bank 1 is necessary */ |
192 | if (ctx->bank1_size > 0) { | 193 | if (ctx->bank1.size > 0) { |
193 | ctx->bank1_buf = vb2_dma_contig_memops.alloc( | 194 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->bank1); |
194 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size); | 195 | if (ret) { |
195 | if (IS_ERR(ctx->bank1_buf)) { | 196 | mfc_err("Failed to allocate Bank1 memory\n"); |
196 | ctx->bank1_buf = 0; | 197 | return ret; |
197 | pr_err("Buf alloc for decoding failed (port A)\n"); | ||
198 | return -ENOMEM; | ||
199 | } | 198 | } |
200 | ctx->bank1_phys = s5p_mfc_mem_cookie( | 199 | BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); |
201 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf); | ||
202 | BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
203 | } | 200 | } |
204 | 201 | ||
205 | return 0; | 202 | return 0; |
@@ -208,12 +205,7 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
208 | /* Release buffers allocated for codec */ | 205 | /* Release buffers allocated for codec */ |
209 | void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | 206 | void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx) |
210 | { | 207 | { |
211 | if (ctx->bank1_buf) { | 208 | s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); |
212 | vb2_dma_contig_memops.put(ctx->bank1_buf); | ||
213 | ctx->bank1_buf = 0; | ||
214 | ctx->bank1_phys = 0; | ||
215 | ctx->bank1_size = 0; | ||
216 | } | ||
217 | } | 209 | } |
218 | 210 | ||
219 | /* Allocate memory for instance data buffer */ | 211 | /* Allocate memory for instance data buffer */ |
@@ -221,6 +213,7 @@ int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) | |||
221 | { | 213 | { |
222 | struct s5p_mfc_dev *dev = ctx->dev; | 214 | struct s5p_mfc_dev *dev = ctx->dev; |
223 | struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; | 215 | struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; |
216 | int ret; | ||
224 | 217 | ||
225 | mfc_debug_enter(); | 218 | mfc_debug_enter(); |
226 | 219 | ||
@@ -250,25 +243,10 @@ int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) | |||
250 | break; | 243 | break; |
251 | } | 244 | } |
252 | 245 | ||
253 | ctx->ctx.alloc = vb2_dma_contig_memops.alloc( | 246 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->ctx); |
254 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size); | 247 | if (ret) { |
255 | if (IS_ERR(ctx->ctx.alloc)) { | 248 | mfc_err("Failed to allocate instance buffer\n"); |
256 | mfc_err("Allocating context buffer failed.\n"); | 249 | return ret; |
257 | return PTR_ERR(ctx->ctx.alloc); | ||
258 | } | ||
259 | |||
260 | ctx->ctx.dma = s5p_mfc_mem_cookie( | ||
261 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc); | ||
262 | |||
263 | ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc); | ||
264 | if (!ctx->ctx.virt) { | ||
265 | vb2_dma_contig_memops.put(ctx->ctx.alloc); | ||
266 | ctx->ctx.alloc = NULL; | ||
267 | ctx->ctx.dma = 0; | ||
268 | ctx->ctx.virt = NULL; | ||
269 | |||
270 | mfc_err("Remapping context buffer failed.\n"); | ||
271 | return -ENOMEM; | ||
272 | } | 250 | } |
273 | 251 | ||
274 | memset(ctx->ctx.virt, 0, ctx->ctx.size); | 252 | memset(ctx->ctx.virt, 0, ctx->ctx.size); |
@@ -282,44 +260,22 @@ int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) | |||
282 | /* Release instance buffer */ | 260 | /* Release instance buffer */ |
283 | void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx) | 261 | void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx) |
284 | { | 262 | { |
285 | mfc_debug_enter(); | 263 | s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx); |
286 | |||
287 | if (ctx->ctx.alloc) { | ||
288 | vb2_dma_contig_memops.put(ctx->ctx.alloc); | ||
289 | ctx->ctx.alloc = NULL; | ||
290 | ctx->ctx.dma = 0; | ||
291 | ctx->ctx.virt = NULL; | ||
292 | } | ||
293 | |||
294 | mfc_debug_leave(); | ||
295 | } | 264 | } |
296 | 265 | ||
297 | /* Allocate context buffers for SYS_INIT */ | 266 | /* Allocate context buffers for SYS_INIT */ |
298 | int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) | 267 | int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) |
299 | { | 268 | { |
300 | struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; | 269 | struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; |
270 | int ret; | ||
301 | 271 | ||
302 | mfc_debug_enter(); | 272 | mfc_debug_enter(); |
303 | 273 | ||
304 | dev->ctx_buf.alloc = vb2_dma_contig_memops.alloc( | 274 | dev->ctx_buf.size = buf_size->dev_ctx; |
305 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->dev_ctx); | 275 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &dev->ctx_buf); |
306 | if (IS_ERR(dev->ctx_buf.alloc)) { | 276 | if (ret) { |
307 | mfc_err("Allocating DESC buffer failed.\n"); | 277 | mfc_err("Failed to allocate device context buffer\n"); |
308 | return PTR_ERR(dev->ctx_buf.alloc); | 278 | return ret; |
309 | } | ||
310 | |||
311 | dev->ctx_buf.dma = s5p_mfc_mem_cookie( | ||
312 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], | ||
313 | dev->ctx_buf.alloc); | ||
314 | |||
315 | dev->ctx_buf.virt = vb2_dma_contig_memops.vaddr(dev->ctx_buf.alloc); | ||
316 | if (!dev->ctx_buf.virt) { | ||
317 | vb2_dma_contig_memops.put(dev->ctx_buf.alloc); | ||
318 | dev->ctx_buf.alloc = NULL; | ||
319 | dev->ctx_buf.dma = 0; | ||
320 | |||
321 | mfc_err("Remapping DESC buffer failed.\n"); | ||
322 | return -ENOMEM; | ||
323 | } | 279 | } |
324 | 280 | ||
325 | memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx); | 281 | memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx); |
@@ -333,12 +289,7 @@ int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) | |||
333 | /* Release context buffers for SYS_INIT */ | 289 | /* Release context buffers for SYS_INIT */ |
334 | void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev) | 290 | void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev) |
335 | { | 291 | { |
336 | if (dev->ctx_buf.alloc) { | 292 | s5p_mfc_release_priv_buf(dev->mem_dev_l, &dev->ctx_buf); |
337 | vb2_dma_contig_memops.put(dev->ctx_buf.alloc); | ||
338 | dev->ctx_buf.alloc = NULL; | ||
339 | dev->ctx_buf.dma = 0; | ||
340 | dev->ctx_buf.virt = NULL; | ||
341 | } | ||
342 | } | 293 | } |
343 | 294 | ||
344 | static int calc_plane(int width, int height) | 295 | static int calc_plane(int width, int height) |
@@ -417,8 +368,8 @@ int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) | |||
417 | int buf_size1; | 368 | int buf_size1; |
418 | int align_gap; | 369 | int align_gap; |
419 | 370 | ||
420 | buf_addr1 = ctx->bank1_phys; | 371 | buf_addr1 = ctx->bank1.dma; |
421 | buf_size1 = ctx->bank1_size; | 372 | buf_size1 = ctx->bank1.size; |
422 | 373 | ||
423 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); | 374 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); |
424 | mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count); | 375 | mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count); |
@@ -535,13 +486,13 @@ void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, | |||
535 | int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) | 486 | int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) |
536 | { | 487 | { |
537 | struct s5p_mfc_dev *dev = ctx->dev; | 488 | struct s5p_mfc_dev *dev = ctx->dev; |
538 | size_t buf_addr1, buf_size1; | 489 | size_t buf_addr1; |
539 | int i; | 490 | int i, buf_size1; |
540 | 491 | ||
541 | mfc_debug_enter(); | 492 | mfc_debug_enter(); |
542 | 493 | ||
543 | buf_addr1 = ctx->bank1_phys; | 494 | buf_addr1 = ctx->bank1.dma; |
544 | buf_size1 = ctx->bank1_size; | 495 | buf_size1 = ctx->bank1.size; |
545 | 496 | ||
546 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); | 497 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); |
547 | 498 | ||
@@ -1253,12 +1204,14 @@ int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | |||
1253 | static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush) | 1204 | static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush) |
1254 | { | 1205 | { |
1255 | struct s5p_mfc_dev *dev = ctx->dev; | 1206 | struct s5p_mfc_dev *dev = ctx->dev; |
1256 | unsigned int dpb; | 1207 | |
1257 | if (flush) | 1208 | if (flush) { |
1258 | dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1 << 14); | 1209 | dev->curr_ctx = ctx->num; |
1259 | else | 1210 | s5p_mfc_clean_ctx_int_flags(ctx); |
1260 | dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~(1 << 14); | 1211 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); |
1261 | WRITEL(dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL); | 1212 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
1213 | S5P_FIMV_H2R_CMD_FLUSH_V6, NULL); | ||
1214 | } | ||
1262 | } | 1215 | } |
1263 | 1216 | ||
1264 | /* Decode a single frame */ | 1217 | /* Decode a single frame */ |
@@ -1408,7 +1361,6 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) | |||
1408 | struct s5p_mfc_buf *temp_vb; | 1361 | struct s5p_mfc_buf *temp_vb; |
1409 | unsigned long flags; | 1362 | unsigned long flags; |
1410 | int last_frame = 0; | 1363 | int last_frame = 0; |
1411 | unsigned int index; | ||
1412 | 1364 | ||
1413 | spin_lock_irqsave(&dev->irqlock, flags); | 1365 | spin_lock_irqsave(&dev->irqlock, flags); |
1414 | 1366 | ||
@@ -1427,8 +1379,6 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) | |||
1427 | temp_vb->b->v4l2_planes[0].bytesused); | 1379 | temp_vb->b->v4l2_planes[0].bytesused); |
1428 | spin_unlock_irqrestore(&dev->irqlock, flags); | 1380 | spin_unlock_irqrestore(&dev->irqlock, flags); |
1429 | 1381 | ||
1430 | index = temp_vb->b->v4l2_buf.index; | ||
1431 | |||
1432 | dev->curr_ctx = ctx->num; | 1382 | dev->curr_ctx = ctx->num; |
1433 | s5p_mfc_clean_ctx_int_flags(ctx); | 1383 | s5p_mfc_clean_ctx_int_flags(ctx); |
1434 | if (temp_vb->b->v4l2_planes[0].bytesused == 0) { | 1384 | if (temp_vb->b->v4l2_planes[0].bytesused == 0) { |
@@ -1452,7 +1402,6 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) | |||
1452 | unsigned int src_y_size, src_c_size; | 1402 | unsigned int src_y_size, src_c_size; |
1453 | */ | 1403 | */ |
1454 | unsigned int dst_size; | 1404 | unsigned int dst_size; |
1455 | unsigned int index; | ||
1456 | 1405 | ||
1457 | spin_lock_irqsave(&dev->irqlock, flags); | 1406 | spin_lock_irqsave(&dev->irqlock, flags); |
1458 | 1407 | ||
@@ -1487,8 +1436,6 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) | |||
1487 | 1436 | ||
1488 | spin_unlock_irqrestore(&dev->irqlock, flags); | 1437 | spin_unlock_irqrestore(&dev->irqlock, flags); |
1489 | 1438 | ||
1490 | index = src_mb->b->v4l2_buf.index; | ||
1491 | |||
1492 | dev->curr_ctx = ctx->num; | 1439 | dev->curr_ctx = ctx->num; |
1493 | s5p_mfc_clean_ctx_int_flags(ctx); | 1440 | s5p_mfc_clean_ctx_int_flags(ctx); |
1494 | s5p_mfc_encode_one_frame_v6(ctx); | 1441 | s5p_mfc_encode_one_frame_v6(ctx); |
@@ -1656,6 +1603,9 @@ void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) | |||
1656 | case MFCINST_HEAD_PARSED: | 1603 | case MFCINST_HEAD_PARSED: |
1657 | ret = s5p_mfc_run_init_dec_buffers(ctx); | 1604 | ret = s5p_mfc_run_init_dec_buffers(ctx); |
1658 | break; | 1605 | break; |
1606 | case MFCINST_FLUSH: | ||
1607 | s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag); | ||
1608 | break; | ||
1659 | case MFCINST_RES_CHANGE_INIT: | 1609 | case MFCINST_RES_CHANGE_INIT: |
1660 | s5p_mfc_run_dec_last_frames(ctx); | 1610 | s5p_mfc_run_dec_last_frames(ctx); |
1661 | break; | 1611 | break; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c index 2895333866fc..6aa38a56aaf2 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | |||
@@ -46,7 +46,7 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) | |||
46 | 46 | ||
47 | ret = clk_prepare(pm->clock_gate); | 47 | ret = clk_prepare(pm->clock_gate); |
48 | if (ret) { | 48 | if (ret) { |
49 | mfc_err("Failed to preapre clock-gating control\n"); | 49 | mfc_err("Failed to prepare clock-gating control\n"); |
50 | goto err_p_ip_clk; | 50 | goto err_p_ip_clk; |
51 | } | 51 | } |
52 | 52 | ||
diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index 7c1116c73bf3..8de1b3dce459 100644 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c | |||
@@ -656,7 +656,7 @@ static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd, | |||
656 | dev_dbg(hdev->dev, "%s\n", __func__); | 656 | dev_dbg(hdev->dev, "%s\n", __func__); |
657 | if (!hdev->cur_conf) | 657 | if (!hdev->cur_conf) |
658 | return -EINVAL; | 658 | return -EINVAL; |
659 | memset(fmt, 0, sizeof *fmt); | 659 | memset(fmt, 0, sizeof(*fmt)); |
660 | fmt->width = t->hact.end - t->hact.beg; | 660 | fmt->width = t->hact.end - t->hact.beg; |
661 | fmt->height = t->vact[0].end - t->vact[0].beg; | 661 | fmt->height = t->vact[0].end - t->vact[0].beg; |
662 | fmt->code = V4L2_MBUS_FMT_FIXED; /* means RGB888 */ | 662 | fmt->code = V4L2_MBUS_FMT_FIXED; /* means RGB888 */ |
@@ -760,7 +760,7 @@ static void hdmi_resources_cleanup(struct hdmi_device *hdev) | |||
760 | clk_put(res->sclk_hdmi); | 760 | clk_put(res->sclk_hdmi); |
761 | if (!IS_ERR_OR_NULL(res->hdmi)) | 761 | if (!IS_ERR_OR_NULL(res->hdmi)) |
762 | clk_put(res->hdmi); | 762 | clk_put(res->hdmi); |
763 | memset(res, 0, sizeof *res); | 763 | memset(res, 0, sizeof(*res)); |
764 | } | 764 | } |
765 | 765 | ||
766 | static int hdmi_resources_init(struct hdmi_device *hdev) | 766 | static int hdmi_resources_init(struct hdmi_device *hdev) |
@@ -777,31 +777,31 @@ static int hdmi_resources_init(struct hdmi_device *hdev) | |||
777 | 777 | ||
778 | dev_dbg(dev, "HDMI resource init\n"); | 778 | dev_dbg(dev, "HDMI resource init\n"); |
779 | 779 | ||
780 | memset(res, 0, sizeof *res); | 780 | memset(res, 0, sizeof(*res)); |
781 | /* get clocks, power */ | 781 | /* get clocks, power */ |
782 | 782 | ||
783 | res->hdmi = clk_get(dev, "hdmi"); | 783 | res->hdmi = clk_get(dev, "hdmi"); |
784 | if (IS_ERR_OR_NULL(res->hdmi)) { | 784 | if (IS_ERR(res->hdmi)) { |
785 | dev_err(dev, "failed to get clock 'hdmi'\n"); | 785 | dev_err(dev, "failed to get clock 'hdmi'\n"); |
786 | goto fail; | 786 | goto fail; |
787 | } | 787 | } |
788 | res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); | 788 | res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); |
789 | if (IS_ERR_OR_NULL(res->sclk_hdmi)) { | 789 | if (IS_ERR(res->sclk_hdmi)) { |
790 | dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); | 790 | dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); |
791 | goto fail; | 791 | goto fail; |
792 | } | 792 | } |
793 | res->sclk_pixel = clk_get(dev, "sclk_pixel"); | 793 | res->sclk_pixel = clk_get(dev, "sclk_pixel"); |
794 | if (IS_ERR_OR_NULL(res->sclk_pixel)) { | 794 | if (IS_ERR(res->sclk_pixel)) { |
795 | dev_err(dev, "failed to get clock 'sclk_pixel'\n"); | 795 | dev_err(dev, "failed to get clock 'sclk_pixel'\n"); |
796 | goto fail; | 796 | goto fail; |
797 | } | 797 | } |
798 | res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy"); | 798 | res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy"); |
799 | if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) { | 799 | if (IS_ERR(res->sclk_hdmiphy)) { |
800 | dev_err(dev, "failed to get clock 'sclk_hdmiphy'\n"); | 800 | dev_err(dev, "failed to get clock 'sclk_hdmiphy'\n"); |
801 | goto fail; | 801 | goto fail; |
802 | } | 802 | } |
803 | res->hdmiphy = clk_get(dev, "hdmiphy"); | 803 | res->hdmiphy = clk_get(dev, "hdmiphy"); |
804 | if (IS_ERR_OR_NULL(res->hdmiphy)) { | 804 | if (IS_ERR(res->hdmiphy)) { |
805 | dev_err(dev, "failed to get clock 'hdmiphy'\n"); | 805 | dev_err(dev, "failed to get clock 'hdmiphy'\n"); |
806 | goto fail; | 806 | goto fail; |
807 | } | 807 | } |
@@ -955,7 +955,7 @@ static int hdmi_probe(struct platform_device *pdev) | |||
955 | v4l2_subdev_init(sd, &hdmi_sd_ops); | 955 | v4l2_subdev_init(sd, &hdmi_sd_ops); |
956 | sd->owner = THIS_MODULE; | 956 | sd->owner = THIS_MODULE; |
957 | 957 | ||
958 | strlcpy(sd->name, "s5p-hdmi", sizeof sd->name); | 958 | strlcpy(sd->name, "s5p-hdmi", sizeof(sd->name)); |
959 | hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET; | 959 | hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET; |
960 | /* FIXME: missing fail preset is not supported */ | 960 | /* FIXME: missing fail preset is not supported */ |
961 | hdmi_dev->cur_conf = hdmi_preset2timings(hdmi_dev->cur_preset); | 961 | hdmi_dev->cur_conf = hdmi_preset2timings(hdmi_dev->cur_preset); |
diff --git a/drivers/media/platform/s5p-tv/hdmiphy_drv.c b/drivers/media/platform/s5p-tv/hdmiphy_drv.c index 06b5d2dbb2d9..80717cec76ae 100644 --- a/drivers/media/platform/s5p-tv/hdmiphy_drv.c +++ b/drivers/media/platform/s5p-tv/hdmiphy_drv.c | |||
@@ -284,7 +284,7 @@ static int hdmiphy_probe(struct i2c_client *client, | |||
284 | { | 284 | { |
285 | struct hdmiphy_ctx *ctx; | 285 | struct hdmiphy_ctx *ctx; |
286 | 286 | ||
287 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); | 287 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
288 | if (!ctx) | 288 | if (!ctx) |
289 | return -ENOMEM; | 289 | return -ENOMEM; |
290 | 290 | ||
diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h index b671e20e9318..04e6490a45be 100644 --- a/drivers/media/platform/s5p-tv/mixer.h +++ b/drivers/media/platform/s5p-tv/mixer.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | #include <linux/fb.h> | 21 | #include <linux/fb.h> |
22 | #include <linux/irqreturn.h> | ||
22 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
23 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
24 | #include <linux/wait.h> | 25 | #include <linux/wait.h> |
diff --git a/drivers/media/platform/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c index 02faea03aa7d..5733033a6ead 100644 --- a/drivers/media/platform/s5p-tv/mixer_drv.c +++ b/drivers/media/platform/s5p-tv/mixer_drv.c | |||
@@ -240,27 +240,27 @@ static int mxr_acquire_clocks(struct mxr_device *mdev) | |||
240 | struct device *dev = mdev->dev; | 240 | struct device *dev = mdev->dev; |
241 | 241 | ||
242 | res->mixer = clk_get(dev, "mixer"); | 242 | res->mixer = clk_get(dev, "mixer"); |
243 | if (IS_ERR_OR_NULL(res->mixer)) { | 243 | if (IS_ERR(res->mixer)) { |
244 | mxr_err(mdev, "failed to get clock 'mixer'\n"); | 244 | mxr_err(mdev, "failed to get clock 'mixer'\n"); |
245 | goto fail; | 245 | goto fail; |
246 | } | 246 | } |
247 | res->vp = clk_get(dev, "vp"); | 247 | res->vp = clk_get(dev, "vp"); |
248 | if (IS_ERR_OR_NULL(res->vp)) { | 248 | if (IS_ERR(res->vp)) { |
249 | mxr_err(mdev, "failed to get clock 'vp'\n"); | 249 | mxr_err(mdev, "failed to get clock 'vp'\n"); |
250 | goto fail; | 250 | goto fail; |
251 | } | 251 | } |
252 | res->sclk_mixer = clk_get(dev, "sclk_mixer"); | 252 | res->sclk_mixer = clk_get(dev, "sclk_mixer"); |
253 | if (IS_ERR_OR_NULL(res->sclk_mixer)) { | 253 | if (IS_ERR(res->sclk_mixer)) { |
254 | mxr_err(mdev, "failed to get clock 'sclk_mixer'\n"); | 254 | mxr_err(mdev, "failed to get clock 'sclk_mixer'\n"); |
255 | goto fail; | 255 | goto fail; |
256 | } | 256 | } |
257 | res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); | 257 | res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); |
258 | if (IS_ERR_OR_NULL(res->sclk_hdmi)) { | 258 | if (IS_ERR(res->sclk_hdmi)) { |
259 | mxr_err(mdev, "failed to get clock 'sclk_hdmi'\n"); | 259 | mxr_err(mdev, "failed to get clock 'sclk_hdmi'\n"); |
260 | goto fail; | 260 | goto fail; |
261 | } | 261 | } |
262 | res->sclk_dac = clk_get(dev, "sclk_dac"); | 262 | res->sclk_dac = clk_get(dev, "sclk_dac"); |
263 | if (IS_ERR_OR_NULL(res->sclk_dac)) { | 263 | if (IS_ERR(res->sclk_dac)) { |
264 | mxr_err(mdev, "failed to get clock 'sclk_dac'\n"); | 264 | mxr_err(mdev, "failed to get clock 'sclk_dac'\n"); |
265 | goto fail; | 265 | goto fail; |
266 | } | 266 | } |
@@ -298,7 +298,7 @@ static void mxr_release_resources(struct mxr_device *mdev) | |||
298 | { | 298 | { |
299 | mxr_release_clocks(mdev); | 299 | mxr_release_clocks(mdev); |
300 | mxr_release_plat_resources(mdev); | 300 | mxr_release_plat_resources(mdev); |
301 | memset(&mdev->res, 0, sizeof mdev->res); | 301 | memset(&mdev->res, 0, sizeof(mdev->res)); |
302 | } | 302 | } |
303 | 303 | ||
304 | static void mxr_release_layers(struct mxr_device *mdev) | 304 | static void mxr_release_layers(struct mxr_device *mdev) |
@@ -382,7 +382,7 @@ static int mxr_probe(struct platform_device *pdev) | |||
382 | /* mdev does not exist yet so no mxr_dbg is used */ | 382 | /* mdev does not exist yet so no mxr_dbg is used */ |
383 | dev_info(dev, "probe start\n"); | 383 | dev_info(dev, "probe start\n"); |
384 | 384 | ||
385 | mdev = kzalloc(sizeof *mdev, GFP_KERNEL); | 385 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); |
386 | if (!mdev) { | 386 | if (!mdev) { |
387 | dev_err(dev, "not enough memory.\n"); | 387 | dev_err(dev, "not enough memory.\n"); |
388 | ret = -ENOMEM; | 388 | ret = -ENOMEM; |
diff --git a/drivers/media/platform/s5p-tv/mixer_reg.c b/drivers/media/platform/s5p-tv/mixer_reg.c index 3b1670a045f4..b713403024ef 100644 --- a/drivers/media/platform/s5p-tv/mixer_reg.c +++ b/drivers/media/platform/s5p-tv/mixer_reg.c | |||
@@ -470,11 +470,11 @@ static inline void mxr_reg_vp_filter_set(struct mxr_device *mdev, | |||
470 | static void mxr_reg_vp_default_filter(struct mxr_device *mdev) | 470 | static void mxr_reg_vp_default_filter(struct mxr_device *mdev) |
471 | { | 471 | { |
472 | mxr_reg_vp_filter_set(mdev, VP_POLY8_Y0_LL, | 472 | mxr_reg_vp_filter_set(mdev, VP_POLY8_Y0_LL, |
473 | filter_y_horiz_tap8, sizeof filter_y_horiz_tap8); | 473 | filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8)); |
474 | mxr_reg_vp_filter_set(mdev, VP_POLY4_Y0_LL, | 474 | mxr_reg_vp_filter_set(mdev, VP_POLY4_Y0_LL, |
475 | filter_y_vert_tap4, sizeof filter_y_vert_tap4); | 475 | filter_y_vert_tap4, sizeof(filter_y_vert_tap4)); |
476 | mxr_reg_vp_filter_set(mdev, VP_POLY4_C0_LL, | 476 | mxr_reg_vp_filter_set(mdev, VP_POLY4_C0_LL, |
477 | filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4); | 477 | filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4)); |
478 | } | 478 | } |
479 | 479 | ||
480 | static void mxr_reg_mxr_dump(struct mxr_device *mdev) | 480 | static void mxr_reg_mxr_dump(struct mxr_device *mdev) |
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index 1f3b7436511c..82142a2d6d93 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/videodev2.h> | 19 | #include <linux/videodev2.h> |
20 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/platform_device.h> | ||
22 | #include <linux/timer.h> | 23 | #include <linux/timer.h> |
23 | #include <media/videobuf2-dma-contig.h> | 24 | #include <media/videobuf2-dma-contig.h> |
24 | 25 | ||
@@ -95,7 +96,7 @@ int mxr_acquire_video(struct mxr_device *mdev, | |||
95 | /* trying to register next output */ | 96 | /* trying to register next output */ |
96 | if (sd == NULL) | 97 | if (sd == NULL) |
97 | continue; | 98 | continue; |
98 | out = kzalloc(sizeof *out, GFP_KERNEL); | 99 | out = kzalloc(sizeof(*out), GFP_KERNEL); |
99 | if (out == NULL) { | 100 | if (out == NULL) { |
100 | mxr_err(mdev, "no memory for '%s'\n", | 101 | mxr_err(mdev, "no memory for '%s'\n", |
101 | conf->output_name); | 102 | conf->output_name); |
@@ -127,7 +128,7 @@ fail_output: | |||
127 | /* kfree is NULL-safe */ | 128 | /* kfree is NULL-safe */ |
128 | for (i = 0; i < mdev->output_cnt; ++i) | 129 | for (i = 0; i < mdev->output_cnt; ++i) |
129 | kfree(mdev->output[i]); | 130 | kfree(mdev->output[i]); |
130 | memset(mdev->output, 0, sizeof mdev->output); | 131 | memset(mdev->output, 0, sizeof(mdev->output)); |
131 | 132 | ||
132 | fail_vb2_allocator: | 133 | fail_vb2_allocator: |
133 | /* freeing allocator context */ | 134 | /* freeing allocator context */ |
@@ -160,8 +161,8 @@ static int mxr_querycap(struct file *file, void *priv, | |||
160 | 161 | ||
161 | mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); | 162 | mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); |
162 | 163 | ||
163 | strlcpy(cap->driver, MXR_DRIVER_NAME, sizeof cap->driver); | 164 | strlcpy(cap->driver, MXR_DRIVER_NAME, sizeof(cap->driver)); |
164 | strlcpy(cap->card, layer->vfd.name, sizeof cap->card); | 165 | strlcpy(cap->card, layer->vfd.name, sizeof(cap->card)); |
165 | sprintf(cap->bus_info, "%d", layer->idx); | 166 | sprintf(cap->bus_info, "%d", layer->idx); |
166 | cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_MPLANE; | 167 | cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_MPLANE; |
167 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | 168 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
@@ -192,7 +193,7 @@ static void mxr_layer_default_geo(struct mxr_layer *layer) | |||
192 | struct mxr_device *mdev = layer->mdev; | 193 | struct mxr_device *mdev = layer->mdev; |
193 | struct v4l2_mbus_framefmt mbus_fmt; | 194 | struct v4l2_mbus_framefmt mbus_fmt; |
194 | 195 | ||
195 | memset(&layer->geo, 0, sizeof layer->geo); | 196 | memset(&layer->geo, 0, sizeof(layer->geo)); |
196 | 197 | ||
197 | mxr_get_mbus_fmt(mdev, &mbus_fmt); | 198 | mxr_get_mbus_fmt(mdev, &mbus_fmt); |
198 | 199 | ||
@@ -425,7 +426,7 @@ static int mxr_s_selection(struct file *file, void *fh, | |||
425 | struct mxr_geometry tmp; | 426 | struct mxr_geometry tmp; |
426 | struct v4l2_rect res; | 427 | struct v4l2_rect res; |
427 | 428 | ||
428 | memset(&res, 0, sizeof res); | 429 | memset(&res, 0, sizeof(res)); |
429 | 430 | ||
430 | mxr_dbg(layer->mdev, "%s: rect: %dx%d@%d,%d\n", __func__, | 431 | mxr_dbg(layer->mdev, "%s: rect: %dx%d@%d,%d\n", __func__, |
431 | s->r.width, s->r.height, s->r.left, s->r.top); | 432 | s->r.width, s->r.height, s->r.left, s->r.top); |
@@ -464,7 +465,7 @@ static int mxr_s_selection(struct file *file, void *fh, | |||
464 | /* apply change and update geometry if needed */ | 465 | /* apply change and update geometry if needed */ |
465 | if (target) { | 466 | if (target) { |
466 | /* backup current geometry if setup fails */ | 467 | /* backup current geometry if setup fails */ |
467 | memcpy(&tmp, geo, sizeof tmp); | 468 | memcpy(&tmp, geo, sizeof(tmp)); |
468 | 469 | ||
469 | /* apply requested selection */ | 470 | /* apply requested selection */ |
470 | target->x_offset = s->r.left; | 471 | target->x_offset = s->r.left; |
@@ -496,7 +497,7 @@ static int mxr_s_selection(struct file *file, void *fh, | |||
496 | fail: | 497 | fail: |
497 | /* restore old geometry, which is not touched if target is NULL */ | 498 | /* restore old geometry, which is not touched if target is NULL */ |
498 | if (target) | 499 | if (target) |
499 | memcpy(geo, &tmp, sizeof tmp); | 500 | memcpy(geo, &tmp, sizeof(tmp)); |
500 | return -ERANGE; | 501 | return -ERANGE; |
501 | } | 502 | } |
502 | 503 | ||
@@ -1071,7 +1072,7 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, | |||
1071 | { | 1072 | { |
1072 | struct mxr_layer *layer; | 1073 | struct mxr_layer *layer; |
1073 | 1074 | ||
1074 | layer = kzalloc(sizeof *layer, GFP_KERNEL); | 1075 | layer = kzalloc(sizeof(*layer), GFP_KERNEL); |
1075 | if (layer == NULL) { | 1076 | if (layer == NULL) { |
1076 | mxr_err(mdev, "not enough memory for layer.\n"); | 1077 | mxr_err(mdev, "not enough memory for layer.\n"); |
1077 | goto fail; | 1078 | goto fail; |
diff --git a/drivers/media/platform/s5p-tv/sdo_drv.c b/drivers/media/platform/s5p-tv/sdo_drv.c index 91a6939a270a..ab6f9ef89423 100644 --- a/drivers/media/platform/s5p-tv/sdo_drv.c +++ b/drivers/media/platform/s5p-tv/sdo_drv.c | |||
@@ -301,7 +301,7 @@ static int sdo_probe(struct platform_device *pdev) | |||
301 | struct clk *sclk_vpll; | 301 | struct clk *sclk_vpll; |
302 | 302 | ||
303 | dev_info(dev, "probe start\n"); | 303 | dev_info(dev, "probe start\n"); |
304 | sdev = devm_kzalloc(&pdev->dev, sizeof *sdev, GFP_KERNEL); | 304 | sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL); |
305 | if (!sdev) { | 305 | if (!sdev) { |
306 | dev_err(dev, "not enough memory.\n"); | 306 | dev_err(dev, "not enough memory.\n"); |
307 | ret = -ENOMEM; | 307 | ret = -ENOMEM; |
@@ -341,47 +341,50 @@ static int sdo_probe(struct platform_device *pdev) | |||
341 | 341 | ||
342 | /* acquire clocks */ | 342 | /* acquire clocks */ |
343 | sdev->sclk_dac = clk_get(dev, "sclk_dac"); | 343 | sdev->sclk_dac = clk_get(dev, "sclk_dac"); |
344 | if (IS_ERR_OR_NULL(sdev->sclk_dac)) { | 344 | if (IS_ERR(sdev->sclk_dac)) { |
345 | dev_err(dev, "failed to get clock 'sclk_dac'\n"); | 345 | dev_err(dev, "failed to get clock 'sclk_dac'\n"); |
346 | ret = -ENXIO; | 346 | ret = PTR_ERR(sdev->sclk_dac); |
347 | goto fail; | 347 | goto fail; |
348 | } | 348 | } |
349 | sdev->dac = clk_get(dev, "dac"); | 349 | sdev->dac = clk_get(dev, "dac"); |
350 | if (IS_ERR_OR_NULL(sdev->dac)) { | 350 | if (IS_ERR(sdev->dac)) { |
351 | dev_err(dev, "failed to get clock 'dac'\n"); | 351 | dev_err(dev, "failed to get clock 'dac'\n"); |
352 | ret = -ENXIO; | 352 | ret = PTR_ERR(sdev->dac); |
353 | goto fail_sclk_dac; | 353 | goto fail_sclk_dac; |
354 | } | 354 | } |
355 | sdev->dacphy = clk_get(dev, "dacphy"); | 355 | sdev->dacphy = clk_get(dev, "dacphy"); |
356 | if (IS_ERR_OR_NULL(sdev->dacphy)) { | 356 | if (IS_ERR(sdev->dacphy)) { |
357 | dev_err(dev, "failed to get clock 'dacphy'\n"); | 357 | dev_err(dev, "failed to get clock 'dacphy'\n"); |
358 | ret = -ENXIO; | 358 | ret = PTR_ERR(sdev->dacphy); |
359 | goto fail_dac; | 359 | goto fail_dac; |
360 | } | 360 | } |
361 | sclk_vpll = clk_get(dev, "sclk_vpll"); | 361 | sclk_vpll = clk_get(dev, "sclk_vpll"); |
362 | if (IS_ERR_OR_NULL(sclk_vpll)) { | 362 | if (IS_ERR(sclk_vpll)) { |
363 | dev_err(dev, "failed to get clock 'sclk_vpll'\n"); | 363 | dev_err(dev, "failed to get clock 'sclk_vpll'\n"); |
364 | ret = -ENXIO; | 364 | ret = PTR_ERR(sclk_vpll); |
365 | goto fail_dacphy; | 365 | goto fail_dacphy; |
366 | } | 366 | } |
367 | clk_set_parent(sdev->sclk_dac, sclk_vpll); | 367 | clk_set_parent(sdev->sclk_dac, sclk_vpll); |
368 | clk_put(sclk_vpll); | 368 | clk_put(sclk_vpll); |
369 | sdev->fout_vpll = clk_get(dev, "fout_vpll"); | 369 | sdev->fout_vpll = clk_get(dev, "fout_vpll"); |
370 | if (IS_ERR_OR_NULL(sdev->fout_vpll)) { | 370 | if (IS_ERR(sdev->fout_vpll)) { |
371 | dev_err(dev, "failed to get clock 'fout_vpll'\n"); | 371 | dev_err(dev, "failed to get clock 'fout_vpll'\n"); |
372 | ret = PTR_ERR(sdev->fout_vpll); | ||
372 | goto fail_dacphy; | 373 | goto fail_dacphy; |
373 | } | 374 | } |
374 | dev_info(dev, "fout_vpll.rate = %lu\n", clk_get_rate(sclk_vpll)); | 375 | dev_info(dev, "fout_vpll.rate = %lu\n", clk_get_rate(sclk_vpll)); |
375 | 376 | ||
376 | /* acquire regulator */ | 377 | /* acquire regulator */ |
377 | sdev->vdac = devm_regulator_get(dev, "vdd33a_dac"); | 378 | sdev->vdac = devm_regulator_get(dev, "vdd33a_dac"); |
378 | if (IS_ERR_OR_NULL(sdev->vdac)) { | 379 | if (IS_ERR(sdev->vdac)) { |
379 | dev_err(dev, "failed to get regulator 'vdac'\n"); | 380 | dev_err(dev, "failed to get regulator 'vdac'\n"); |
381 | ret = PTR_ERR(sdev->vdac); | ||
380 | goto fail_fout_vpll; | 382 | goto fail_fout_vpll; |
381 | } | 383 | } |
382 | sdev->vdet = devm_regulator_get(dev, "vdet"); | 384 | sdev->vdet = devm_regulator_get(dev, "vdet"); |
383 | if (IS_ERR_OR_NULL(sdev->vdet)) { | 385 | if (IS_ERR(sdev->vdet)) { |
384 | dev_err(dev, "failed to get regulator 'vdet'\n"); | 386 | dev_err(dev, "failed to get regulator 'vdet'\n"); |
387 | ret = PTR_ERR(sdev->vdet); | ||
385 | goto fail_fout_vpll; | 388 | goto fail_fout_vpll; |
386 | } | 389 | } |
387 | 390 | ||
@@ -394,7 +397,7 @@ static int sdo_probe(struct platform_device *pdev) | |||
394 | /* configuration of interface subdevice */ | 397 | /* configuration of interface subdevice */ |
395 | v4l2_subdev_init(&sdev->sd, &sdo_sd_ops); | 398 | v4l2_subdev_init(&sdev->sd, &sdo_sd_ops); |
396 | sdev->sd.owner = THIS_MODULE; | 399 | sdev->sd.owner = THIS_MODULE; |
397 | strlcpy(sdev->sd.name, "s5p-sdo", sizeof sdev->sd.name); | 400 | strlcpy(sdev->sd.name, "s5p-sdo", sizeof(sdev->sd.name)); |
398 | 401 | ||
399 | /* set default format */ | 402 | /* set default format */ |
400 | sdev->fmt = sdo_find_format(SDO_DEFAULT_STD); | 403 | sdev->fmt = sdo_find_format(SDO_DEFAULT_STD); |
diff --git a/drivers/media/platform/s5p-tv/sii9234_drv.c b/drivers/media/platform/s5p-tv/sii9234_drv.c index 49191aac9634..d90d2286090b 100644 --- a/drivers/media/platform/s5p-tv/sii9234_drv.c +++ b/drivers/media/platform/s5p-tv/sii9234_drv.c | |||
@@ -338,7 +338,7 @@ static int sii9234_probe(struct i2c_client *client, | |||
338 | } | 338 | } |
339 | 339 | ||
340 | ctx->gpio_n_reset = pdata->gpio_n_reset; | 340 | ctx->gpio_n_reset = pdata->gpio_n_reset; |
341 | ret = gpio_request(ctx->gpio_n_reset, "MHL_RST"); | 341 | ret = devm_gpio_request(dev, ctx->gpio_n_reset, "MHL_RST"); |
342 | if (ret) { | 342 | if (ret) { |
343 | dev_err(dev, "failed to acquire MHL_RST gpio\n"); | 343 | dev_err(dev, "failed to acquire MHL_RST gpio\n"); |
344 | return ret; | 344 | return ret; |
@@ -370,7 +370,6 @@ fail_pm_get: | |||
370 | 370 | ||
371 | fail_pm: | 371 | fail_pm: |
372 | pm_runtime_disable(dev); | 372 | pm_runtime_disable(dev); |
373 | gpio_free(ctx->gpio_n_reset); | ||
374 | 373 | ||
375 | fail: | 374 | fail: |
376 | dev_err(dev, "probe failed\n"); | 375 | dev_err(dev, "probe failed\n"); |
@@ -381,11 +380,8 @@ fail: | |||
381 | static int sii9234_remove(struct i2c_client *client) | 380 | static int sii9234_remove(struct i2c_client *client) |
382 | { | 381 | { |
383 | struct device *dev = &client->dev; | 382 | struct device *dev = &client->dev; |
384 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
385 | struct sii9234_context *ctx = sd_to_context(sd); | ||
386 | 383 | ||
387 | pm_runtime_disable(dev); | 384 | pm_runtime_disable(dev); |
388 | gpio_free(ctx->gpio_n_reset); | ||
389 | 385 | ||
390 | dev_info(dev, "remove successful\n"); | 386 | dev_info(dev, "remove successful\n"); |
391 | 387 | ||
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c new file mode 100644 index 000000000000..cb54c69d5748 --- /dev/null +++ b/drivers/media/platform/sh_veu.c | |||
@@ -0,0 +1,1266 @@ | |||
1 | /* | ||
2 | * sh-mobile VEU mem2mem driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Renesas Electronics Corporation | ||
5 | * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de> | ||
6 | * Copyright (C) 2008 Magnus Damm | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation | ||
11 | */ | ||
12 | |||
13 | #include <linux/fs.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/pm_runtime.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/videodev2.h> | ||
23 | |||
24 | #include <media/v4l2-dev.h> | ||
25 | #include <media/v4l2-device.h> | ||
26 | #include <media/v4l2-ioctl.h> | ||
27 | #include <media/v4l2-mem2mem.h> | ||
28 | #include <media/videobuf2-dma-contig.h> | ||
29 | |||
30 | #define VEU_STR 0x00 /* start register */ | ||
31 | #define VEU_SWR 0x10 /* src: line length */ | ||
32 | #define VEU_SSR 0x14 /* src: image size */ | ||
33 | #define VEU_SAYR 0x18 /* src: y/rgb plane address */ | ||
34 | #define VEU_SACR 0x1c /* src: c plane address */ | ||
35 | #define VEU_BSSR 0x20 /* bundle mode register */ | ||
36 | #define VEU_EDWR 0x30 /* dst: line length */ | ||
37 | #define VEU_DAYR 0x34 /* dst: y/rgb plane address */ | ||
38 | #define VEU_DACR 0x38 /* dst: c plane address */ | ||
39 | #define VEU_TRCR 0x50 /* transform control */ | ||
40 | #define VEU_RFCR 0x54 /* resize scale */ | ||
41 | #define VEU_RFSR 0x58 /* resize clip */ | ||
42 | #define VEU_ENHR 0x5c /* enhance */ | ||
43 | #define VEU_FMCR 0x70 /* filter mode */ | ||
44 | #define VEU_VTCR 0x74 /* lowpass vertical */ | ||
45 | #define VEU_HTCR 0x78 /* lowpass horizontal */ | ||
46 | #define VEU_APCR 0x80 /* color match */ | ||
47 | #define VEU_ECCR 0x84 /* color replace */ | ||
48 | #define VEU_AFXR 0x90 /* fixed mode */ | ||
49 | #define VEU_SWPR 0x94 /* swap */ | ||
50 | #define VEU_EIER 0xa0 /* interrupt mask */ | ||
51 | #define VEU_EVTR 0xa4 /* interrupt event */ | ||
52 | #define VEU_STAR 0xb0 /* status */ | ||
53 | #define VEU_BSRR 0xb4 /* reset */ | ||
54 | |||
55 | #define VEU_MCR00 0x200 /* color conversion matrix coefficient 00 */ | ||
56 | #define VEU_MCR01 0x204 /* color conversion matrix coefficient 01 */ | ||
57 | #define VEU_MCR02 0x208 /* color conversion matrix coefficient 02 */ | ||
58 | #define VEU_MCR10 0x20c /* color conversion matrix coefficient 10 */ | ||
59 | #define VEU_MCR11 0x210 /* color conversion matrix coefficient 11 */ | ||
60 | #define VEU_MCR12 0x214 /* color conversion matrix coefficient 12 */ | ||
61 | #define VEU_MCR20 0x218 /* color conversion matrix coefficient 20 */ | ||
62 | #define VEU_MCR21 0x21c /* color conversion matrix coefficient 21 */ | ||
63 | #define VEU_MCR22 0x220 /* color conversion matrix coefficient 22 */ | ||
64 | #define VEU_COFFR 0x224 /* color conversion offset */ | ||
65 | #define VEU_CBR 0x228 /* color conversion clip */ | ||
66 | |||
67 | /* | ||
68 | * 4092x4092 max size is the normal case. In some cases it can be reduced to | ||
69 | * 2048x2048, in other cases it can be 4092x8188 or even 8188x8188. | ||
70 | */ | ||
71 | #define MAX_W 4092 | ||
72 | #define MAX_H 4092 | ||
73 | #define MIN_W 8 | ||
74 | #define MIN_H 8 | ||
75 | #define ALIGN_W 4 | ||
76 | |||
77 | /* 3 buffers of 2048 x 1536 - 3 megapixels @ 16bpp */ | ||
78 | #define VIDEO_MEM_LIMIT ALIGN(2048 * 1536 * 2 * 3, 1024 * 1024) | ||
79 | |||
80 | #define MEM2MEM_DEF_TRANSLEN 1 | ||
81 | |||
82 | struct sh_veu_dev; | ||
83 | |||
84 | struct sh_veu_file { | ||
85 | struct sh_veu_dev *veu_dev; | ||
86 | bool cfg_needed; | ||
87 | }; | ||
88 | |||
89 | struct sh_veu_format { | ||
90 | char *name; | ||
91 | u32 fourcc; | ||
92 | unsigned int depth; | ||
93 | unsigned int ydepth; | ||
94 | }; | ||
95 | |||
96 | /* video data format */ | ||
97 | struct sh_veu_vfmt { | ||
98 | /* Replace with v4l2_rect */ | ||
99 | struct v4l2_rect frame; | ||
100 | unsigned int bytesperline; | ||
101 | unsigned int offset_y; | ||
102 | unsigned int offset_c; | ||
103 | const struct sh_veu_format *fmt; | ||
104 | }; | ||
105 | |||
106 | struct sh_veu_dev { | ||
107 | struct v4l2_device v4l2_dev; | ||
108 | struct video_device vdev; | ||
109 | struct v4l2_m2m_dev *m2m_dev; | ||
110 | struct device *dev; | ||
111 | struct v4l2_m2m_ctx *m2m_ctx; | ||
112 | struct sh_veu_vfmt vfmt_out; | ||
113 | struct sh_veu_vfmt vfmt_in; | ||
114 | /* Only single user per direction so far */ | ||
115 | struct sh_veu_file *capture; | ||
116 | struct sh_veu_file *output; | ||
117 | struct mutex fop_lock; | ||
118 | void __iomem *base; | ||
119 | struct vb2_alloc_ctx *alloc_ctx; | ||
120 | spinlock_t lock; | ||
121 | bool is_2h; | ||
122 | unsigned int xaction; | ||
123 | bool aborting; | ||
124 | }; | ||
125 | |||
126 | enum sh_veu_fmt_idx { | ||
127 | SH_VEU_FMT_NV12, | ||
128 | SH_VEU_FMT_NV16, | ||
129 | SH_VEU_FMT_NV24, | ||
130 | SH_VEU_FMT_RGB332, | ||
131 | SH_VEU_FMT_RGB444, | ||
132 | SH_VEU_FMT_RGB565, | ||
133 | SH_VEU_FMT_RGB666, | ||
134 | SH_VEU_FMT_RGB24, | ||
135 | }; | ||
136 | |||
137 | #define VGA_WIDTH 640 | ||
138 | #define VGA_HEIGHT 480 | ||
139 | |||
140 | #define DEFAULT_IN_WIDTH VGA_WIDTH | ||
141 | #define DEFAULT_IN_HEIGHT VGA_HEIGHT | ||
142 | #define DEFAULT_IN_FMTIDX SH_VEU_FMT_NV12 | ||
143 | #define DEFAULT_OUT_WIDTH VGA_WIDTH | ||
144 | #define DEFAULT_OUT_HEIGHT VGA_HEIGHT | ||
145 | #define DEFAULT_OUT_FMTIDX SH_VEU_FMT_RGB565 | ||
146 | |||
147 | /* | ||
148 | * Alignment: Y-plane should be 4-byte aligned for NV12 and NV16, and 8-byte | ||
149 | * aligned for NV24. | ||
150 | */ | ||
151 | static const struct sh_veu_format sh_veu_fmt[] = { | ||
152 | [SH_VEU_FMT_NV12] = { .ydepth = 8, .depth = 12, .name = "NV12", .fourcc = V4L2_PIX_FMT_NV12 }, | ||
153 | [SH_VEU_FMT_NV16] = { .ydepth = 8, .depth = 16, .name = "NV16", .fourcc = V4L2_PIX_FMT_NV16 }, | ||
154 | [SH_VEU_FMT_NV24] = { .ydepth = 8, .depth = 24, .name = "NV24", .fourcc = V4L2_PIX_FMT_NV24 }, | ||
155 | [SH_VEU_FMT_RGB332] = { .ydepth = 8, .depth = 8, .name = "RGB332", .fourcc = V4L2_PIX_FMT_RGB332 }, | ||
156 | [SH_VEU_FMT_RGB444] = { .ydepth = 16, .depth = 16, .name = "RGB444", .fourcc = V4L2_PIX_FMT_RGB444 }, | ||
157 | [SH_VEU_FMT_RGB565] = { .ydepth = 16, .depth = 16, .name = "RGB565", .fourcc = V4L2_PIX_FMT_RGB565 }, | ||
158 | [SH_VEU_FMT_RGB666] = { .ydepth = 32, .depth = 32, .name = "BGR666", .fourcc = V4L2_PIX_FMT_BGR666 }, | ||
159 | [SH_VEU_FMT_RGB24] = { .ydepth = 24, .depth = 24, .name = "RGB24", .fourcc = V4L2_PIX_FMT_RGB24 }, | ||
160 | }; | ||
161 | |||
162 | #define DEFAULT_IN_VFMT (struct sh_veu_vfmt){ \ | ||
163 | .frame = { \ | ||
164 | .width = VGA_WIDTH, \ | ||
165 | .height = VGA_HEIGHT, \ | ||
166 | }, \ | ||
167 | .bytesperline = (VGA_WIDTH * sh_veu_fmt[DEFAULT_IN_FMTIDX].ydepth) >> 3, \ | ||
168 | .fmt = &sh_veu_fmt[DEFAULT_IN_FMTIDX], \ | ||
169 | } | ||
170 | |||
171 | #define DEFAULT_OUT_VFMT (struct sh_veu_vfmt){ \ | ||
172 | .frame = { \ | ||
173 | .width = VGA_WIDTH, \ | ||
174 | .height = VGA_HEIGHT, \ | ||
175 | }, \ | ||
176 | .bytesperline = (VGA_WIDTH * sh_veu_fmt[DEFAULT_OUT_FMTIDX].ydepth) >> 3, \ | ||
177 | .fmt = &sh_veu_fmt[DEFAULT_OUT_FMTIDX], \ | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | * TODO: add support for further output formats: | ||
182 | * SH_VEU_FMT_NV12, | ||
183 | * SH_VEU_FMT_NV16, | ||
184 | * SH_VEU_FMT_NV24, | ||
185 | * SH_VEU_FMT_RGB332, | ||
186 | * SH_VEU_FMT_RGB444, | ||
187 | * SH_VEU_FMT_RGB666, | ||
188 | * SH_VEU_FMT_RGB24, | ||
189 | */ | ||
190 | |||
191 | static const int sh_veu_fmt_out[] = { | ||
192 | SH_VEU_FMT_RGB565, | ||
193 | }; | ||
194 | |||
195 | /* | ||
196 | * TODO: add support for further input formats: | ||
197 | * SH_VEU_FMT_NV16, | ||
198 | * SH_VEU_FMT_NV24, | ||
199 | * SH_VEU_FMT_RGB565, | ||
200 | * SH_VEU_FMT_RGB666, | ||
201 | * SH_VEU_FMT_RGB24, | ||
202 | */ | ||
203 | static const int sh_veu_fmt_in[] = { | ||
204 | SH_VEU_FMT_NV12, | ||
205 | }; | ||
206 | |||
207 | static enum v4l2_colorspace sh_veu_4cc2cspace(u32 fourcc) | ||
208 | { | ||
209 | switch (fourcc) { | ||
210 | default: | ||
211 | BUG(); | ||
212 | case V4L2_PIX_FMT_NV12: | ||
213 | case V4L2_PIX_FMT_NV16: | ||
214 | case V4L2_PIX_FMT_NV24: | ||
215 | return V4L2_COLORSPACE_JPEG; | ||
216 | case V4L2_PIX_FMT_RGB332: | ||
217 | case V4L2_PIX_FMT_RGB444: | ||
218 | case V4L2_PIX_FMT_RGB565: | ||
219 | case V4L2_PIX_FMT_BGR666: | ||
220 | case V4L2_PIX_FMT_RGB24: | ||
221 | return V4L2_COLORSPACE_SRGB; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static u32 sh_veu_reg_read(struct sh_veu_dev *veu, unsigned int reg) | ||
226 | { | ||
227 | return ioread32(veu->base + reg); | ||
228 | } | ||
229 | |||
230 | static void sh_veu_reg_write(struct sh_veu_dev *veu, unsigned int reg, | ||
231 | u32 value) | ||
232 | { | ||
233 | iowrite32(value, veu->base + reg); | ||
234 | } | ||
235 | |||
236 | /* ========== mem2mem callbacks ========== */ | ||
237 | |||
238 | static void sh_veu_job_abort(void *priv) | ||
239 | { | ||
240 | struct sh_veu_dev *veu = priv; | ||
241 | |||
242 | /* Will cancel the transaction in the next interrupt handler */ | ||
243 | veu->aborting = true; | ||
244 | } | ||
245 | |||
246 | static void sh_veu_lock(void *priv) | ||
247 | { | ||
248 | struct sh_veu_dev *veu = priv; | ||
249 | |||
250 | mutex_lock(&veu->fop_lock); | ||
251 | } | ||
252 | |||
253 | static void sh_veu_unlock(void *priv) | ||
254 | { | ||
255 | struct sh_veu_dev *veu = priv; | ||
256 | |||
257 | mutex_unlock(&veu->fop_lock); | ||
258 | } | ||
259 | |||
260 | static void sh_veu_process(struct sh_veu_dev *veu, | ||
261 | struct vb2_buffer *src_buf, | ||
262 | struct vb2_buffer *dst_buf) | ||
263 | { | ||
264 | dma_addr_t addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); | ||
265 | |||
266 | sh_veu_reg_write(veu, VEU_DAYR, addr + veu->vfmt_out.offset_y); | ||
267 | sh_veu_reg_write(veu, VEU_DACR, veu->vfmt_out.offset_c ? | ||
268 | addr + veu->vfmt_out.offset_c : 0); | ||
269 | dev_dbg(veu->dev, "%s(): dst base %lx, y: %x, c: %x\n", __func__, | ||
270 | (unsigned long)addr, | ||
271 | veu->vfmt_out.offset_y, veu->vfmt_out.offset_c); | ||
272 | |||
273 | addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); | ||
274 | sh_veu_reg_write(veu, VEU_SAYR, addr + veu->vfmt_in.offset_y); | ||
275 | sh_veu_reg_write(veu, VEU_SACR, veu->vfmt_in.offset_c ? | ||
276 | addr + veu->vfmt_in.offset_c : 0); | ||
277 | dev_dbg(veu->dev, "%s(): src base %lx, y: %x, c: %x\n", __func__, | ||
278 | (unsigned long)addr, | ||
279 | veu->vfmt_in.offset_y, veu->vfmt_in.offset_c); | ||
280 | |||
281 | sh_veu_reg_write(veu, VEU_STR, 1); | ||
282 | |||
283 | sh_veu_reg_write(veu, VEU_EIER, 1); /* enable interrupt in VEU */ | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * sh_veu_device_run() - prepares and starts the device | ||
288 | * | ||
289 | * This will be called by the framework when it decides to schedule a particular | ||
290 | * instance. | ||
291 | */ | ||
292 | static void sh_veu_device_run(void *priv) | ||
293 | { | ||
294 | struct sh_veu_dev *veu = priv; | ||
295 | struct vb2_buffer *src_buf, *dst_buf; | ||
296 | |||
297 | src_buf = v4l2_m2m_next_src_buf(veu->m2m_ctx); | ||
298 | dst_buf = v4l2_m2m_next_dst_buf(veu->m2m_ctx); | ||
299 | |||
300 | if (src_buf && dst_buf) | ||
301 | sh_veu_process(veu, src_buf, dst_buf); | ||
302 | } | ||
303 | |||
304 | /* ========== video ioctls ========== */ | ||
305 | |||
306 | static bool sh_veu_is_streamer(struct sh_veu_dev *veu, struct sh_veu_file *veu_file, | ||
307 | enum v4l2_buf_type type) | ||
308 | { | ||
309 | return (type == V4L2_BUF_TYPE_VIDEO_CAPTURE && | ||
310 | veu_file == veu->capture) || | ||
311 | (type == V4L2_BUF_TYPE_VIDEO_OUTPUT && | ||
312 | veu_file == veu->output); | ||
313 | } | ||
314 | |||
315 | static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq, | ||
316 | struct vb2_queue *dst_vq); | ||
317 | |||
318 | /* | ||
319 | * It is not unusual to have video nodes open()ed multiple times. While some | ||
320 | * V4L2 operations are non-intrusive, like querying formats and various | ||
321 | * parameters, others, like setting formats, starting and stopping streaming, | ||
322 | * queuing and dequeuing buffers, directly affect hardware configuration and / | ||
323 | * or execution. This function verifies availability of the requested interface | ||
324 | * and, if available, reserves it for the requesting user. | ||
325 | */ | ||
326 | static int sh_veu_stream_init(struct sh_veu_dev *veu, struct sh_veu_file *veu_file, | ||
327 | enum v4l2_buf_type type) | ||
328 | { | ||
329 | struct sh_veu_file **stream; | ||
330 | |||
331 | switch (type) { | ||
332 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
333 | stream = &veu->capture; | ||
334 | break; | ||
335 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
336 | stream = &veu->output; | ||
337 | break; | ||
338 | default: | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | |||
342 | if (*stream == veu_file) | ||
343 | return 0; | ||
344 | |||
345 | if (*stream) | ||
346 | return -EBUSY; | ||
347 | |||
348 | *stream = veu_file; | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int sh_veu_context_init(struct sh_veu_dev *veu) | ||
354 | { | ||
355 | if (veu->m2m_ctx) | ||
356 | return 0; | ||
357 | |||
358 | veu->m2m_ctx = v4l2_m2m_ctx_init(veu->m2m_dev, veu, | ||
359 | sh_veu_queue_init); | ||
360 | |||
361 | if (IS_ERR(veu->m2m_ctx)) | ||
362 | return PTR_ERR(veu->m2m_ctx); | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int sh_veu_querycap(struct file *file, void *priv, | ||
368 | struct v4l2_capability *cap) | ||
369 | { | ||
370 | strlcpy(cap->driver, "sh-veu", sizeof(cap->driver)); | ||
371 | strlcpy(cap->card, "sh-mobile VEU", sizeof(cap->card)); | ||
372 | strlcpy(cap->bus_info, "platform:sh-veu", sizeof(cap->bus_info)); | ||
373 | cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; | ||
374 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | ||
375 | |||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static int sh_veu_enum_fmt(struct v4l2_fmtdesc *f, const int *fmt, int fmt_num) | ||
380 | { | ||
381 | if (f->index >= fmt_num) | ||
382 | return -EINVAL; | ||
383 | |||
384 | strlcpy(f->description, sh_veu_fmt[fmt[f->index]].name, sizeof(f->description)); | ||
385 | f->pixelformat = sh_veu_fmt[fmt[f->index]].fourcc; | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static int sh_veu_enum_fmt_vid_cap(struct file *file, void *priv, | ||
390 | struct v4l2_fmtdesc *f) | ||
391 | { | ||
392 | return sh_veu_enum_fmt(f, sh_veu_fmt_out, ARRAY_SIZE(sh_veu_fmt_out)); | ||
393 | } | ||
394 | |||
395 | static int sh_veu_enum_fmt_vid_out(struct file *file, void *priv, | ||
396 | struct v4l2_fmtdesc *f) | ||
397 | { | ||
398 | return sh_veu_enum_fmt(f, sh_veu_fmt_in, ARRAY_SIZE(sh_veu_fmt_in)); | ||
399 | } | ||
400 | |||
401 | static struct sh_veu_vfmt *sh_veu_get_vfmt(struct sh_veu_dev *veu, | ||
402 | enum v4l2_buf_type type) | ||
403 | { | ||
404 | switch (type) { | ||
405 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
406 | return &veu->vfmt_out; | ||
407 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
408 | return &veu->vfmt_in; | ||
409 | default: | ||
410 | return NULL; | ||
411 | } | ||
412 | } | ||
413 | |||
414 | static int sh_veu_g_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f) | ||
415 | { | ||
416 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
417 | struct sh_veu_dev *veu = veu_file->veu_dev; | ||
418 | struct sh_veu_vfmt *vfmt; | ||
419 | |||
420 | vfmt = sh_veu_get_vfmt(veu, f->type); | ||
421 | |||
422 | pix->width = vfmt->frame.width; | ||
423 | pix->height = vfmt->frame.height; | ||
424 | pix->field = V4L2_FIELD_NONE; | ||
425 | pix->pixelformat = vfmt->fmt->fourcc; | ||
426 | pix->colorspace = sh_veu_4cc2cspace(pix->pixelformat); | ||
427 | pix->bytesperline = vfmt->bytesperline; | ||
428 | pix->sizeimage = vfmt->bytesperline * pix->height * | ||
429 | vfmt->fmt->depth / vfmt->fmt->ydepth; | ||
430 | pix->priv = 0; | ||
431 | dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__, | ||
432 | f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat); | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static int sh_veu_g_fmt_vid_out(struct file *file, void *priv, | ||
438 | struct v4l2_format *f) | ||
439 | { | ||
440 | return sh_veu_g_fmt(priv, f); | ||
441 | } | ||
442 | |||
443 | static int sh_veu_g_fmt_vid_cap(struct file *file, void *priv, | ||
444 | struct v4l2_format *f) | ||
445 | { | ||
446 | return sh_veu_g_fmt(priv, f); | ||
447 | } | ||
448 | |||
449 | static int sh_veu_try_fmt(struct v4l2_format *f, const struct sh_veu_format *fmt) | ||
450 | { | ||
451 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
452 | unsigned int y_bytes_used; | ||
453 | |||
454 | /* | ||
455 | * V4L2 specification suggests, that the driver should correct the | ||
456 | * format struct if any of the dimensions is unsupported | ||
457 | */ | ||
458 | switch (pix->field) { | ||
459 | default: | ||
460 | case V4L2_FIELD_ANY: | ||
461 | pix->field = V4L2_FIELD_NONE; | ||
462 | /* fall through: continue handling V4L2_FIELD_NONE */ | ||
463 | case V4L2_FIELD_NONE: | ||
464 | break; | ||
465 | } | ||
466 | |||
467 | v4l_bound_align_image(&pix->width, MIN_W, MAX_W, ALIGN_W, | ||
468 | &pix->height, MIN_H, MAX_H, 0, 0); | ||
469 | |||
470 | y_bytes_used = (pix->width * fmt->ydepth) >> 3; | ||
471 | |||
472 | if (pix->bytesperline < y_bytes_used) | ||
473 | pix->bytesperline = y_bytes_used; | ||
474 | pix->sizeimage = pix->height * pix->bytesperline * fmt->depth / fmt->ydepth; | ||
475 | |||
476 | pix->pixelformat = fmt->fourcc; | ||
477 | pix->colorspace = sh_veu_4cc2cspace(pix->pixelformat); | ||
478 | pix->priv = 0; | ||
479 | |||
480 | pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage); | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static const struct sh_veu_format *sh_veu_find_fmt(const struct v4l2_format *f) | ||
486 | { | ||
487 | const int *fmt; | ||
488 | int i, n, dflt; | ||
489 | |||
490 | pr_debug("%s(%d;%d)\n", __func__, f->type, f->fmt.pix.field); | ||
491 | |||
492 | switch (f->type) { | ||
493 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
494 | fmt = sh_veu_fmt_out; | ||
495 | n = ARRAY_SIZE(sh_veu_fmt_out); | ||
496 | dflt = DEFAULT_OUT_FMTIDX; | ||
497 | break; | ||
498 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
499 | default: | ||
500 | fmt = sh_veu_fmt_in; | ||
501 | n = ARRAY_SIZE(sh_veu_fmt_in); | ||
502 | dflt = DEFAULT_IN_FMTIDX; | ||
503 | break; | ||
504 | } | ||
505 | |||
506 | for (i = 0; i < n; i++) | ||
507 | if (sh_veu_fmt[fmt[i]].fourcc == f->fmt.pix.pixelformat) | ||
508 | return &sh_veu_fmt[fmt[i]]; | ||
509 | |||
510 | return &sh_veu_fmt[dflt]; | ||
511 | } | ||
512 | |||
513 | static int sh_veu_try_fmt_vid_cap(struct file *file, void *priv, | ||
514 | struct v4l2_format *f) | ||
515 | { | ||
516 | const struct sh_veu_format *fmt; | ||
517 | |||
518 | fmt = sh_veu_find_fmt(f); | ||
519 | if (!fmt) | ||
520 | /* wrong buffer type */ | ||
521 | return -EINVAL; | ||
522 | |||
523 | return sh_veu_try_fmt(f, fmt); | ||
524 | } | ||
525 | |||
526 | static int sh_veu_try_fmt_vid_out(struct file *file, void *priv, | ||
527 | struct v4l2_format *f) | ||
528 | { | ||
529 | const struct sh_veu_format *fmt; | ||
530 | |||
531 | fmt = sh_veu_find_fmt(f); | ||
532 | if (!fmt) | ||
533 | /* wrong buffer type */ | ||
534 | return -EINVAL; | ||
535 | |||
536 | return sh_veu_try_fmt(f, fmt); | ||
537 | } | ||
538 | |||
539 | static void sh_veu_colour_offset(struct sh_veu_dev *veu, struct sh_veu_vfmt *vfmt) | ||
540 | { | ||
541 | /* dst_left and dst_top validity will be verified in CROP / COMPOSE */ | ||
542 | unsigned int left = vfmt->frame.left & ~0x03; | ||
543 | unsigned int top = vfmt->frame.top; | ||
544 | dma_addr_t offset = ((left * veu->vfmt_out.fmt->depth) >> 3) + | ||
545 | top * veu->vfmt_out.bytesperline; | ||
546 | unsigned int y_line; | ||
547 | |||
548 | vfmt->offset_y = offset; | ||
549 | |||
550 | switch (vfmt->fmt->fourcc) { | ||
551 | case V4L2_PIX_FMT_NV12: | ||
552 | case V4L2_PIX_FMT_NV16: | ||
553 | case V4L2_PIX_FMT_NV24: | ||
554 | y_line = ALIGN(vfmt->frame.width, 16); | ||
555 | vfmt->offset_c = offset + y_line * vfmt->frame.height; | ||
556 | break; | ||
557 | case V4L2_PIX_FMT_RGB332: | ||
558 | case V4L2_PIX_FMT_RGB444: | ||
559 | case V4L2_PIX_FMT_RGB565: | ||
560 | case V4L2_PIX_FMT_BGR666: | ||
561 | case V4L2_PIX_FMT_RGB24: | ||
562 | vfmt->offset_c = 0; | ||
563 | break; | ||
564 | default: | ||
565 | BUG(); | ||
566 | } | ||
567 | } | ||
568 | |||
569 | static int sh_veu_s_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f) | ||
570 | { | ||
571 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
572 | struct sh_veu_dev *veu = veu_file->veu_dev; | ||
573 | struct sh_veu_vfmt *vfmt; | ||
574 | struct vb2_queue *vq; | ||
575 | int ret = sh_veu_context_init(veu); | ||
576 | if (ret < 0) | ||
577 | return ret; | ||
578 | |||
579 | vq = v4l2_m2m_get_vq(veu->m2m_ctx, f->type); | ||
580 | if (!vq) | ||
581 | return -EINVAL; | ||
582 | |||
583 | if (vb2_is_busy(vq)) { | ||
584 | v4l2_err(&veu_file->veu_dev->v4l2_dev, "%s queue busy\n", __func__); | ||
585 | return -EBUSY; | ||
586 | } | ||
587 | |||
588 | vfmt = sh_veu_get_vfmt(veu, f->type); | ||
589 | /* called after try_fmt(), hence vfmt != NULL. Implicit BUG_ON() below */ | ||
590 | |||
591 | vfmt->fmt = sh_veu_find_fmt(f); | ||
592 | /* vfmt->fmt != NULL following the same argument as above */ | ||
593 | vfmt->frame.width = pix->width; | ||
594 | vfmt->frame.height = pix->height; | ||
595 | vfmt->bytesperline = pix->bytesperline; | ||
596 | |||
597 | sh_veu_colour_offset(veu, vfmt); | ||
598 | |||
599 | /* | ||
600 | * We could also verify and require configuration only if any parameters | ||
601 | * actually have changed, but it is unlikely, that the user requests the | ||
602 | * same configuration several times without closing the device. | ||
603 | */ | ||
604 | veu_file->cfg_needed = true; | ||
605 | |||
606 | dev_dbg(veu->dev, | ||
607 | "Setting format for type %d, wxh: %dx%d, fmt: %x\n", | ||
608 | f->type, pix->width, pix->height, vfmt->fmt->fourcc); | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | static int sh_veu_s_fmt_vid_cap(struct file *file, void *priv, | ||
614 | struct v4l2_format *f) | ||
615 | { | ||
616 | int ret = sh_veu_try_fmt_vid_cap(file, priv, f); | ||
617 | if (ret) | ||
618 | return ret; | ||
619 | |||
620 | return sh_veu_s_fmt(priv, f); | ||
621 | } | ||
622 | |||
623 | static int sh_veu_s_fmt_vid_out(struct file *file, void *priv, | ||
624 | struct v4l2_format *f) | ||
625 | { | ||
626 | int ret = sh_veu_try_fmt_vid_out(file, priv, f); | ||
627 | if (ret) | ||
628 | return ret; | ||
629 | |||
630 | return sh_veu_s_fmt(priv, f); | ||
631 | } | ||
632 | |||
633 | static int sh_veu_reqbufs(struct file *file, void *priv, | ||
634 | struct v4l2_requestbuffers *reqbufs) | ||
635 | { | ||
636 | struct sh_veu_file *veu_file = priv; | ||
637 | struct sh_veu_dev *veu = veu_file->veu_dev; | ||
638 | int ret = sh_veu_context_init(veu); | ||
639 | if (ret < 0) | ||
640 | return ret; | ||
641 | |||
642 | ret = sh_veu_stream_init(veu, veu_file, reqbufs->type); | ||
643 | if (ret < 0) | ||
644 | return ret; | ||
645 | |||
646 | return v4l2_m2m_reqbufs(file, veu->m2m_ctx, reqbufs); | ||
647 | } | ||
648 | |||
649 | static int sh_veu_querybuf(struct file *file, void *priv, | ||
650 | struct v4l2_buffer *buf) | ||
651 | { | ||
652 | struct sh_veu_file *veu_file = priv; | ||
653 | |||
654 | if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type)) | ||
655 | return -EBUSY; | ||
656 | |||
657 | return v4l2_m2m_querybuf(file, veu_file->veu_dev->m2m_ctx, buf); | ||
658 | } | ||
659 | |||
660 | static int sh_veu_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
661 | { | ||
662 | struct sh_veu_file *veu_file = priv; | ||
663 | |||
664 | dev_dbg(veu_file->veu_dev->dev, "%s(%d)\n", __func__, buf->type); | ||
665 | if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type)) | ||
666 | return -EBUSY; | ||
667 | |||
668 | return v4l2_m2m_qbuf(file, veu_file->veu_dev->m2m_ctx, buf); | ||
669 | } | ||
670 | |||
671 | static int sh_veu_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
672 | { | ||
673 | struct sh_veu_file *veu_file = priv; | ||
674 | |||
675 | dev_dbg(veu_file->veu_dev->dev, "%s(%d)\n", __func__, buf->type); | ||
676 | if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type)) | ||
677 | return -EBUSY; | ||
678 | |||
679 | return v4l2_m2m_dqbuf(file, veu_file->veu_dev->m2m_ctx, buf); | ||
680 | } | ||
681 | |||
682 | static void sh_veu_calc_scale(struct sh_veu_dev *veu, | ||
683 | int size_in, int size_out, int crop_out, | ||
684 | u32 *mant, u32 *frac, u32 *rep) | ||
685 | { | ||
686 | u32 fixpoint; | ||
687 | |||
688 | /* calculate FRAC and MANT */ | ||
689 | *rep = *mant = *frac = 0; | ||
690 | |||
691 | if (size_in == size_out) { | ||
692 | if (crop_out != size_out) | ||
693 | *mant = 1; /* needed for cropping */ | ||
694 | return; | ||
695 | } | ||
696 | |||
697 | /* VEU2H special upscale */ | ||
698 | if (veu->is_2h && size_out > size_in) { | ||
699 | u32 fixpoint = (4096 * size_in) / size_out; | ||
700 | *mant = fixpoint / 4096; | ||
701 | *frac = (fixpoint - (*mant * 4096)) & ~0x07; | ||
702 | |||
703 | switch (*frac) { | ||
704 | case 0x800: | ||
705 | *rep = 1; | ||
706 | break; | ||
707 | case 0x400: | ||
708 | *rep = 3; | ||
709 | break; | ||
710 | case 0x200: | ||
711 | *rep = 7; | ||
712 | break; | ||
713 | } | ||
714 | if (*rep) | ||
715 | return; | ||
716 | } | ||
717 | |||
718 | fixpoint = (4096 * (size_in - 1)) / (size_out + 1); | ||
719 | *mant = fixpoint / 4096; | ||
720 | *frac = fixpoint - (*mant * 4096); | ||
721 | |||
722 | if (*frac & 0x07) { | ||
723 | /* | ||
724 | * FIXME: do we really have to round down twice in the | ||
725 | * up-scaling case? | ||
726 | */ | ||
727 | *frac &= ~0x07; | ||
728 | if (size_out > size_in) | ||
729 | *frac -= 8; /* round down if scaling up */ | ||
730 | else | ||
731 | *frac += 8; /* round up if scaling down */ | ||
732 | } | ||
733 | } | ||
734 | |||
735 | static unsigned long sh_veu_scale_v(struct sh_veu_dev *veu, | ||
736 | int size_in, int size_out, int crop_out) | ||
737 | { | ||
738 | u32 mant, frac, value, rep; | ||
739 | |||
740 | sh_veu_calc_scale(veu, size_in, size_out, crop_out, &mant, &frac, &rep); | ||
741 | |||
742 | /* set scale */ | ||
743 | value = (sh_veu_reg_read(veu, VEU_RFCR) & ~0xffff0000) | | ||
744 | (((mant << 12) | frac) << 16); | ||
745 | |||
746 | sh_veu_reg_write(veu, VEU_RFCR, value); | ||
747 | |||
748 | /* set clip */ | ||
749 | value = (sh_veu_reg_read(veu, VEU_RFSR) & ~0xffff0000) | | ||
750 | (((rep << 12) | crop_out) << 16); | ||
751 | |||
752 | sh_veu_reg_write(veu, VEU_RFSR, value); | ||
753 | |||
754 | return ALIGN((size_in * crop_out) / size_out, 4); | ||
755 | } | ||
756 | |||
757 | static unsigned long sh_veu_scale_h(struct sh_veu_dev *veu, | ||
758 | int size_in, int size_out, int crop_out) | ||
759 | { | ||
760 | u32 mant, frac, value, rep; | ||
761 | |||
762 | sh_veu_calc_scale(veu, size_in, size_out, crop_out, &mant, &frac, &rep); | ||
763 | |||
764 | /* set scale */ | ||
765 | value = (sh_veu_reg_read(veu, VEU_RFCR) & ~0xffff) | | ||
766 | (mant << 12) | frac; | ||
767 | |||
768 | sh_veu_reg_write(veu, VEU_RFCR, value); | ||
769 | |||
770 | /* set clip */ | ||
771 | value = (sh_veu_reg_read(veu, VEU_RFSR) & ~0xffff) | | ||
772 | (rep << 12) | crop_out; | ||
773 | |||
774 | sh_veu_reg_write(veu, VEU_RFSR, value); | ||
775 | |||
776 | return ALIGN((size_in * crop_out) / size_out, 4); | ||
777 | } | ||
778 | |||
779 | static void sh_veu_configure(struct sh_veu_dev *veu) | ||
780 | { | ||
781 | u32 src_width, src_stride, src_height; | ||
782 | u32 dst_width, dst_stride, dst_height; | ||
783 | u32 real_w, real_h; | ||
784 | |||
785 | /* reset VEU */ | ||
786 | sh_veu_reg_write(veu, VEU_BSRR, 0x100); | ||
787 | |||
788 | src_width = veu->vfmt_in.frame.width; | ||
789 | src_height = veu->vfmt_in.frame.height; | ||
790 | src_stride = ALIGN(veu->vfmt_in.frame.width, 16); | ||
791 | |||
792 | dst_width = real_w = veu->vfmt_out.frame.width; | ||
793 | dst_height = real_h = veu->vfmt_out.frame.height; | ||
794 | /* Datasheet is unclear - whether it's always number of bytes or not */ | ||
795 | dst_stride = veu->vfmt_out.bytesperline; | ||
796 | |||
797 | /* | ||
798 | * So far real_w == dst_width && real_h == dst_height, but it wasn't | ||
799 | * necessarily the case in the original vidix driver, so, it may change | ||
800 | * here in the future too. | ||
801 | */ | ||
802 | src_width = sh_veu_scale_h(veu, src_width, real_w, dst_width); | ||
803 | src_height = sh_veu_scale_v(veu, src_height, real_h, dst_height); | ||
804 | |||
805 | sh_veu_reg_write(veu, VEU_SWR, src_stride); | ||
806 | sh_veu_reg_write(veu, VEU_SSR, src_width | (src_height << 16)); | ||
807 | sh_veu_reg_write(veu, VEU_BSSR, 0); /* not using bundle mode */ | ||
808 | |||
809 | sh_veu_reg_write(veu, VEU_EDWR, dst_stride); | ||
810 | sh_veu_reg_write(veu, VEU_DACR, 0); /* unused for RGB */ | ||
811 | |||
812 | sh_veu_reg_write(veu, VEU_SWPR, 0x67); | ||
813 | sh_veu_reg_write(veu, VEU_TRCR, (6 << 16) | (0 << 14) | 2 | 4); | ||
814 | |||
815 | if (veu->is_2h) { | ||
816 | sh_veu_reg_write(veu, VEU_MCR00, 0x0cc5); | ||
817 | sh_veu_reg_write(veu, VEU_MCR01, 0x0950); | ||
818 | sh_veu_reg_write(veu, VEU_MCR02, 0x0000); | ||
819 | |||
820 | sh_veu_reg_write(veu, VEU_MCR10, 0x397f); | ||
821 | sh_veu_reg_write(veu, VEU_MCR11, 0x0950); | ||
822 | sh_veu_reg_write(veu, VEU_MCR12, 0x3ccd); | ||
823 | |||
824 | sh_veu_reg_write(veu, VEU_MCR20, 0x0000); | ||
825 | sh_veu_reg_write(veu, VEU_MCR21, 0x0950); | ||
826 | sh_veu_reg_write(veu, VEU_MCR22, 0x1023); | ||
827 | |||
828 | sh_veu_reg_write(veu, VEU_COFFR, 0x00800010); | ||
829 | } | ||
830 | } | ||
831 | |||
832 | static int sh_veu_streamon(struct file *file, void *priv, | ||
833 | enum v4l2_buf_type type) | ||
834 | { | ||
835 | struct sh_veu_file *veu_file = priv; | ||
836 | |||
837 | if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, type)) | ||
838 | return -EBUSY; | ||
839 | |||
840 | if (veu_file->cfg_needed) { | ||
841 | struct sh_veu_dev *veu = veu_file->veu_dev; | ||
842 | veu_file->cfg_needed = false; | ||
843 | sh_veu_configure(veu_file->veu_dev); | ||
844 | veu->xaction = 0; | ||
845 | veu->aborting = false; | ||
846 | } | ||
847 | |||
848 | return v4l2_m2m_streamon(file, veu_file->veu_dev->m2m_ctx, type); | ||
849 | } | ||
850 | |||
851 | static int sh_veu_streamoff(struct file *file, void *priv, | ||
852 | enum v4l2_buf_type type) | ||
853 | { | ||
854 | struct sh_veu_file *veu_file = priv; | ||
855 | |||
856 | if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, type)) | ||
857 | return -EBUSY; | ||
858 | |||
859 | return v4l2_m2m_streamoff(file, veu_file->veu_dev->m2m_ctx, type); | ||
860 | } | ||
861 | |||
862 | static const struct v4l2_ioctl_ops sh_veu_ioctl_ops = { | ||
863 | .vidioc_querycap = sh_veu_querycap, | ||
864 | |||
865 | .vidioc_enum_fmt_vid_cap = sh_veu_enum_fmt_vid_cap, | ||
866 | .vidioc_g_fmt_vid_cap = sh_veu_g_fmt_vid_cap, | ||
867 | .vidioc_try_fmt_vid_cap = sh_veu_try_fmt_vid_cap, | ||
868 | .vidioc_s_fmt_vid_cap = sh_veu_s_fmt_vid_cap, | ||
869 | |||
870 | .vidioc_enum_fmt_vid_out = sh_veu_enum_fmt_vid_out, | ||
871 | .vidioc_g_fmt_vid_out = sh_veu_g_fmt_vid_out, | ||
872 | .vidioc_try_fmt_vid_out = sh_veu_try_fmt_vid_out, | ||
873 | .vidioc_s_fmt_vid_out = sh_veu_s_fmt_vid_out, | ||
874 | |||
875 | .vidioc_reqbufs = sh_veu_reqbufs, | ||
876 | .vidioc_querybuf = sh_veu_querybuf, | ||
877 | |||
878 | .vidioc_qbuf = sh_veu_qbuf, | ||
879 | .vidioc_dqbuf = sh_veu_dqbuf, | ||
880 | |||
881 | .vidioc_streamon = sh_veu_streamon, | ||
882 | .vidioc_streamoff = sh_veu_streamoff, | ||
883 | }; | ||
884 | |||
885 | /* ========== Queue operations ========== */ | ||
886 | |||
887 | static int sh_veu_queue_setup(struct vb2_queue *vq, | ||
888 | const struct v4l2_format *f, | ||
889 | unsigned int *nbuffers, unsigned int *nplanes, | ||
890 | unsigned int sizes[], void *alloc_ctxs[]) | ||
891 | { | ||
892 | struct sh_veu_dev *veu = vb2_get_drv_priv(vq); | ||
893 | struct sh_veu_vfmt *vfmt; | ||
894 | unsigned int size, count = *nbuffers; | ||
895 | |||
896 | if (f) { | ||
897 | const struct v4l2_pix_format *pix = &f->fmt.pix; | ||
898 | const struct sh_veu_format *fmt = sh_veu_find_fmt(f); | ||
899 | struct v4l2_format ftmp = *f; | ||
900 | |||
901 | if (fmt->fourcc != pix->pixelformat) | ||
902 | return -EINVAL; | ||
903 | sh_veu_try_fmt(&ftmp, fmt); | ||
904 | if (ftmp.fmt.pix.width != pix->width || | ||
905 | ftmp.fmt.pix.height != pix->height) | ||
906 | return -EINVAL; | ||
907 | size = pix->bytesperline ? pix->bytesperline * pix->height : | ||
908 | pix->width * pix->height * fmt->depth >> 3; | ||
909 | } else { | ||
910 | vfmt = sh_veu_get_vfmt(veu, vq->type); | ||
911 | size = vfmt->bytesperline * vfmt->frame.height; | ||
912 | } | ||
913 | |||
914 | if (count < 2) | ||
915 | *nbuffers = count = 2; | ||
916 | |||
917 | if (size * count > VIDEO_MEM_LIMIT) { | ||
918 | count = VIDEO_MEM_LIMIT / size; | ||
919 | *nbuffers = count; | ||
920 | } | ||
921 | |||
922 | *nplanes = 1; | ||
923 | sizes[0] = size; | ||
924 | alloc_ctxs[0] = veu->alloc_ctx; | ||
925 | |||
926 | dev_dbg(veu->dev, "get %d buffer(s) of size %d each.\n", count, size); | ||
927 | |||
928 | return 0; | ||
929 | } | ||
930 | |||
931 | static int sh_veu_buf_prepare(struct vb2_buffer *vb) | ||
932 | { | ||
933 | struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue); | ||
934 | struct sh_veu_vfmt *vfmt; | ||
935 | unsigned int sizeimage; | ||
936 | |||
937 | vfmt = sh_veu_get_vfmt(veu, vb->vb2_queue->type); | ||
938 | sizeimage = vfmt->bytesperline * vfmt->frame.height * | ||
939 | vfmt->fmt->depth / vfmt->fmt->ydepth; | ||
940 | |||
941 | if (vb2_plane_size(vb, 0) < sizeimage) { | ||
942 | dev_dbg(veu->dev, "%s data will not fit into plane (%lu < %u)\n", | ||
943 | __func__, vb2_plane_size(vb, 0), sizeimage); | ||
944 | return -EINVAL; | ||
945 | } | ||
946 | |||
947 | vb2_set_plane_payload(vb, 0, sizeimage); | ||
948 | |||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | static void sh_veu_buf_queue(struct vb2_buffer *vb) | ||
953 | { | ||
954 | struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue); | ||
955 | dev_dbg(veu->dev, "%s(%d)\n", __func__, vb->v4l2_buf.type); | ||
956 | v4l2_m2m_buf_queue(veu->m2m_ctx, vb); | ||
957 | } | ||
958 | |||
959 | static void sh_veu_wait_prepare(struct vb2_queue *q) | ||
960 | { | ||
961 | sh_veu_unlock(vb2_get_drv_priv(q)); | ||
962 | } | ||
963 | |||
964 | static void sh_veu_wait_finish(struct vb2_queue *q) | ||
965 | { | ||
966 | sh_veu_lock(vb2_get_drv_priv(q)); | ||
967 | } | ||
968 | |||
969 | static const struct vb2_ops sh_veu_qops = { | ||
970 | .queue_setup = sh_veu_queue_setup, | ||
971 | .buf_prepare = sh_veu_buf_prepare, | ||
972 | .buf_queue = sh_veu_buf_queue, | ||
973 | .wait_prepare = sh_veu_wait_prepare, | ||
974 | .wait_finish = sh_veu_wait_finish, | ||
975 | }; | ||
976 | |||
977 | static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq, | ||
978 | struct vb2_queue *dst_vq) | ||
979 | { | ||
980 | int ret; | ||
981 | |||
982 | memset(src_vq, 0, sizeof(*src_vq)); | ||
983 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
984 | src_vq->io_modes = VB2_MMAP | VB2_USERPTR; | ||
985 | src_vq->drv_priv = priv; | ||
986 | src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); | ||
987 | src_vq->ops = &sh_veu_qops; | ||
988 | src_vq->mem_ops = &vb2_dma_contig_memops; | ||
989 | |||
990 | ret = vb2_queue_init(src_vq); | ||
991 | if (ret < 0) | ||
992 | return ret; | ||
993 | |||
994 | memset(dst_vq, 0, sizeof(*dst_vq)); | ||
995 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
996 | dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; | ||
997 | dst_vq->drv_priv = priv; | ||
998 | dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); | ||
999 | dst_vq->ops = &sh_veu_qops; | ||
1000 | dst_vq->mem_ops = &vb2_dma_contig_memops; | ||
1001 | |||
1002 | return vb2_queue_init(dst_vq); | ||
1003 | } | ||
1004 | |||
1005 | /* ========== File operations ========== */ | ||
1006 | |||
1007 | static int sh_veu_open(struct file *file) | ||
1008 | { | ||
1009 | struct sh_veu_dev *veu = video_drvdata(file); | ||
1010 | struct sh_veu_file *veu_file; | ||
1011 | |||
1012 | veu_file = kzalloc(sizeof(*veu_file), GFP_KERNEL); | ||
1013 | if (!veu_file) | ||
1014 | return -ENOMEM; | ||
1015 | |||
1016 | veu_file->veu_dev = veu; | ||
1017 | veu_file->cfg_needed = true; | ||
1018 | |||
1019 | file->private_data = veu_file; | ||
1020 | |||
1021 | pm_runtime_get_sync(veu->dev); | ||
1022 | |||
1023 | dev_dbg(veu->dev, "Created instance %p\n", veu_file); | ||
1024 | |||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | static int sh_veu_release(struct file *file) | ||
1029 | { | ||
1030 | struct sh_veu_dev *veu = video_drvdata(file); | ||
1031 | struct sh_veu_file *veu_file = file->private_data; | ||
1032 | |||
1033 | dev_dbg(veu->dev, "Releasing instance %p\n", veu_file); | ||
1034 | |||
1035 | pm_runtime_put(veu->dev); | ||
1036 | |||
1037 | if (veu_file == veu->capture) { | ||
1038 | veu->capture = NULL; | ||
1039 | vb2_queue_release(v4l2_m2m_get_vq(veu->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)); | ||
1040 | } | ||
1041 | |||
1042 | if (veu_file == veu->output) { | ||
1043 | veu->output = NULL; | ||
1044 | vb2_queue_release(v4l2_m2m_get_vq(veu->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT)); | ||
1045 | } | ||
1046 | |||
1047 | if (!veu->output && !veu->capture && veu->m2m_ctx) { | ||
1048 | v4l2_m2m_ctx_release(veu->m2m_ctx); | ||
1049 | veu->m2m_ctx = NULL; | ||
1050 | } | ||
1051 | |||
1052 | kfree(veu_file); | ||
1053 | |||
1054 | return 0; | ||
1055 | } | ||
1056 | |||
1057 | static unsigned int sh_veu_poll(struct file *file, | ||
1058 | struct poll_table_struct *wait) | ||
1059 | { | ||
1060 | struct sh_veu_file *veu_file = file->private_data; | ||
1061 | |||
1062 | return v4l2_m2m_poll(file, veu_file->veu_dev->m2m_ctx, wait); | ||
1063 | } | ||
1064 | |||
1065 | static int sh_veu_mmap(struct file *file, struct vm_area_struct *vma) | ||
1066 | { | ||
1067 | struct sh_veu_file *veu_file = file->private_data; | ||
1068 | |||
1069 | return v4l2_m2m_mmap(file, veu_file->veu_dev->m2m_ctx, vma); | ||
1070 | } | ||
1071 | |||
1072 | static const struct v4l2_file_operations sh_veu_fops = { | ||
1073 | .owner = THIS_MODULE, | ||
1074 | .open = sh_veu_open, | ||
1075 | .release = sh_veu_release, | ||
1076 | .poll = sh_veu_poll, | ||
1077 | .unlocked_ioctl = video_ioctl2, | ||
1078 | .mmap = sh_veu_mmap, | ||
1079 | }; | ||
1080 | |||
1081 | static const struct video_device sh_veu_videodev = { | ||
1082 | .name = "sh-veu", | ||
1083 | .fops = &sh_veu_fops, | ||
1084 | .ioctl_ops = &sh_veu_ioctl_ops, | ||
1085 | .minor = -1, | ||
1086 | .release = video_device_release_empty, | ||
1087 | .vfl_dir = VFL_DIR_M2M, | ||
1088 | }; | ||
1089 | |||
1090 | static const struct v4l2_m2m_ops sh_veu_m2m_ops = { | ||
1091 | .device_run = sh_veu_device_run, | ||
1092 | .job_abort = sh_veu_job_abort, | ||
1093 | }; | ||
1094 | |||
1095 | static irqreturn_t sh_veu_bh(int irq, void *dev_id) | ||
1096 | { | ||
1097 | struct sh_veu_dev *veu = dev_id; | ||
1098 | |||
1099 | if (veu->xaction == MEM2MEM_DEF_TRANSLEN || veu->aborting) { | ||
1100 | v4l2_m2m_job_finish(veu->m2m_dev, veu->m2m_ctx); | ||
1101 | veu->xaction = 0; | ||
1102 | } else { | ||
1103 | sh_veu_device_run(veu); | ||
1104 | } | ||
1105 | |||
1106 | return IRQ_HANDLED; | ||
1107 | } | ||
1108 | |||
1109 | static irqreturn_t sh_veu_isr(int irq, void *dev_id) | ||
1110 | { | ||
1111 | struct sh_veu_dev *veu = dev_id; | ||
1112 | struct vb2_buffer *dst; | ||
1113 | struct vb2_buffer *src; | ||
1114 | u32 status = sh_veu_reg_read(veu, VEU_EVTR); | ||
1115 | |||
1116 | /* bundle read mode not used */ | ||
1117 | if (!(status & 1)) | ||
1118 | return IRQ_NONE; | ||
1119 | |||
1120 | /* disable interrupt in VEU */ | ||
1121 | sh_veu_reg_write(veu, VEU_EIER, 0); | ||
1122 | /* halt operation */ | ||
1123 | sh_veu_reg_write(veu, VEU_STR, 0); | ||
1124 | /* ack int, write 0 to clear bits */ | ||
1125 | sh_veu_reg_write(veu, VEU_EVTR, status & ~1); | ||
1126 | |||
1127 | /* conversion completed */ | ||
1128 | dst = v4l2_m2m_dst_buf_remove(veu->m2m_ctx); | ||
1129 | src = v4l2_m2m_src_buf_remove(veu->m2m_ctx); | ||
1130 | if (!src || !dst) | ||
1131 | return IRQ_NONE; | ||
1132 | |||
1133 | spin_lock(&veu->lock); | ||
1134 | v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); | ||
1135 | v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); | ||
1136 | spin_unlock(&veu->lock); | ||
1137 | |||
1138 | veu->xaction++; | ||
1139 | |||
1140 | if (!veu->aborting) | ||
1141 | return IRQ_WAKE_THREAD; | ||
1142 | |||
1143 | return IRQ_HANDLED; | ||
1144 | } | ||
1145 | |||
1146 | static int sh_veu_probe(struct platform_device *pdev) | ||
1147 | { | ||
1148 | struct sh_veu_dev *veu; | ||
1149 | struct resource *reg_res; | ||
1150 | struct video_device *vdev; | ||
1151 | int irq, ret; | ||
1152 | |||
1153 | reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1154 | irq = platform_get_irq(pdev, 0); | ||
1155 | |||
1156 | if (!reg_res || irq <= 0) { | ||
1157 | dev_err(&pdev->dev, "Insufficient VEU platform information.\n"); | ||
1158 | return -ENODEV; | ||
1159 | } | ||
1160 | |||
1161 | veu = devm_kzalloc(&pdev->dev, sizeof(*veu), GFP_KERNEL); | ||
1162 | if (!veu) | ||
1163 | return -ENOMEM; | ||
1164 | |||
1165 | veu->is_2h = resource_size(reg_res) == 0x22c; | ||
1166 | |||
1167 | veu->base = devm_request_and_ioremap(&pdev->dev, reg_res); | ||
1168 | if (!veu->base) | ||
1169 | return -ENOMEM; | ||
1170 | |||
1171 | ret = devm_request_threaded_irq(&pdev->dev, irq, sh_veu_isr, sh_veu_bh, | ||
1172 | 0, "veu", veu); | ||
1173 | if (ret < 0) | ||
1174 | return ret; | ||
1175 | |||
1176 | ret = v4l2_device_register(&pdev->dev, &veu->v4l2_dev); | ||
1177 | if (ret < 0) { | ||
1178 | dev_err(&pdev->dev, "Error registering v4l2 device\n"); | ||
1179 | return ret; | ||
1180 | } | ||
1181 | |||
1182 | vdev = &veu->vdev; | ||
1183 | |||
1184 | veu->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
1185 | if (IS_ERR(veu->alloc_ctx)) { | ||
1186 | ret = PTR_ERR(veu->alloc_ctx); | ||
1187 | goto einitctx; | ||
1188 | } | ||
1189 | |||
1190 | *vdev = sh_veu_videodev; | ||
1191 | spin_lock_init(&veu->lock); | ||
1192 | mutex_init(&veu->fop_lock); | ||
1193 | vdev->lock = &veu->fop_lock; | ||
1194 | |||
1195 | video_set_drvdata(vdev, veu); | ||
1196 | |||
1197 | veu->dev = &pdev->dev; | ||
1198 | veu->vfmt_out = DEFAULT_OUT_VFMT; | ||
1199 | veu->vfmt_in = DEFAULT_IN_VFMT; | ||
1200 | |||
1201 | veu->m2m_dev = v4l2_m2m_init(&sh_veu_m2m_ops); | ||
1202 | if (IS_ERR(veu->m2m_dev)) { | ||
1203 | ret = PTR_ERR(veu->m2m_dev); | ||
1204 | v4l2_err(&veu->v4l2_dev, "Failed to init mem2mem device: %d\n", ret); | ||
1205 | goto em2minit; | ||
1206 | } | ||
1207 | |||
1208 | pm_runtime_enable(&pdev->dev); | ||
1209 | pm_runtime_resume(&pdev->dev); | ||
1210 | |||
1211 | ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); | ||
1212 | pm_runtime_suspend(&pdev->dev); | ||
1213 | if (ret < 0) | ||
1214 | goto evidreg; | ||
1215 | |||
1216 | return ret; | ||
1217 | |||
1218 | evidreg: | ||
1219 | pm_runtime_disable(&pdev->dev); | ||
1220 | v4l2_m2m_release(veu->m2m_dev); | ||
1221 | em2minit: | ||
1222 | vb2_dma_contig_cleanup_ctx(veu->alloc_ctx); | ||
1223 | einitctx: | ||
1224 | v4l2_device_unregister(&veu->v4l2_dev); | ||
1225 | return ret; | ||
1226 | } | ||
1227 | |||
1228 | static int sh_veu_remove(struct platform_device *pdev) | ||
1229 | { | ||
1230 | struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); | ||
1231 | struct sh_veu_dev *veu = container_of(v4l2_dev, | ||
1232 | struct sh_veu_dev, v4l2_dev); | ||
1233 | |||
1234 | video_unregister_device(&veu->vdev); | ||
1235 | pm_runtime_disable(&pdev->dev); | ||
1236 | v4l2_m2m_release(veu->m2m_dev); | ||
1237 | vb2_dma_contig_cleanup_ctx(veu->alloc_ctx); | ||
1238 | v4l2_device_unregister(&veu->v4l2_dev); | ||
1239 | |||
1240 | return 0; | ||
1241 | } | ||
1242 | |||
1243 | static struct platform_driver __refdata sh_veu_pdrv = { | ||
1244 | .remove = sh_veu_remove, | ||
1245 | .driver = { | ||
1246 | .name = "sh_veu", | ||
1247 | .owner = THIS_MODULE, | ||
1248 | }, | ||
1249 | }; | ||
1250 | |||
1251 | static int __init sh_veu_init(void) | ||
1252 | { | ||
1253 | return platform_driver_probe(&sh_veu_pdrv, sh_veu_probe); | ||
1254 | } | ||
1255 | |||
1256 | static void __exit sh_veu_exit(void) | ||
1257 | { | ||
1258 | platform_driver_unregister(&sh_veu_pdrv); | ||
1259 | } | ||
1260 | |||
1261 | module_init(sh_veu_init); | ||
1262 | module_exit(sh_veu_exit); | ||
1263 | |||
1264 | MODULE_DESCRIPTION("sh-mobile VEU mem2mem driver"); | ||
1265 | MODULE_AUTHOR("Guennadi Liakhovetski, <g.liakhovetski@gmx.de>"); | ||
1266 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index f3c4571ac01e..66c8da18df84 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c | |||
@@ -207,6 +207,7 @@ static void sh_vou_stream_start(struct sh_vou_device *vou_dev, | |||
207 | #endif | 207 | #endif |
208 | 208 | ||
209 | switch (vou_dev->pix.pixelformat) { | 209 | switch (vou_dev->pix.pixelformat) { |
210 | default: | ||
210 | case V4L2_PIX_FMT_NV12: | 211 | case V4L2_PIX_FMT_NV12: |
211 | case V4L2_PIX_FMT_NV16: | 212 | case V4L2_PIX_FMT_NV16: |
212 | row_coeff = 1; | 213 | row_coeff = 1; |
@@ -253,7 +254,8 @@ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
253 | if (PAGE_ALIGN(*size) * *count > 4 * 1024 * 1024) | 254 | if (PAGE_ALIGN(*size) * *count > 4 * 1024 * 1024) |
254 | *count = 4 * 1024 * 1024 / PAGE_ALIGN(*size); | 255 | *count = 4 * 1024 * 1024 / PAGE_ALIGN(*size); |
255 | 256 | ||
256 | dev_dbg(vq->dev, "%s(): count=%d, size=%d\n", __func__, *count, *size); | 257 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): count=%d, size=%d\n", __func__, |
258 | *count, *size); | ||
257 | 259 | ||
258 | return 0; | 260 | return 0; |
259 | } | 261 | } |
@@ -269,7 +271,7 @@ static int sh_vou_buf_prepare(struct videobuf_queue *vq, | |||
269 | int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8; | 271 | int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8; |
270 | int ret; | 272 | int ret; |
271 | 273 | ||
272 | dev_dbg(vq->dev, "%s()\n", __func__); | 274 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
273 | 275 | ||
274 | if (vb->width != pix->width || | 276 | if (vb->width != pix->width || |
275 | vb->height != pix->height || | 277 | vb->height != pix->height || |
@@ -299,7 +301,7 @@ static int sh_vou_buf_prepare(struct videobuf_queue *vq, | |||
299 | vb->state = VIDEOBUF_PREPARED; | 301 | vb->state = VIDEOBUF_PREPARED; |
300 | } | 302 | } |
301 | 303 | ||
302 | dev_dbg(vq->dev, | 304 | dev_dbg(vou_dev->v4l2_dev.dev, |
303 | "%s(): fmt #%d, %u bytes per line, phys 0x%x, type %d, state %d\n", | 305 | "%s(): fmt #%d, %u bytes per line, phys 0x%x, type %d, state %d\n", |
304 | __func__, vou_dev->pix_idx, bytes_per_line, | 306 | __func__, vou_dev->pix_idx, bytes_per_line, |
305 | videobuf_to_dma_contig(vb), vb->memory, vb->state); | 307 | videobuf_to_dma_contig(vb), vb->memory, vb->state); |
@@ -314,7 +316,7 @@ static void sh_vou_buf_queue(struct videobuf_queue *vq, | |||
314 | struct video_device *vdev = vq->priv_data; | 316 | struct video_device *vdev = vq->priv_data; |
315 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | 317 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); |
316 | 318 | ||
317 | dev_dbg(vq->dev, "%s()\n", __func__); | 319 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
318 | 320 | ||
319 | vb->state = VIDEOBUF_QUEUED; | 321 | vb->state = VIDEOBUF_QUEUED; |
320 | list_add_tail(&vb->queue, &vou_dev->queue); | 322 | list_add_tail(&vb->queue, &vou_dev->queue); |
@@ -325,8 +327,8 @@ static void sh_vou_buf_queue(struct videobuf_queue *vq, | |||
325 | vou_dev->active = vb; | 327 | vou_dev->active = vb; |
326 | /* Start from side A: we use mirror addresses, so, set B */ | 328 | /* Start from side A: we use mirror addresses, so, set B */ |
327 | sh_vou_reg_a_write(vou_dev, VOURPR, 1); | 329 | sh_vou_reg_a_write(vou_dev, VOURPR, 1); |
328 | dev_dbg(vq->dev, "%s: first buffer status 0x%x\n", __func__, | 330 | dev_dbg(vou_dev->v4l2_dev.dev, "%s: first buffer status 0x%x\n", |
329 | sh_vou_reg_a_read(vou_dev, VOUSTR)); | 331 | __func__, sh_vou_reg_a_read(vou_dev, VOUSTR)); |
330 | sh_vou_schedule_next(vou_dev, vb); | 332 | sh_vou_schedule_next(vou_dev, vb); |
331 | /* Only activate VOU after the second buffer */ | 333 | /* Only activate VOU after the second buffer */ |
332 | } else if (vou_dev->active->queue.next == &vb->queue) { | 334 | } else if (vou_dev->active->queue.next == &vb->queue) { |
@@ -336,8 +338,8 @@ static void sh_vou_buf_queue(struct videobuf_queue *vq, | |||
336 | 338 | ||
337 | /* Register side switching with frame VSYNC */ | 339 | /* Register side switching with frame VSYNC */ |
338 | sh_vou_reg_a_write(vou_dev, VOURCR, 5); | 340 | sh_vou_reg_a_write(vou_dev, VOURCR, 5); |
339 | dev_dbg(vq->dev, "%s: second buffer status 0x%x\n", __func__, | 341 | dev_dbg(vou_dev->v4l2_dev.dev, "%s: second buffer status 0x%x\n", |
340 | sh_vou_reg_a_read(vou_dev, VOUSTR)); | 342 | __func__, sh_vou_reg_a_read(vou_dev, VOUSTR)); |
341 | 343 | ||
342 | /* Enable End-of-Frame (VSYNC) interrupts */ | 344 | /* Enable End-of-Frame (VSYNC) interrupts */ |
343 | sh_vou_reg_a_write(vou_dev, VOUIR, 0x10004); | 345 | sh_vou_reg_a_write(vou_dev, VOUIR, 0x10004); |
@@ -355,7 +357,7 @@ static void sh_vou_buf_release(struct videobuf_queue *vq, | |||
355 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | 357 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); |
356 | unsigned long flags; | 358 | unsigned long flags; |
357 | 359 | ||
358 | dev_dbg(vq->dev, "%s()\n", __func__); | 360 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
359 | 361 | ||
360 | spin_lock_irqsave(&vou_dev->lock, flags); | 362 | spin_lock_irqsave(&vou_dev->lock, flags); |
361 | 363 | ||
@@ -388,9 +390,9 @@ static struct videobuf_queue_ops sh_vou_video_qops = { | |||
388 | static int sh_vou_querycap(struct file *file, void *priv, | 390 | static int sh_vou_querycap(struct file *file, void *priv, |
389 | struct v4l2_capability *cap) | 391 | struct v4l2_capability *cap) |
390 | { | 392 | { |
391 | struct sh_vou_file *vou_file = priv; | 393 | struct sh_vou_device *vou_dev = video_drvdata(file); |
392 | 394 | ||
393 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 395 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
394 | 396 | ||
395 | strlcpy(cap->card, "SuperH VOU", sizeof(cap->card)); | 397 | strlcpy(cap->card, "SuperH VOU", sizeof(cap->card)); |
396 | cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; | 398 | cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; |
@@ -401,12 +403,12 @@ static int sh_vou_querycap(struct file *file, void *priv, | |||
401 | static int sh_vou_enum_fmt_vid_out(struct file *file, void *priv, | 403 | static int sh_vou_enum_fmt_vid_out(struct file *file, void *priv, |
402 | struct v4l2_fmtdesc *fmt) | 404 | struct v4l2_fmtdesc *fmt) |
403 | { | 405 | { |
404 | struct sh_vou_file *vou_file = priv; | 406 | struct sh_vou_device *vou_dev = video_drvdata(file); |
405 | 407 | ||
406 | if (fmt->index >= ARRAY_SIZE(vou_fmt)) | 408 | if (fmt->index >= ARRAY_SIZE(vou_fmt)) |
407 | return -EINVAL; | 409 | return -EINVAL; |
408 | 410 | ||
409 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 411 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
410 | 412 | ||
411 | fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | 413 | fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
412 | strlcpy(fmt->description, vou_fmt[fmt->index].desc, | 414 | strlcpy(fmt->description, vou_fmt[fmt->index].desc, |
@@ -419,8 +421,7 @@ static int sh_vou_enum_fmt_vid_out(struct file *file, void *priv, | |||
419 | static int sh_vou_g_fmt_vid_out(struct file *file, void *priv, | 421 | static int sh_vou_g_fmt_vid_out(struct file *file, void *priv, |
420 | struct v4l2_format *fmt) | 422 | struct v4l2_format *fmt) |
421 | { | 423 | { |
422 | struct video_device *vdev = video_devdata(file); | 424 | struct sh_vou_device *vou_dev = video_drvdata(file); |
423 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
424 | 425 | ||
425 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); | 426 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
426 | 427 | ||
@@ -595,9 +596,9 @@ static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) | |||
595 | */ | 596 | */ |
596 | static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) | 597 | static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) |
597 | { | 598 | { |
598 | unsigned int best_err = UINT_MAX, best, width_max, height_max, | 599 | unsigned int best_err = UINT_MAX, best = geo->in_width, |
599 | img_height_max; | 600 | width_max, height_max, img_height_max; |
600 | int i, idx; | 601 | int i, idx = 0; |
601 | 602 | ||
602 | if (std & V4L2_STD_525_60) { | 603 | if (std & V4L2_STD_525_60) { |
603 | width_max = 858; | 604 | width_max = 858; |
@@ -671,8 +672,7 @@ static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) | |||
671 | static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, | 672 | static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, |
672 | struct v4l2_format *fmt) | 673 | struct v4l2_format *fmt) |
673 | { | 674 | { |
674 | struct video_device *vdev = video_devdata(file); | 675 | struct sh_vou_device *vou_dev = video_drvdata(file); |
675 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
676 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | 676 | struct v4l2_pix_format *pix = &fmt->fmt.pix; |
677 | unsigned int img_height_max; | 677 | unsigned int img_height_max; |
678 | int pix_idx; | 678 | int pix_idx; |
@@ -764,11 +764,11 @@ static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, | |||
764 | static int sh_vou_try_fmt_vid_out(struct file *file, void *priv, | 764 | static int sh_vou_try_fmt_vid_out(struct file *file, void *priv, |
765 | struct v4l2_format *fmt) | 765 | struct v4l2_format *fmt) |
766 | { | 766 | { |
767 | struct sh_vou_file *vou_file = priv; | 767 | struct sh_vou_device *vou_dev = video_drvdata(file); |
768 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | 768 | struct v4l2_pix_format *pix = &fmt->fmt.pix; |
769 | int i; | 769 | int i; |
770 | 770 | ||
771 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 771 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
772 | 772 | ||
773 | fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | 773 | fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
774 | pix->field = V4L2_FIELD_NONE; | 774 | pix->field = V4L2_FIELD_NONE; |
@@ -788,9 +788,10 @@ static int sh_vou_try_fmt_vid_out(struct file *file, void *priv, | |||
788 | static int sh_vou_reqbufs(struct file *file, void *priv, | 788 | static int sh_vou_reqbufs(struct file *file, void *priv, |
789 | struct v4l2_requestbuffers *req) | 789 | struct v4l2_requestbuffers *req) |
790 | { | 790 | { |
791 | struct sh_vou_device *vou_dev = video_drvdata(file); | ||
791 | struct sh_vou_file *vou_file = priv; | 792 | struct sh_vou_file *vou_file = priv; |
792 | 793 | ||
793 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 794 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
794 | 795 | ||
795 | if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | 796 | if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) |
796 | return -EINVAL; | 797 | return -EINVAL; |
@@ -801,27 +802,30 @@ static int sh_vou_reqbufs(struct file *file, void *priv, | |||
801 | static int sh_vou_querybuf(struct file *file, void *priv, | 802 | static int sh_vou_querybuf(struct file *file, void *priv, |
802 | struct v4l2_buffer *b) | 803 | struct v4l2_buffer *b) |
803 | { | 804 | { |
805 | struct sh_vou_device *vou_dev = video_drvdata(file); | ||
804 | struct sh_vou_file *vou_file = priv; | 806 | struct sh_vou_file *vou_file = priv; |
805 | 807 | ||
806 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 808 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
807 | 809 | ||
808 | return videobuf_querybuf(&vou_file->vbq, b); | 810 | return videobuf_querybuf(&vou_file->vbq, b); |
809 | } | 811 | } |
810 | 812 | ||
811 | static int sh_vou_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) | 813 | static int sh_vou_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) |
812 | { | 814 | { |
815 | struct sh_vou_device *vou_dev = video_drvdata(file); | ||
813 | struct sh_vou_file *vou_file = priv; | 816 | struct sh_vou_file *vou_file = priv; |
814 | 817 | ||
815 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 818 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
816 | 819 | ||
817 | return videobuf_qbuf(&vou_file->vbq, b); | 820 | return videobuf_qbuf(&vou_file->vbq, b); |
818 | } | 821 | } |
819 | 822 | ||
820 | static int sh_vou_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | 823 | static int sh_vou_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) |
821 | { | 824 | { |
825 | struct sh_vou_device *vou_dev = video_drvdata(file); | ||
822 | struct sh_vou_file *vou_file = priv; | 826 | struct sh_vou_file *vou_file = priv; |
823 | 827 | ||
824 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 828 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
825 | 829 | ||
826 | return videobuf_dqbuf(&vou_file->vbq, b, file->f_flags & O_NONBLOCK); | 830 | return videobuf_dqbuf(&vou_file->vbq, b, file->f_flags & O_NONBLOCK); |
827 | } | 831 | } |
@@ -829,12 +833,11 @@ static int sh_vou_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | |||
829 | static int sh_vou_streamon(struct file *file, void *priv, | 833 | static int sh_vou_streamon(struct file *file, void *priv, |
830 | enum v4l2_buf_type buftype) | 834 | enum v4l2_buf_type buftype) |
831 | { | 835 | { |
832 | struct video_device *vdev = video_devdata(file); | 836 | struct sh_vou_device *vou_dev = video_drvdata(file); |
833 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
834 | struct sh_vou_file *vou_file = priv; | 837 | struct sh_vou_file *vou_file = priv; |
835 | int ret; | 838 | int ret; |
836 | 839 | ||
837 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 840 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
838 | 841 | ||
839 | ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, | 842 | ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, |
840 | video, s_stream, 1); | 843 | video, s_stream, 1); |
@@ -848,11 +851,10 @@ static int sh_vou_streamon(struct file *file, void *priv, | |||
848 | static int sh_vou_streamoff(struct file *file, void *priv, | 851 | static int sh_vou_streamoff(struct file *file, void *priv, |
849 | enum v4l2_buf_type buftype) | 852 | enum v4l2_buf_type buftype) |
850 | { | 853 | { |
851 | struct video_device *vdev = video_devdata(file); | 854 | struct sh_vou_device *vou_dev = video_drvdata(file); |
852 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
853 | struct sh_vou_file *vou_file = priv; | 855 | struct sh_vou_file *vou_file = priv; |
854 | 856 | ||
855 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 857 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
856 | 858 | ||
857 | /* | 859 | /* |
858 | * This calls buf_release from host driver's videobuf_queue_ops for all | 860 | * This calls buf_release from host driver's videobuf_queue_ops for all |
@@ -881,13 +883,12 @@ static u32 sh_vou_ntsc_mode(enum sh_vou_bus_fmt bus_fmt) | |||
881 | 883 | ||
882 | static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id *std_id) | 884 | static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id *std_id) |
883 | { | 885 | { |
884 | struct video_device *vdev = video_devdata(file); | 886 | struct sh_vou_device *vou_dev = video_drvdata(file); |
885 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
886 | int ret; | 887 | int ret; |
887 | 888 | ||
888 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): 0x%llx\n", __func__, *std_id); | 889 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): 0x%llx\n", __func__, *std_id); |
889 | 890 | ||
890 | if (*std_id & ~vdev->tvnorms) | 891 | if (*std_id & ~vou_dev->vdev->tvnorms) |
891 | return -EINVAL; | 892 | return -EINVAL; |
892 | 893 | ||
893 | ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, | 894 | ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, |
@@ -909,8 +910,7 @@ static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id *std_id) | |||
909 | 910 | ||
910 | static int sh_vou_g_std(struct file *file, void *priv, v4l2_std_id *std) | 911 | static int sh_vou_g_std(struct file *file, void *priv, v4l2_std_id *std) |
911 | { | 912 | { |
912 | struct video_device *vdev = video_devdata(file); | 913 | struct sh_vou_device *vou_dev = video_drvdata(file); |
913 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
914 | 914 | ||
915 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); | 915 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
916 | 916 | ||
@@ -921,8 +921,7 @@ static int sh_vou_g_std(struct file *file, void *priv, v4l2_std_id *std) | |||
921 | 921 | ||
922 | static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a) | 922 | static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a) |
923 | { | 923 | { |
924 | struct video_device *vdev = video_devdata(file); | 924 | struct sh_vou_device *vou_dev = video_drvdata(file); |
925 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
926 | 925 | ||
927 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); | 926 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
928 | 927 | ||
@@ -936,8 +935,7 @@ static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a) | |||
936 | static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a) | 935 | static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a) |
937 | { | 936 | { |
938 | struct v4l2_crop a_writable = *a; | 937 | struct v4l2_crop a_writable = *a; |
939 | struct video_device *vdev = video_devdata(file); | 938 | struct sh_vou_device *vou_dev = video_drvdata(file); |
940 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
941 | struct v4l2_rect *rect = &a_writable.c; | 939 | struct v4l2_rect *rect = &a_writable.c; |
942 | struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT}; | 940 | struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT}; |
943 | struct v4l2_pix_format *pix = &vou_dev->pix; | 941 | struct v4l2_pix_format *pix = &vou_dev->pix; |
@@ -1028,9 +1026,9 @@ static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a) | |||
1028 | static int sh_vou_cropcap(struct file *file, void *priv, | 1026 | static int sh_vou_cropcap(struct file *file, void *priv, |
1029 | struct v4l2_cropcap *a) | 1027 | struct v4l2_cropcap *a) |
1030 | { | 1028 | { |
1031 | struct sh_vou_file *vou_file = priv; | 1029 | struct sh_vou_device *vou_dev = video_drvdata(file); |
1032 | 1030 | ||
1033 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 1031 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
1034 | 1032 | ||
1035 | a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | 1033 | a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
1036 | a->bounds.left = 0; | 1034 | a->bounds.left = 0; |
@@ -1091,7 +1089,7 @@ static irqreturn_t sh_vou_isr(int irq, void *dev_id) | |||
1091 | list_del(&vb->queue); | 1089 | list_del(&vb->queue); |
1092 | 1090 | ||
1093 | vb->state = VIDEOBUF_DONE; | 1091 | vb->state = VIDEOBUF_DONE; |
1094 | do_gettimeofday(&vb->ts); | 1092 | v4l2_get_timestamp(&vb->ts); |
1095 | vb->field_count++; | 1093 | vb->field_count++; |
1096 | wake_up(&vb->done); | 1094 | wake_up(&vb->done); |
1097 | 1095 | ||
@@ -1160,8 +1158,7 @@ static int sh_vou_hw_init(struct sh_vou_device *vou_dev) | |||
1160 | /* File operations */ | 1158 | /* File operations */ |
1161 | static int sh_vou_open(struct file *file) | 1159 | static int sh_vou_open(struct file *file) |
1162 | { | 1160 | { |
1163 | struct video_device *vdev = video_devdata(file); | 1161 | struct sh_vou_device *vou_dev = video_drvdata(file); |
1164 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1165 | struct sh_vou_file *vou_file = kzalloc(sizeof(struct sh_vou_file), | 1162 | struct sh_vou_file *vou_file = kzalloc(sizeof(struct sh_vou_file), |
1166 | GFP_KERNEL); | 1163 | GFP_KERNEL); |
1167 | 1164 | ||
@@ -1178,11 +1175,11 @@ static int sh_vou_open(struct file *file) | |||
1178 | int ret; | 1175 | int ret; |
1179 | /* First open */ | 1176 | /* First open */ |
1180 | vou_dev->status = SH_VOU_INITIALISING; | 1177 | vou_dev->status = SH_VOU_INITIALISING; |
1181 | pm_runtime_get_sync(vdev->v4l2_dev->dev); | 1178 | pm_runtime_get_sync(vou_dev->v4l2_dev.dev); |
1182 | ret = sh_vou_hw_init(vou_dev); | 1179 | ret = sh_vou_hw_init(vou_dev); |
1183 | if (ret < 0) { | 1180 | if (ret < 0) { |
1184 | atomic_dec(&vou_dev->use_count); | 1181 | atomic_dec(&vou_dev->use_count); |
1185 | pm_runtime_put(vdev->v4l2_dev->dev); | 1182 | pm_runtime_put(vou_dev->v4l2_dev.dev); |
1186 | vou_dev->status = SH_VOU_IDLE; | 1183 | vou_dev->status = SH_VOU_IDLE; |
1187 | mutex_unlock(&vou_dev->fop_lock); | 1184 | mutex_unlock(&vou_dev->fop_lock); |
1188 | return ret; | 1185 | return ret; |
@@ -1193,8 +1190,8 @@ static int sh_vou_open(struct file *file) | |||
1193 | vou_dev->v4l2_dev.dev, &vou_dev->lock, | 1190 | vou_dev->v4l2_dev.dev, &vou_dev->lock, |
1194 | V4L2_BUF_TYPE_VIDEO_OUTPUT, | 1191 | V4L2_BUF_TYPE_VIDEO_OUTPUT, |
1195 | V4L2_FIELD_NONE, | 1192 | V4L2_FIELD_NONE, |
1196 | sizeof(struct videobuf_buffer), vdev, | 1193 | sizeof(struct videobuf_buffer), |
1197 | &vou_dev->fop_lock); | 1194 | vou_dev->vdev, &vou_dev->fop_lock); |
1198 | mutex_unlock(&vou_dev->fop_lock); | 1195 | mutex_unlock(&vou_dev->fop_lock); |
1199 | 1196 | ||
1200 | return 0; | 1197 | return 0; |
@@ -1202,18 +1199,17 @@ static int sh_vou_open(struct file *file) | |||
1202 | 1199 | ||
1203 | static int sh_vou_release(struct file *file) | 1200 | static int sh_vou_release(struct file *file) |
1204 | { | 1201 | { |
1205 | struct video_device *vdev = video_devdata(file); | 1202 | struct sh_vou_device *vou_dev = video_drvdata(file); |
1206 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1207 | struct sh_vou_file *vou_file = file->private_data; | 1203 | struct sh_vou_file *vou_file = file->private_data; |
1208 | 1204 | ||
1209 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 1205 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
1210 | 1206 | ||
1211 | if (!atomic_dec_return(&vou_dev->use_count)) { | 1207 | if (!atomic_dec_return(&vou_dev->use_count)) { |
1212 | mutex_lock(&vou_dev->fop_lock); | 1208 | mutex_lock(&vou_dev->fop_lock); |
1213 | /* Last close */ | 1209 | /* Last close */ |
1214 | vou_dev->status = SH_VOU_IDLE; | 1210 | vou_dev->status = SH_VOU_IDLE; |
1215 | sh_vou_reg_a_set(vou_dev, VOUER, 0, 0x101); | 1211 | sh_vou_reg_a_set(vou_dev, VOUER, 0, 0x101); |
1216 | pm_runtime_put(vdev->v4l2_dev->dev); | 1212 | pm_runtime_put(vou_dev->v4l2_dev.dev); |
1217 | mutex_unlock(&vou_dev->fop_lock); | 1213 | mutex_unlock(&vou_dev->fop_lock); |
1218 | } | 1214 | } |
1219 | 1215 | ||
@@ -1225,12 +1221,11 @@ static int sh_vou_release(struct file *file) | |||
1225 | 1221 | ||
1226 | static int sh_vou_mmap(struct file *file, struct vm_area_struct *vma) | 1222 | static int sh_vou_mmap(struct file *file, struct vm_area_struct *vma) |
1227 | { | 1223 | { |
1228 | struct video_device *vdev = video_devdata(file); | 1224 | struct sh_vou_device *vou_dev = video_drvdata(file); |
1229 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1230 | struct sh_vou_file *vou_file = file->private_data; | 1225 | struct sh_vou_file *vou_file = file->private_data; |
1231 | int ret; | 1226 | int ret; |
1232 | 1227 | ||
1233 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 1228 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
1234 | 1229 | ||
1235 | if (mutex_lock_interruptible(&vou_dev->fop_lock)) | 1230 | if (mutex_lock_interruptible(&vou_dev->fop_lock)) |
1236 | return -ERESTARTSYS; | 1231 | return -ERESTARTSYS; |
@@ -1241,12 +1236,11 @@ static int sh_vou_mmap(struct file *file, struct vm_area_struct *vma) | |||
1241 | 1236 | ||
1242 | static unsigned int sh_vou_poll(struct file *file, poll_table *wait) | 1237 | static unsigned int sh_vou_poll(struct file *file, poll_table *wait) |
1243 | { | 1238 | { |
1244 | struct video_device *vdev = video_devdata(file); | 1239 | struct sh_vou_device *vou_dev = video_drvdata(file); |
1245 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1246 | struct sh_vou_file *vou_file = file->private_data; | 1240 | struct sh_vou_file *vou_file = file->private_data; |
1247 | unsigned int res; | 1241 | unsigned int res; |
1248 | 1242 | ||
1249 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | 1243 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); |
1250 | 1244 | ||
1251 | mutex_lock(&vou_dev->fop_lock); | 1245 | mutex_lock(&vou_dev->fop_lock); |
1252 | res = videobuf_poll_stream(file, &vou_file->vbq, wait); | 1246 | res = videobuf_poll_stream(file, &vou_file->vbq, wait); |
@@ -1257,8 +1251,7 @@ static unsigned int sh_vou_poll(struct file *file, poll_table *wait) | |||
1257 | static int sh_vou_g_chip_ident(struct file *file, void *fh, | 1251 | static int sh_vou_g_chip_ident(struct file *file, void *fh, |
1258 | struct v4l2_dbg_chip_ident *id) | 1252 | struct v4l2_dbg_chip_ident *id) |
1259 | { | 1253 | { |
1260 | struct video_device *vdev = video_devdata(file); | 1254 | struct sh_vou_device *vou_dev = video_drvdata(file); |
1261 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1262 | 1255 | ||
1263 | return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_chip_ident, id); | 1256 | return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_chip_ident, id); |
1264 | } | 1257 | } |
@@ -1267,8 +1260,7 @@ static int sh_vou_g_chip_ident(struct file *file, void *fh, | |||
1267 | static int sh_vou_g_register(struct file *file, void *fh, | 1260 | static int sh_vou_g_register(struct file *file, void *fh, |
1268 | struct v4l2_dbg_register *reg) | 1261 | struct v4l2_dbg_register *reg) |
1269 | { | 1262 | { |
1270 | struct video_device *vdev = video_devdata(file); | 1263 | struct sh_vou_device *vou_dev = video_drvdata(file); |
1271 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1272 | 1264 | ||
1273 | return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_register, reg); | 1265 | return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_register, reg); |
1274 | } | 1266 | } |
@@ -1276,8 +1268,7 @@ static int sh_vou_g_register(struct file *file, void *fh, | |||
1276 | static int sh_vou_s_register(struct file *file, void *fh, | 1268 | static int sh_vou_s_register(struct file *file, void *fh, |
1277 | struct v4l2_dbg_register *reg) | 1269 | struct v4l2_dbg_register *reg) |
1278 | { | 1270 | { |
1279 | struct video_device *vdev = video_devdata(file); | 1271 | struct sh_vou_device *vou_dev = video_drvdata(file); |
1280 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1281 | 1272 | ||
1282 | return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, s_register, reg); | 1273 | return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, s_register, reg); |
1283 | } | 1274 | } |
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index cb6791e62bd4..b139b525bb16 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig | |||
@@ -70,13 +70,12 @@ config VIDEO_MX2_HOSTSUPPORT | |||
70 | bool | 70 | bool |
71 | 71 | ||
72 | config VIDEO_MX2 | 72 | config VIDEO_MX2 |
73 | tristate "i.MX27/i.MX25 Camera Sensor Interface driver" | 73 | tristate "i.MX27 Camera Sensor Interface driver" |
74 | depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || (ARCH_MX25 && BROKEN)) | 74 | depends on VIDEO_DEV && SOC_CAMERA && MACH_MX27 |
75 | select VIDEOBUF2_DMA_CONTIG | 75 | select VIDEOBUF2_DMA_CONTIG |
76 | select VIDEO_MX2_HOSTSUPPORT | 76 | select VIDEO_MX2_HOSTSUPPORT |
77 | ---help--- | 77 | ---help--- |
78 | This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor | 78 | This is a v4l2 driver for the i.MX27 Camera Sensor Interface |
79 | Interface | ||
80 | 79 | ||
81 | config VIDEO_ATMEL_ISI | 80 | config VIDEO_ATMEL_ISI |
82 | tristate "ATMEL Image Sensor Interface (ISI) support" | 81 | tristate "ATMEL Image Sensor Interface (ISI) support" |
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index d96c8c7e01d9..82dbf99d347c 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c | |||
@@ -166,7 +166,7 @@ static irqreturn_t atmel_isi_handle_streaming(struct atmel_isi *isi) | |||
166 | struct frame_buffer *buf = isi->active; | 166 | struct frame_buffer *buf = isi->active; |
167 | 167 | ||
168 | list_del_init(&buf->list); | 168 | list_del_init(&buf->list); |
169 | do_gettimeofday(&vb->v4l2_buf.timestamp); | 169 | v4l2_get_timestamp(&vb->v4l2_buf.timestamp); |
170 | vb->v4l2_buf.sequence = isi->sequence++; | 170 | vb->v4l2_buf.sequence = isi->sequence++; |
171 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | 171 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); |
172 | } | 172 | } |
@@ -745,7 +745,7 @@ static int isi_camera_get_formats(struct soc_camera_device *icd, | |||
745 | return formats; | 745 | return formats; |
746 | } | 746 | } |
747 | 747 | ||
748 | /* Called with .video_lock held */ | 748 | /* Called with .host_lock held */ |
749 | static int isi_camera_add_device(struct soc_camera_device *icd) | 749 | static int isi_camera_add_device(struct soc_camera_device *icd) |
750 | { | 750 | { |
751 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 751 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
@@ -770,7 +770,7 @@ static int isi_camera_add_device(struct soc_camera_device *icd) | |||
770 | icd->devnum); | 770 | icd->devnum); |
771 | return 0; | 771 | return 0; |
772 | } | 772 | } |
773 | /* Called with .video_lock held */ | 773 | /* Called with .host_lock held */ |
774 | static void isi_camera_remove_device(struct soc_camera_device *icd) | 774 | static void isi_camera_remove_device(struct soc_camera_device *icd) |
775 | { | 775 | { |
776 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 776 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c index 032b8c9097f9..25b2a285dc86 100644 --- a/drivers/media/platform/soc_camera/mx1_camera.c +++ b/drivers/media/platform/soc_camera/mx1_camera.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <linux/mutex.h> | ||
30 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
31 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
32 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
@@ -307,7 +306,7 @@ static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev, | |||
307 | /* _init is used to debug races, see comment in mx1_camera_reqbufs() */ | 306 | /* _init is used to debug races, see comment in mx1_camera_reqbufs() */ |
308 | list_del_init(&vb->queue); | 307 | list_del_init(&vb->queue); |
309 | vb->state = VIDEOBUF_DONE; | 308 | vb->state = VIDEOBUF_DONE; |
310 | do_gettimeofday(&vb->ts); | 309 | v4l2_get_timestamp(&vb->ts); |
311 | vb->field_count++; | 310 | vb->field_count++; |
312 | wake_up(&vb->done); | 311 | wake_up(&vb->done); |
313 | 312 | ||
@@ -373,7 +372,7 @@ static void mx1_camera_init_videobuf(struct videobuf_queue *q, | |||
373 | videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->parent, | 372 | videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->parent, |
374 | &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, | 373 | &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
375 | V4L2_FIELD_NONE, | 374 | V4L2_FIELD_NONE, |
376 | sizeof(struct mx1_buffer), icd, &icd->video_lock); | 375 | sizeof(struct mx1_buffer), icd, &ici->host_lock); |
377 | } | 376 | } |
378 | 377 | ||
379 | static int mclk_get_divisor(struct mx1_camera_dev *pcdev) | 378 | static int mclk_get_divisor(struct mx1_camera_dev *pcdev) |
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c index 4a574f3cfb2f..ffba7d91f413 100644 --- a/drivers/media/platform/soc_camera/mx2_camera.c +++ b/drivers/media/platform/soc_camera/mx2_camera.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * V4L2 Driver for i.MX27/i.MX25 camera host | 2 | * V4L2 Driver for i.MX27 camera host |
3 | * | 3 | * |
4 | * Copyright (C) 2008, Sascha Hauer, Pengutronix | 4 | * Copyright (C) 2008, Sascha Hauer, Pengutronix |
5 | * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography | 5 | * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography |
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <linux/device.h> | 29 | #include <linux/device.h> |
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/mutex.h> | ||
32 | #include <linux/clk.h> | 31 | #include <linux/clk.h> |
33 | 32 | ||
34 | #include <media/v4l2-common.h> | 33 | #include <media/v4l2-common.h> |
@@ -64,9 +63,7 @@ | |||
64 | #define CSICR1_RF_OR_INTEN (1 << 24) | 63 | #define CSICR1_RF_OR_INTEN (1 << 24) |
65 | #define CSICR1_STATFF_LEVEL (3 << 22) | 64 | #define CSICR1_STATFF_LEVEL (3 << 22) |
66 | #define CSICR1_STATFF_INTEN (1 << 21) | 65 | #define CSICR1_STATFF_INTEN (1 << 21) |
67 | #define CSICR1_RXFF_LEVEL(l) (((l) & 3) << 19) /* MX27 */ | 66 | #define CSICR1_RXFF_LEVEL(l) (((l) & 3) << 19) |
68 | #define CSICR1_FB2_DMA_INTEN (1 << 20) /* MX25 */ | ||
69 | #define CSICR1_FB1_DMA_INTEN (1 << 19) /* MX25 */ | ||
70 | #define CSICR1_RXFF_INTEN (1 << 18) | 67 | #define CSICR1_RXFF_INTEN (1 << 18) |
71 | #define CSICR1_SOF_POL (1 << 17) | 68 | #define CSICR1_SOF_POL (1 << 17) |
72 | #define CSICR1_SOF_INTEN (1 << 16) | 69 | #define CSICR1_SOF_INTEN (1 << 16) |
@@ -88,45 +85,15 @@ | |||
88 | #define SHIFT_RXFF_LEVEL 19 | 85 | #define SHIFT_RXFF_LEVEL 19 |
89 | #define SHIFT_MCLKDIV 12 | 86 | #define SHIFT_MCLKDIV 12 |
90 | 87 | ||
91 | /* control reg 3 */ | ||
92 | #define CSICR3_FRMCNT (0xFFFF << 16) | ||
93 | #define CSICR3_FRMCNT_RST (1 << 15) | ||
94 | #define CSICR3_DMA_REFLASH_RFF (1 << 14) | ||
95 | #define CSICR3_DMA_REFLASH_SFF (1 << 13) | ||
96 | #define CSICR3_DMA_REQ_EN_RFF (1 << 12) | ||
97 | #define CSICR3_DMA_REQ_EN_SFF (1 << 11) | ||
98 | #define CSICR3_RXFF_LEVEL(l) (((l) & 7) << 4) /* MX25 */ | ||
99 | #define CSICR3_CSI_SUP (1 << 3) | ||
100 | #define CSICR3_ZERO_PACK_EN (1 << 2) | ||
101 | #define CSICR3_ECC_INT_EN (1 << 1) | ||
102 | #define CSICR3_ECC_AUTO_EN (1 << 0) | ||
103 | |||
104 | #define SHIFT_FRMCNT 16 | 88 | #define SHIFT_FRMCNT 16 |
105 | 89 | ||
106 | /* csi status reg */ | ||
107 | #define CSISR_SFF_OR_INT (1 << 25) | ||
108 | #define CSISR_RFF_OR_INT (1 << 24) | ||
109 | #define CSISR_STATFF_INT (1 << 21) | ||
110 | #define CSISR_DMA_TSF_FB2_INT (1 << 20) /* MX25 */ | ||
111 | #define CSISR_DMA_TSF_FB1_INT (1 << 19) /* MX25 */ | ||
112 | #define CSISR_RXFF_INT (1 << 18) | ||
113 | #define CSISR_EOF_INT (1 << 17) | ||
114 | #define CSISR_SOF_INT (1 << 16) | ||
115 | #define CSISR_F2_INT (1 << 15) | ||
116 | #define CSISR_F1_INT (1 << 14) | ||
117 | #define CSISR_COF_INT (1 << 13) | ||
118 | #define CSISR_ECC_INT (1 << 1) | ||
119 | #define CSISR_DRDY (1 << 0) | ||
120 | |||
121 | #define CSICR1 0x00 | 90 | #define CSICR1 0x00 |
122 | #define CSICR2 0x04 | 91 | #define CSICR2 0x04 |
123 | #define CSISR_IMX25 0x18 | 92 | #define CSISR 0x08 |
124 | #define CSISR_IMX27 0x08 | ||
125 | #define CSISTATFIFO 0x0c | 93 | #define CSISTATFIFO 0x0c |
126 | #define CSIRFIFO 0x10 | 94 | #define CSIRFIFO 0x10 |
127 | #define CSIRXCNT 0x14 | 95 | #define CSIRXCNT 0x14 |
128 | #define CSICR3_IMX25 0x08 | 96 | #define CSICR3 0x1c |
129 | #define CSICR3_IMX27 0x1c | ||
130 | #define CSIDMASA_STATFIFO 0x20 | 97 | #define CSIDMASA_STATFIFO 0x20 |
131 | #define CSIDMATA_STATFIFO 0x24 | 98 | #define CSIDMATA_STATFIFO 0x24 |
132 | #define CSIDMASA_FB1 0x28 | 99 | #define CSIDMASA_FB1 0x28 |
@@ -249,12 +216,6 @@ struct mx2_fmt_cfg { | |||
249 | struct mx2_prp_cfg cfg; | 216 | struct mx2_prp_cfg cfg; |
250 | }; | 217 | }; |
251 | 218 | ||
252 | enum mx2_buffer_state { | ||
253 | MX2_STATE_QUEUED, | ||
254 | MX2_STATE_ACTIVE, | ||
255 | MX2_STATE_DONE, | ||
256 | }; | ||
257 | |||
258 | struct mx2_buf_internal { | 219 | struct mx2_buf_internal { |
259 | struct list_head queue; | 220 | struct list_head queue; |
260 | int bufnum; | 221 | int bufnum; |
@@ -265,12 +226,10 @@ struct mx2_buf_internal { | |||
265 | struct mx2_buffer { | 226 | struct mx2_buffer { |
266 | /* common v4l buffer stuff -- must be first */ | 227 | /* common v4l buffer stuff -- must be first */ |
267 | struct vb2_buffer vb; | 228 | struct vb2_buffer vb; |
268 | enum mx2_buffer_state state; | ||
269 | struct mx2_buf_internal internal; | 229 | struct mx2_buf_internal internal; |
270 | }; | 230 | }; |
271 | 231 | ||
272 | enum mx2_camera_type { | 232 | enum mx2_camera_type { |
273 | IMX25_CAMERA, | ||
274 | IMX27_CAMERA, | 233 | IMX27_CAMERA, |
275 | }; | 234 | }; |
276 | 235 | ||
@@ -298,8 +257,6 @@ struct mx2_camera_dev { | |||
298 | struct mx2_buffer *fb2_active; | 257 | struct mx2_buffer *fb2_active; |
299 | 258 | ||
300 | u32 csicr1; | 259 | u32 csicr1; |
301 | u32 reg_csisr; | ||
302 | u32 reg_csicr3; | ||
303 | enum mx2_camera_type devtype; | 260 | enum mx2_camera_type devtype; |
304 | 261 | ||
305 | struct mx2_buf_internal buf_discard[2]; | 262 | struct mx2_buf_internal buf_discard[2]; |
@@ -315,9 +272,6 @@ struct mx2_camera_dev { | |||
315 | 272 | ||
316 | static struct platform_device_id mx2_camera_devtype[] = { | 273 | static struct platform_device_id mx2_camera_devtype[] = { |
317 | { | 274 | { |
318 | .name = "imx25-camera", | ||
319 | .driver_data = IMX25_CAMERA, | ||
320 | }, { | ||
321 | .name = "imx27-camera", | 275 | .name = "imx27-camera", |
322 | .driver_data = IMX27_CAMERA, | 276 | .driver_data = IMX27_CAMERA, |
323 | }, { | 277 | }, { |
@@ -326,16 +280,6 @@ static struct platform_device_id mx2_camera_devtype[] = { | |||
326 | }; | 280 | }; |
327 | MODULE_DEVICE_TABLE(platform, mx2_camera_devtype); | 281 | MODULE_DEVICE_TABLE(platform, mx2_camera_devtype); |
328 | 282 | ||
329 | static inline int is_imx25_camera(struct mx2_camera_dev *pcdev) | ||
330 | { | ||
331 | return pcdev->devtype == IMX25_CAMERA; | ||
332 | } | ||
333 | |||
334 | static inline int is_imx27_camera(struct mx2_camera_dev *pcdev) | ||
335 | { | ||
336 | return pcdev->devtype == IMX27_CAMERA; | ||
337 | } | ||
338 | |||
339 | static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf) | 283 | static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf) |
340 | { | 284 | { |
341 | return container_of(int_buf, struct mx2_buffer, internal); | 285 | return container_of(int_buf, struct mx2_buffer, internal); |
@@ -463,21 +407,10 @@ static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev, | |||
463 | 407 | ||
464 | static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) | 408 | static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) |
465 | { | 409 | { |
466 | unsigned long flags; | ||
467 | |||
468 | clk_disable_unprepare(pcdev->clk_csi_ahb); | 410 | clk_disable_unprepare(pcdev->clk_csi_ahb); |
469 | clk_disable_unprepare(pcdev->clk_csi_per); | 411 | clk_disable_unprepare(pcdev->clk_csi_per); |
470 | writel(0, pcdev->base_csi + CSICR1); | 412 | writel(0, pcdev->base_csi + CSICR1); |
471 | if (is_imx27_camera(pcdev)) { | 413 | writel(0, pcdev->base_emma + PRP_CNTL); |
472 | writel(0, pcdev->base_emma + PRP_CNTL); | ||
473 | } else if (is_imx25_camera(pcdev)) { | ||
474 | spin_lock_irqsave(&pcdev->lock, flags); | ||
475 | pcdev->fb1_active = NULL; | ||
476 | pcdev->fb2_active = NULL; | ||
477 | writel(0, pcdev->base_csi + CSIDMASA_FB1); | ||
478 | writel(0, pcdev->base_csi + CSIDMASA_FB2); | ||
479 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
480 | } | ||
481 | } | 414 | } |
482 | 415 | ||
483 | /* | 416 | /* |
@@ -502,11 +435,8 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) | |||
502 | if (ret < 0) | 435 | if (ret < 0) |
503 | goto exit_csi_ahb; | 436 | goto exit_csi_ahb; |
504 | 437 | ||
505 | csicr1 = CSICR1_MCLKEN; | 438 | csicr1 = CSICR1_MCLKEN | CSICR1_PRP_IF_EN | CSICR1_FCC | |
506 | 439 | CSICR1_RXFF_LEVEL(0); | |
507 | if (is_imx27_camera(pcdev)) | ||
508 | csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC | | ||
509 | CSICR1_RXFF_LEVEL(0); | ||
510 | 440 | ||
511 | pcdev->csicr1 = csicr1; | 441 | pcdev->csicr1 = csicr1; |
512 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); | 442 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); |
@@ -540,65 +470,6 @@ static void mx2_camera_remove_device(struct soc_camera_device *icd) | |||
540 | pcdev->icd = NULL; | 470 | pcdev->icd = NULL; |
541 | } | 471 | } |
542 | 472 | ||
543 | static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, | ||
544 | int state) | ||
545 | { | ||
546 | struct vb2_buffer *vb; | ||
547 | struct mx2_buffer *buf; | ||
548 | struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active : | ||
549 | &pcdev->fb2_active; | ||
550 | u32 fb_reg = fb == 1 ? CSIDMASA_FB1 : CSIDMASA_FB2; | ||
551 | unsigned long flags; | ||
552 | |||
553 | spin_lock_irqsave(&pcdev->lock, flags); | ||
554 | |||
555 | if (*fb_active == NULL) | ||
556 | goto out; | ||
557 | |||
558 | vb = &(*fb_active)->vb; | ||
559 | dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, | ||
560 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); | ||
561 | |||
562 | do_gettimeofday(&vb->v4l2_buf.timestamp); | ||
563 | vb->v4l2_buf.sequence++; | ||
564 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | ||
565 | |||
566 | if (list_empty(&pcdev->capture)) { | ||
567 | buf = NULL; | ||
568 | writel(0, pcdev->base_csi + fb_reg); | ||
569 | } else { | ||
570 | buf = list_first_entry(&pcdev->capture, struct mx2_buffer, | ||
571 | internal.queue); | ||
572 | vb = &buf->vb; | ||
573 | list_del(&buf->internal.queue); | ||
574 | buf->state = MX2_STATE_ACTIVE; | ||
575 | writel(vb2_dma_contig_plane_dma_addr(vb, 0), | ||
576 | pcdev->base_csi + fb_reg); | ||
577 | } | ||
578 | |||
579 | *fb_active = buf; | ||
580 | |||
581 | out: | ||
582 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
583 | } | ||
584 | |||
585 | static irqreturn_t mx25_camera_irq(int irq_csi, void *data) | ||
586 | { | ||
587 | struct mx2_camera_dev *pcdev = data; | ||
588 | u32 status = readl(pcdev->base_csi + pcdev->reg_csisr); | ||
589 | |||
590 | if (status & CSISR_DMA_TSF_FB1_INT) | ||
591 | mx25_camera_frame_done(pcdev, 1, MX2_STATE_DONE); | ||
592 | else if (status & CSISR_DMA_TSF_FB2_INT) | ||
593 | mx25_camera_frame_done(pcdev, 2, MX2_STATE_DONE); | ||
594 | |||
595 | /* FIXME: handle CSISR_RFF_OR_INT */ | ||
596 | |||
597 | writel(status, pcdev->base_csi + pcdev->reg_csisr); | ||
598 | |||
599 | return IRQ_HANDLED; | ||
600 | } | ||
601 | |||
602 | /* | 473 | /* |
603 | * Videobuf operations | 474 | * Videobuf operations |
604 | */ | 475 | */ |
@@ -676,97 +547,8 @@ static void mx2_videobuf_queue(struct vb2_buffer *vb) | |||
676 | 547 | ||
677 | spin_lock_irqsave(&pcdev->lock, flags); | 548 | spin_lock_irqsave(&pcdev->lock, flags); |
678 | 549 | ||
679 | buf->state = MX2_STATE_QUEUED; | ||
680 | list_add_tail(&buf->internal.queue, &pcdev->capture); | 550 | list_add_tail(&buf->internal.queue, &pcdev->capture); |
681 | 551 | ||
682 | if (is_imx25_camera(pcdev)) { | ||
683 | u32 csicr3, dma_inten = 0; | ||
684 | |||
685 | if (pcdev->fb1_active == NULL) { | ||
686 | writel(vb2_dma_contig_plane_dma_addr(vb, 0), | ||
687 | pcdev->base_csi + CSIDMASA_FB1); | ||
688 | pcdev->fb1_active = buf; | ||
689 | dma_inten = CSICR1_FB1_DMA_INTEN; | ||
690 | } else if (pcdev->fb2_active == NULL) { | ||
691 | writel(vb2_dma_contig_plane_dma_addr(vb, 0), | ||
692 | pcdev->base_csi + CSIDMASA_FB2); | ||
693 | pcdev->fb2_active = buf; | ||
694 | dma_inten = CSICR1_FB2_DMA_INTEN; | ||
695 | } | ||
696 | |||
697 | if (dma_inten) { | ||
698 | list_del(&buf->internal.queue); | ||
699 | buf->state = MX2_STATE_ACTIVE; | ||
700 | |||
701 | csicr3 = readl(pcdev->base_csi + pcdev->reg_csicr3); | ||
702 | |||
703 | /* Reflash DMA */ | ||
704 | writel(csicr3 | CSICR3_DMA_REFLASH_RFF, | ||
705 | pcdev->base_csi + pcdev->reg_csicr3); | ||
706 | |||
707 | /* clear & enable interrupts */ | ||
708 | writel(dma_inten, pcdev->base_csi + pcdev->reg_csisr); | ||
709 | pcdev->csicr1 |= dma_inten; | ||
710 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); | ||
711 | |||
712 | /* enable DMA */ | ||
713 | csicr3 |= CSICR3_DMA_REQ_EN_RFF | CSICR3_RXFF_LEVEL(1); | ||
714 | writel(csicr3, pcdev->base_csi + pcdev->reg_csicr3); | ||
715 | } | ||
716 | } | ||
717 | |||
718 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
719 | } | ||
720 | |||
721 | static void mx2_videobuf_release(struct vb2_buffer *vb) | ||
722 | { | ||
723 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); | ||
724 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
725 | struct mx2_camera_dev *pcdev = ici->priv; | ||
726 | struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); | ||
727 | unsigned long flags; | ||
728 | |||
729 | #ifdef DEBUG | ||
730 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, | ||
731 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); | ||
732 | |||
733 | switch (buf->state) { | ||
734 | case MX2_STATE_ACTIVE: | ||
735 | dev_info(icd->parent, "%s (active)\n", __func__); | ||
736 | break; | ||
737 | case MX2_STATE_QUEUED: | ||
738 | dev_info(icd->parent, "%s (queued)\n", __func__); | ||
739 | break; | ||
740 | default: | ||
741 | dev_info(icd->parent, "%s (unknown) %d\n", __func__, | ||
742 | buf->state); | ||
743 | break; | ||
744 | } | ||
745 | #endif | ||
746 | |||
747 | /* | ||
748 | * Terminate only queued but inactive buffers. Active buffers are | ||
749 | * released when they become inactive after videobuf_waiton(). | ||
750 | * | ||
751 | * FIXME: implement forced termination of active buffers for mx27 and | ||
752 | * mx27 eMMA, so that the user won't get stuck in an uninterruptible | ||
753 | * state. This requires a specific handling for each of the these DMA | ||
754 | * types. | ||
755 | */ | ||
756 | |||
757 | spin_lock_irqsave(&pcdev->lock, flags); | ||
758 | if (is_imx25_camera(pcdev) && buf->state == MX2_STATE_ACTIVE) { | ||
759 | if (pcdev->fb1_active == buf) { | ||
760 | pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN; | ||
761 | writel(0, pcdev->base_csi + CSIDMASA_FB1); | ||
762 | pcdev->fb1_active = NULL; | ||
763 | } else if (pcdev->fb2_active == buf) { | ||
764 | pcdev->csicr1 &= ~CSICR1_FB2_DMA_INTEN; | ||
765 | writel(0, pcdev->base_csi + CSIDMASA_FB2); | ||
766 | pcdev->fb2_active = NULL; | ||
767 | } | ||
768 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); | ||
769 | } | ||
770 | spin_unlock_irqrestore(&pcdev->lock, flags); | 552 | spin_unlock_irqrestore(&pcdev->lock, flags); |
771 | } | 553 | } |
772 | 554 | ||
@@ -877,91 +659,87 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) | |||
877 | struct mx2_buffer *buf; | 659 | struct mx2_buffer *buf; |
878 | unsigned long phys; | 660 | unsigned long phys; |
879 | int bytesperline; | 661 | int bytesperline; |
662 | unsigned long flags; | ||
880 | 663 | ||
881 | if (is_imx27_camera(pcdev)) { | 664 | if (count < 2) |
882 | unsigned long flags; | 665 | return -EINVAL; |
883 | if (count < 2) | ||
884 | return -EINVAL; | ||
885 | 666 | ||
886 | spin_lock_irqsave(&pcdev->lock, flags); | 667 | spin_lock_irqsave(&pcdev->lock, flags); |
887 | 668 | ||
888 | buf = list_first_entry(&pcdev->capture, struct mx2_buffer, | 669 | buf = list_first_entry(&pcdev->capture, struct mx2_buffer, |
889 | internal.queue); | 670 | internal.queue); |
890 | buf->internal.bufnum = 0; | 671 | buf->internal.bufnum = 0; |
891 | vb = &buf->vb; | 672 | vb = &buf->vb; |
892 | buf->state = MX2_STATE_ACTIVE; | ||
893 | 673 | ||
894 | phys = vb2_dma_contig_plane_dma_addr(vb, 0); | 674 | phys = vb2_dma_contig_plane_dma_addr(vb, 0); |
895 | mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); | 675 | mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); |
896 | list_move_tail(pcdev->capture.next, &pcdev->active_bufs); | 676 | list_move_tail(pcdev->capture.next, &pcdev->active_bufs); |
897 | 677 | ||
898 | buf = list_first_entry(&pcdev->capture, struct mx2_buffer, | 678 | buf = list_first_entry(&pcdev->capture, struct mx2_buffer, |
899 | internal.queue); | 679 | internal.queue); |
900 | buf->internal.bufnum = 1; | 680 | buf->internal.bufnum = 1; |
901 | vb = &buf->vb; | 681 | vb = &buf->vb; |
902 | buf->state = MX2_STATE_ACTIVE; | ||
903 | 682 | ||
904 | phys = vb2_dma_contig_plane_dma_addr(vb, 0); | 683 | phys = vb2_dma_contig_plane_dma_addr(vb, 0); |
905 | mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); | 684 | mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); |
906 | list_move_tail(pcdev->capture.next, &pcdev->active_bufs); | 685 | list_move_tail(pcdev->capture.next, &pcdev->active_bufs); |
907 | |||
908 | bytesperline = soc_mbus_bytes_per_line(icd->user_width, | ||
909 | icd->current_fmt->host_fmt); | ||
910 | if (bytesperline < 0) { | ||
911 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
912 | return bytesperline; | ||
913 | } | ||
914 | 686 | ||
915 | /* | 687 | bytesperline = soc_mbus_bytes_per_line(icd->user_width, |
916 | * I didn't manage to properly enable/disable the prp | 688 | icd->current_fmt->host_fmt); |
917 | * on a per frame basis during running transfers, | 689 | if (bytesperline < 0) { |
918 | * thus we allocate a buffer here and use it to | 690 | spin_unlock_irqrestore(&pcdev->lock, flags); |
919 | * discard frames when no buffer is available. | 691 | return bytesperline; |
920 | * Feel free to work on this ;) | 692 | } |
921 | */ | ||
922 | pcdev->discard_size = icd->user_height * bytesperline; | ||
923 | pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, | ||
924 | pcdev->discard_size, &pcdev->discard_buffer_dma, | ||
925 | GFP_KERNEL); | ||
926 | if (!pcdev->discard_buffer) { | ||
927 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
928 | return -ENOMEM; | ||
929 | } | ||
930 | 693 | ||
931 | pcdev->buf_discard[0].discard = true; | 694 | /* |
932 | list_add_tail(&pcdev->buf_discard[0].queue, | 695 | * I didn't manage to properly enable/disable the prp |
933 | &pcdev->discard); | 696 | * on a per frame basis during running transfers, |
697 | * thus we allocate a buffer here and use it to | ||
698 | * discard frames when no buffer is available. | ||
699 | * Feel free to work on this ;) | ||
700 | */ | ||
701 | pcdev->discard_size = icd->user_height * bytesperline; | ||
702 | pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, | ||
703 | pcdev->discard_size, | ||
704 | &pcdev->discard_buffer_dma, GFP_ATOMIC); | ||
705 | if (!pcdev->discard_buffer) { | ||
706 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
707 | return -ENOMEM; | ||
708 | } | ||
934 | 709 | ||
935 | pcdev->buf_discard[1].discard = true; | 710 | pcdev->buf_discard[0].discard = true; |
936 | list_add_tail(&pcdev->buf_discard[1].queue, | 711 | list_add_tail(&pcdev->buf_discard[0].queue, |
937 | &pcdev->discard); | 712 | &pcdev->discard); |
938 | 713 | ||
939 | mx2_prp_resize_commit(pcdev); | 714 | pcdev->buf_discard[1].discard = true; |
715 | list_add_tail(&pcdev->buf_discard[1].queue, | ||
716 | &pcdev->discard); | ||
940 | 717 | ||
941 | mx27_camera_emma_buf_init(icd, bytesperline); | 718 | mx2_prp_resize_commit(pcdev); |
942 | 719 | ||
943 | if (prp->cfg.channel == 1) { | 720 | mx27_camera_emma_buf_init(icd, bytesperline); |
944 | writel(PRP_CNTL_CH1EN | | 721 | |
945 | PRP_CNTL_CSIEN | | 722 | if (prp->cfg.channel == 1) { |
946 | prp->cfg.in_fmt | | 723 | writel(PRP_CNTL_CH1EN | |
947 | prp->cfg.out_fmt | | 724 | PRP_CNTL_CSIEN | |
948 | PRP_CNTL_CH1_LEN | | 725 | prp->cfg.in_fmt | |
949 | PRP_CNTL_CH1BYP | | 726 | prp->cfg.out_fmt | |
950 | PRP_CNTL_CH1_TSKIP(0) | | 727 | PRP_CNTL_CH1_LEN | |
951 | PRP_CNTL_IN_TSKIP(0), | 728 | PRP_CNTL_CH1BYP | |
952 | pcdev->base_emma + PRP_CNTL); | 729 | PRP_CNTL_CH1_TSKIP(0) | |
953 | } else { | 730 | PRP_CNTL_IN_TSKIP(0), |
954 | writel(PRP_CNTL_CH2EN | | 731 | pcdev->base_emma + PRP_CNTL); |
955 | PRP_CNTL_CSIEN | | 732 | } else { |
956 | prp->cfg.in_fmt | | 733 | writel(PRP_CNTL_CH2EN | |
957 | prp->cfg.out_fmt | | 734 | PRP_CNTL_CSIEN | |
958 | PRP_CNTL_CH2_LEN | | 735 | prp->cfg.in_fmt | |
959 | PRP_CNTL_CH2_TSKIP(0) | | 736 | prp->cfg.out_fmt | |
960 | PRP_CNTL_IN_TSKIP(0), | 737 | PRP_CNTL_CH2_LEN | |
961 | pcdev->base_emma + PRP_CNTL); | 738 | PRP_CNTL_CH2_TSKIP(0) | |
962 | } | 739 | PRP_CNTL_IN_TSKIP(0), |
963 | spin_unlock_irqrestore(&pcdev->lock, flags); | 740 | pcdev->base_emma + PRP_CNTL); |
964 | } | 741 | } |
742 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
965 | 743 | ||
966 | return 0; | 744 | return 0; |
967 | } | 745 | } |
@@ -977,29 +755,27 @@ static int mx2_stop_streaming(struct vb2_queue *q) | |||
977 | void *b; | 755 | void *b; |
978 | u32 cntl; | 756 | u32 cntl; |
979 | 757 | ||
980 | if (is_imx27_camera(pcdev)) { | 758 | spin_lock_irqsave(&pcdev->lock, flags); |
981 | spin_lock_irqsave(&pcdev->lock, flags); | ||
982 | 759 | ||
983 | cntl = readl(pcdev->base_emma + PRP_CNTL); | 760 | cntl = readl(pcdev->base_emma + PRP_CNTL); |
984 | if (prp->cfg.channel == 1) { | 761 | if (prp->cfg.channel == 1) { |
985 | writel(cntl & ~PRP_CNTL_CH1EN, | 762 | writel(cntl & ~PRP_CNTL_CH1EN, |
986 | pcdev->base_emma + PRP_CNTL); | 763 | pcdev->base_emma + PRP_CNTL); |
987 | } else { | 764 | } else { |
988 | writel(cntl & ~PRP_CNTL_CH2EN, | 765 | writel(cntl & ~PRP_CNTL_CH2EN, |
989 | pcdev->base_emma + PRP_CNTL); | 766 | pcdev->base_emma + PRP_CNTL); |
990 | } | 767 | } |
991 | INIT_LIST_HEAD(&pcdev->capture); | 768 | INIT_LIST_HEAD(&pcdev->capture); |
992 | INIT_LIST_HEAD(&pcdev->active_bufs); | 769 | INIT_LIST_HEAD(&pcdev->active_bufs); |
993 | INIT_LIST_HEAD(&pcdev->discard); | 770 | INIT_LIST_HEAD(&pcdev->discard); |
994 | 771 | ||
995 | b = pcdev->discard_buffer; | 772 | b = pcdev->discard_buffer; |
996 | pcdev->discard_buffer = NULL; | 773 | pcdev->discard_buffer = NULL; |
997 | 774 | ||
998 | spin_unlock_irqrestore(&pcdev->lock, flags); | 775 | spin_unlock_irqrestore(&pcdev->lock, flags); |
999 | 776 | ||
1000 | dma_free_coherent(ici->v4l2_dev.dev, | 777 | dma_free_coherent(ici->v4l2_dev.dev, |
1001 | pcdev->discard_size, b, pcdev->discard_buffer_dma); | 778 | pcdev->discard_size, b, pcdev->discard_buffer_dma); |
1002 | } | ||
1003 | 779 | ||
1004 | return 0; | 780 | return 0; |
1005 | } | 781 | } |
@@ -1008,7 +784,6 @@ static struct vb2_ops mx2_videobuf_ops = { | |||
1008 | .queue_setup = mx2_videobuf_setup, | 784 | .queue_setup = mx2_videobuf_setup, |
1009 | .buf_prepare = mx2_videobuf_prepare, | 785 | .buf_prepare = mx2_videobuf_prepare, |
1010 | .buf_queue = mx2_videobuf_queue, | 786 | .buf_queue = mx2_videobuf_queue, |
1011 | .buf_cleanup = mx2_videobuf_release, | ||
1012 | .start_streaming = mx2_start_streaming, | 787 | .start_streaming = mx2_start_streaming, |
1013 | .stop_streaming = mx2_stop_streaming, | 788 | .stop_streaming = mx2_stop_streaming, |
1014 | }; | 789 | }; |
@@ -1129,16 +904,9 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd) | |||
1129 | if (bytesperline < 0) | 904 | if (bytesperline < 0) |
1130 | return bytesperline; | 905 | return bytesperline; |
1131 | 906 | ||
1132 | if (is_imx27_camera(pcdev)) { | 907 | ret = mx27_camera_emma_prp_reset(pcdev); |
1133 | ret = mx27_camera_emma_prp_reset(pcdev); | 908 | if (ret) |
1134 | if (ret) | 909 | return ret; |
1135 | return ret; | ||
1136 | } else if (is_imx25_camera(pcdev)) { | ||
1137 | writel((bytesperline * icd->user_height) >> 2, | ||
1138 | pcdev->base_csi + CSIRXCNT); | ||
1139 | writel((bytesperline << 16) | icd->user_height, | ||
1140 | pcdev->base_csi + CSIIMAG_PARA); | ||
1141 | } | ||
1142 | 910 | ||
1143 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); | 911 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); |
1144 | 912 | ||
@@ -1425,7 +1193,6 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd, | |||
1425 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 1193 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
1426 | struct mx2_camera_dev *pcdev = ici->priv; | 1194 | struct mx2_camera_dev *pcdev = ici->priv; |
1427 | struct mx2_fmt_cfg *emma_prp; | 1195 | struct mx2_fmt_cfg *emma_prp; |
1428 | unsigned int width_limit; | ||
1429 | int ret; | 1196 | int ret; |
1430 | 1197 | ||
1431 | dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", | 1198 | dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", |
@@ -1437,40 +1204,11 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd, | |||
1437 | return -EINVAL; | 1204 | return -EINVAL; |
1438 | } | 1205 | } |
1439 | 1206 | ||
1440 | /* FIXME: implement MX27 limits */ | 1207 | /* |
1441 | 1208 | * limit to MX27 hardware capabilities: width must be a multiple of 8 as | |
1442 | /* limit to MX25 hardware capabilities */ | 1209 | * requested by the CSI. (Table 39-2 in the i.MX27 Reference Manual). |
1443 | if (is_imx25_camera(pcdev)) { | 1210 | */ |
1444 | if (xlate->host_fmt->bits_per_sample <= 8) | 1211 | pix->width &= ~0x7; |
1445 | width_limit = 0xffff * 4; | ||
1446 | else | ||
1447 | width_limit = 0xffff * 2; | ||
1448 | /* CSIIMAG_PARA limit */ | ||
1449 | if (pix->width > width_limit) | ||
1450 | pix->width = width_limit; | ||
1451 | if (pix->height > 0xffff) | ||
1452 | pix->height = 0xffff; | ||
1453 | |||
1454 | pix->bytesperline = soc_mbus_bytes_per_line(pix->width, | ||
1455 | xlate->host_fmt); | ||
1456 | if (pix->bytesperline < 0) | ||
1457 | return pix->bytesperline; | ||
1458 | pix->sizeimage = soc_mbus_image_size(xlate->host_fmt, | ||
1459 | pix->bytesperline, pix->height); | ||
1460 | /* Check against the CSIRXCNT limit */ | ||
1461 | if (pix->sizeimage > 4 * 0x3ffff) { | ||
1462 | /* Adjust geometry, preserve aspect ratio */ | ||
1463 | unsigned int new_height = int_sqrt(div_u64(0x3ffffULL * | ||
1464 | 4 * pix->height, pix->bytesperline)); | ||
1465 | pix->width = new_height * pix->width / pix->height; | ||
1466 | pix->height = new_height; | ||
1467 | pix->bytesperline = soc_mbus_bytes_per_line(pix->width, | ||
1468 | xlate->host_fmt); | ||
1469 | BUG_ON(pix->bytesperline < 0); | ||
1470 | pix->sizeimage = soc_mbus_image_size(xlate->host_fmt, | ||
1471 | pix->bytesperline, pix->height); | ||
1472 | } | ||
1473 | } | ||
1474 | 1212 | ||
1475 | /* limit to sensor capabilities */ | 1213 | /* limit to sensor capabilities */ |
1476 | mf.width = pix->width; | 1214 | mf.width = pix->width; |
@@ -1488,7 +1226,7 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd, | |||
1488 | 1226 | ||
1489 | /* If the sensor does not support image size try PrP resizing */ | 1227 | /* If the sensor does not support image size try PrP resizing */ |
1490 | emma_prp = mx27_emma_prp_get_format(xlate->code, | 1228 | emma_prp = mx27_emma_prp_get_format(xlate->code, |
1491 | xlate->host_fmt->fourcc); | 1229 | xlate->host_fmt->fourcc); |
1492 | 1230 | ||
1493 | if ((mf.width != pix->width || mf.height != pix->height) && | 1231 | if ((mf.width != pix->width || mf.height != pix->height) && |
1494 | emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { | 1232 | emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { |
@@ -1600,7 +1338,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | |||
1600 | vb2_get_plane_payload(vb, 0)); | 1338 | vb2_get_plane_payload(vb, 0)); |
1601 | 1339 | ||
1602 | list_del_init(&buf->internal.queue); | 1340 | list_del_init(&buf->internal.queue); |
1603 | do_gettimeofday(&vb->v4l2_buf.timestamp); | 1341 | v4l2_get_timestamp(&vb->v4l2_buf.timestamp); |
1604 | vb->v4l2_buf.sequence = pcdev->frame_count; | 1342 | vb->v4l2_buf.sequence = pcdev->frame_count; |
1605 | if (err) | 1343 | if (err) |
1606 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); | 1344 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); |
@@ -1634,7 +1372,6 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | |||
1634 | list_move_tail(pcdev->capture.next, &pcdev->active_bufs); | 1372 | list_move_tail(pcdev->capture.next, &pcdev->active_bufs); |
1635 | 1373 | ||
1636 | vb = &buf->vb; | 1374 | vb = &buf->vb; |
1637 | buf->state = MX2_STATE_ACTIVE; | ||
1638 | 1375 | ||
1639 | phys = vb2_dma_contig_plane_dma_addr(vb, 0); | 1376 | phys = vb2_dma_contig_plane_dma_addr(vb, 0); |
1640 | mx27_update_emma_buf(pcdev, phys, bufnum); | 1377 | mx27_update_emma_buf(pcdev, phys, bufnum); |
@@ -1774,20 +1511,6 @@ static int mx2_camera_probe(struct platform_device *pdev) | |||
1774 | goto exit; | 1511 | goto exit; |
1775 | } | 1512 | } |
1776 | 1513 | ||
1777 | pcdev->devtype = pdev->id_entry->driver_data; | ||
1778 | switch (pcdev->devtype) { | ||
1779 | case IMX25_CAMERA: | ||
1780 | pcdev->reg_csisr = CSISR_IMX25; | ||
1781 | pcdev->reg_csicr3 = CSICR3_IMX25; | ||
1782 | break; | ||
1783 | case IMX27_CAMERA: | ||
1784 | pcdev->reg_csisr = CSISR_IMX27; | ||
1785 | pcdev->reg_csicr3 = CSICR3_IMX27; | ||
1786 | break; | ||
1787 | default: | ||
1788 | break; | ||
1789 | } | ||
1790 | |||
1791 | pcdev->clk_csi_ahb = devm_clk_get(&pdev->dev, "ahb"); | 1514 | pcdev->clk_csi_ahb = devm_clk_get(&pdev->dev, "ahb"); |
1792 | if (IS_ERR(pcdev->clk_csi_ahb)) { | 1515 | if (IS_ERR(pcdev->clk_csi_ahb)) { |
1793 | dev_err(&pdev->dev, "Could not get csi ahb clock\n"); | 1516 | dev_err(&pdev->dev, "Could not get csi ahb clock\n"); |
@@ -1833,20 +1556,9 @@ static int mx2_camera_probe(struct platform_device *pdev) | |||
1833 | pcdev->dev = &pdev->dev; | 1556 | pcdev->dev = &pdev->dev; |
1834 | platform_set_drvdata(pdev, pcdev); | 1557 | platform_set_drvdata(pdev, pcdev); |
1835 | 1558 | ||
1836 | if (is_imx25_camera(pcdev)) { | 1559 | err = mx27_camera_emma_init(pdev); |
1837 | err = devm_request_irq(&pdev->dev, irq_csi, mx25_camera_irq, 0, | 1560 | if (err) |
1838 | MX2_CAM_DRV_NAME, pcdev); | 1561 | goto exit; |
1839 | if (err) { | ||
1840 | dev_err(pcdev->dev, "Camera interrupt register failed \n"); | ||
1841 | goto exit; | ||
1842 | } | ||
1843 | } | ||
1844 | |||
1845 | if (is_imx27_camera(pcdev)) { | ||
1846 | err = mx27_camera_emma_init(pdev); | ||
1847 | if (err) | ||
1848 | goto exit; | ||
1849 | } | ||
1850 | 1562 | ||
1851 | /* | 1563 | /* |
1852 | * We're done with drvdata here. Clear the pointer so that | 1564 | * We're done with drvdata here. Clear the pointer so that |
@@ -1859,8 +1571,6 @@ static int mx2_camera_probe(struct platform_device *pdev) | |||
1859 | pcdev->soc_host.priv = pcdev; | 1571 | pcdev->soc_host.priv = pcdev; |
1860 | pcdev->soc_host.v4l2_dev.dev = &pdev->dev; | 1572 | pcdev->soc_host.v4l2_dev.dev = &pdev->dev; |
1861 | pcdev->soc_host.nr = pdev->id; | 1573 | pcdev->soc_host.nr = pdev->id; |
1862 | if (is_imx25_camera(pcdev)) | ||
1863 | pcdev->soc_host.capabilities = SOCAM_HOST_CAP_STRIDE; | ||
1864 | 1574 | ||
1865 | pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | 1575 | pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); |
1866 | if (IS_ERR(pcdev->alloc_ctx)) { | 1576 | if (IS_ERR(pcdev->alloc_ctx)) { |
@@ -1879,10 +1589,8 @@ static int mx2_camera_probe(struct platform_device *pdev) | |||
1879 | exit_free_emma: | 1589 | exit_free_emma: |
1880 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | 1590 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); |
1881 | eallocctx: | 1591 | eallocctx: |
1882 | if (is_imx27_camera(pcdev)) { | 1592 | clk_disable_unprepare(pcdev->clk_emma_ipg); |
1883 | clk_disable_unprepare(pcdev->clk_emma_ipg); | 1593 | clk_disable_unprepare(pcdev->clk_emma_ahb); |
1884 | clk_disable_unprepare(pcdev->clk_emma_ahb); | ||
1885 | } | ||
1886 | exit: | 1594 | exit: |
1887 | return err; | 1595 | return err; |
1888 | } | 1596 | } |
@@ -1897,10 +1605,8 @@ static int mx2_camera_remove(struct platform_device *pdev) | |||
1897 | 1605 | ||
1898 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | 1606 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); |
1899 | 1607 | ||
1900 | if (is_imx27_camera(pcdev)) { | 1608 | clk_disable_unprepare(pcdev->clk_emma_ipg); |
1901 | clk_disable_unprepare(pcdev->clk_emma_ipg); | 1609 | clk_disable_unprepare(pcdev->clk_emma_ahb); |
1902 | clk_disable_unprepare(pcdev->clk_emma_ahb); | ||
1903 | } | ||
1904 | 1610 | ||
1905 | dev_info(&pdev->dev, "MX2 Camera driver unloaded\n"); | 1611 | dev_info(&pdev->dev, "MX2 Camera driver unloaded\n"); |
1906 | 1612 | ||
@@ -1913,23 +1619,12 @@ static struct platform_driver mx2_camera_driver = { | |||
1913 | }, | 1619 | }, |
1914 | .id_table = mx2_camera_devtype, | 1620 | .id_table = mx2_camera_devtype, |
1915 | .remove = mx2_camera_remove, | 1621 | .remove = mx2_camera_remove, |
1622 | .probe = mx2_camera_probe, | ||
1916 | }; | 1623 | }; |
1917 | 1624 | ||
1625 | module_platform_driver(mx2_camera_driver); | ||
1918 | 1626 | ||
1919 | static int __init mx2_camera_init(void) | 1627 | MODULE_DESCRIPTION("i.MX27 SoC Camera Host driver"); |
1920 | { | ||
1921 | return platform_driver_probe(&mx2_camera_driver, &mx2_camera_probe); | ||
1922 | } | ||
1923 | |||
1924 | static void __exit mx2_camera_exit(void) | ||
1925 | { | ||
1926 | return platform_driver_unregister(&mx2_camera_driver); | ||
1927 | } | ||
1928 | |||
1929 | module_init(mx2_camera_init); | ||
1930 | module_exit(mx2_camera_exit); | ||
1931 | |||
1932 | MODULE_DESCRIPTION("i.MX27/i.MX25 SoC Camera Host driver"); | ||
1933 | MODULE_AUTHOR("Sascha Hauer <sha@pengutronix.de>"); | 1628 | MODULE_AUTHOR("Sascha Hauer <sha@pengutronix.de>"); |
1934 | MODULE_LICENSE("GPL"); | 1629 | MODULE_LICENSE("GPL"); |
1935 | MODULE_VERSION(MX2_CAM_VERSION); | 1630 | MODULE_VERSION(MX2_CAM_VERSION); |
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 45aef1053a49..f5cbb92db545 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c | |||
@@ -156,7 +156,7 @@ static void mx3_cam_dma_done(void *arg) | |||
156 | struct mx3_camera_buffer *buf = to_mx3_vb(vb); | 156 | struct mx3_camera_buffer *buf = to_mx3_vb(vb); |
157 | 157 | ||
158 | list_del_init(&buf->queue); | 158 | list_del_init(&buf->queue); |
159 | do_gettimeofday(&vb->v4l2_buf.timestamp); | 159 | v4l2_get_timestamp(&vb->v4l2_buf.timestamp); |
160 | vb->v4l2_buf.field = mx3_cam->field; | 160 | vb->v4l2_buf.field = mx3_cam->field; |
161 | vb->v4l2_buf.sequence = mx3_cam->sequence++; | 161 | vb->v4l2_buf.sequence = mx3_cam->sequence++; |
162 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | 162 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); |
@@ -510,7 +510,7 @@ static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam, | |||
510 | clk_set_rate(mx3_cam->clk, rate); | 510 | clk_set_rate(mx3_cam->clk, rate); |
511 | } | 511 | } |
512 | 512 | ||
513 | /* Called with .video_lock held */ | 513 | /* Called with .host_lock held */ |
514 | static int mx3_camera_add_device(struct soc_camera_device *icd) | 514 | static int mx3_camera_add_device(struct soc_camera_device *icd) |
515 | { | 515 | { |
516 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 516 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
@@ -530,7 +530,7 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) | |||
530 | return 0; | 530 | return 0; |
531 | } | 531 | } |
532 | 532 | ||
533 | /* Called with .video_lock held */ | 533 | /* Called with .host_lock held */ |
534 | static void mx3_camera_remove_device(struct soc_camera_device *icd) | 534 | static void mx3_camera_remove_device(struct soc_camera_device *icd) |
535 | { | 535 | { |
536 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 536 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c index 39a77f0b8860..2547bf88f79f 100644 --- a/drivers/media/platform/soc_camera/omap1_camera.c +++ b/drivers/media/platform/soc_camera/omap1_camera.c | |||
@@ -592,7 +592,7 @@ static void videobuf_done(struct omap1_cam_dev *pcdev, | |||
592 | suspend_capture(pcdev); | 592 | suspend_capture(pcdev); |
593 | } | 593 | } |
594 | vb->state = result; | 594 | vb->state = result; |
595 | do_gettimeofday(&vb->ts); | 595 | v4l2_get_timestamp(&vb->ts); |
596 | if (result != VIDEOBUF_ERROR) | 596 | if (result != VIDEOBUF_ERROR) |
597 | vb->field_count++; | 597 | vb->field_count++; |
598 | wake_up(&vb->done); | 598 | wake_up(&vb->done); |
@@ -1383,12 +1383,12 @@ static void omap1_cam_init_videobuf(struct videobuf_queue *q, | |||
1383 | videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops, | 1383 | videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops, |
1384 | icd->parent, &pcdev->lock, | 1384 | icd->parent, &pcdev->lock, |
1385 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, | 1385 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, |
1386 | sizeof(struct omap1_cam_buf), icd, &icd->video_lock); | 1386 | sizeof(struct omap1_cam_buf), icd, &ici->host_lock); |
1387 | else | 1387 | else |
1388 | videobuf_queue_sg_init(q, &omap1_videobuf_ops, | 1388 | videobuf_queue_sg_init(q, &omap1_videobuf_ops, |
1389 | icd->parent, &pcdev->lock, | 1389 | icd->parent, &pcdev->lock, |
1390 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, | 1390 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, |
1391 | sizeof(struct omap1_cam_buf), icd, &icd->video_lock); | 1391 | sizeof(struct omap1_cam_buf), icd, &ici->host_lock); |
1392 | 1392 | ||
1393 | /* use videobuf mode (auto)selected with the module parameter */ | 1393 | /* use videobuf mode (auto)selected with the module parameter */ |
1394 | pcdev->vb_mode = sg_mode ? OMAP1_CAM_DMA_SG : OMAP1_CAM_DMA_CONTIG; | 1394 | pcdev->vb_mode = sg_mode ? OMAP1_CAM_DMA_SG : OMAP1_CAM_DMA_CONTIG; |
diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index 523330d00dee..395e2e043615 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c | |||
@@ -681,7 +681,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, | |||
681 | /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ | 681 | /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ |
682 | list_del_init(&vb->queue); | 682 | list_del_init(&vb->queue); |
683 | vb->state = VIDEOBUF_DONE; | 683 | vb->state = VIDEOBUF_DONE; |
684 | do_gettimeofday(&vb->ts); | 684 | v4l2_get_timestamp(&vb->ts); |
685 | vb->field_count++; | 685 | vb->field_count++; |
686 | wake_up(&vb->done); | 686 | wake_up(&vb->done); |
687 | dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s dequeud buffer (vb=0x%p)\n", | 687 | dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s dequeud buffer (vb=0x%p)\n", |
@@ -842,7 +842,7 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q, | |||
842 | */ | 842 | */ |
843 | videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock, | 843 | videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock, |
844 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, | 844 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, |
845 | sizeof(struct pxa_buffer), icd, &icd->video_lock); | 845 | sizeof(struct pxa_buffer), icd, &ici->host_lock); |
846 | } | 846 | } |
847 | 847 | ||
848 | static u32 mclk_get_divisor(struct platform_device *pdev, | 848 | static u32 mclk_get_divisor(struct platform_device *pdev, |
@@ -958,7 +958,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) | |||
958 | /* | 958 | /* |
959 | * The following two functions absolutely depend on the fact, that | 959 | * The following two functions absolutely depend on the fact, that |
960 | * there can be only one camera on PXA quick capture interface | 960 | * there can be only one camera on PXA quick capture interface |
961 | * Called with .video_lock held | 961 | * Called with .host_lock held |
962 | */ | 962 | */ |
963 | static int pxa_camera_add_device(struct soc_camera_device *icd) | 963 | static int pxa_camera_add_device(struct soc_camera_device *icd) |
964 | { | 964 | { |
@@ -978,7 +978,7 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) | |||
978 | return 0; | 978 | return 0; |
979 | } | 979 | } |
980 | 980 | ||
981 | /* Called with .video_lock held */ | 981 | /* Called with .host_lock held */ |
982 | static void pxa_camera_remove_device(struct soc_camera_device *icd) | 982 | static void pxa_camera_remove_device(struct soc_camera_device *icd) |
983 | { | 983 | { |
984 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 984 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
@@ -1661,23 +1661,18 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
1661 | 1661 | ||
1662 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1662 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1663 | irq = platform_get_irq(pdev, 0); | 1663 | irq = platform_get_irq(pdev, 0); |
1664 | if (!res || irq < 0) { | 1664 | if (!res || irq < 0) |
1665 | err = -ENODEV; | 1665 | return -ENODEV; |
1666 | goto exit; | ||
1667 | } | ||
1668 | 1666 | ||
1669 | pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); | 1667 | pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL); |
1670 | if (!pcdev) { | 1668 | if (!pcdev) { |
1671 | dev_err(&pdev->dev, "Could not allocate pcdev\n"); | 1669 | dev_err(&pdev->dev, "Could not allocate pcdev\n"); |
1672 | err = -ENOMEM; | 1670 | return -ENOMEM; |
1673 | goto exit; | ||
1674 | } | 1671 | } |
1675 | 1672 | ||
1676 | pcdev->clk = clk_get(&pdev->dev, NULL); | 1673 | pcdev->clk = devm_clk_get(&pdev->dev, NULL); |
1677 | if (IS_ERR(pcdev->clk)) { | 1674 | if (IS_ERR(pcdev->clk)) |
1678 | err = PTR_ERR(pcdev->clk); | 1675 | return PTR_ERR(pcdev->clk); |
1679 | goto exit_kfree; | ||
1680 | } | ||
1681 | 1676 | ||
1682 | pcdev->res = res; | 1677 | pcdev->res = res; |
1683 | 1678 | ||
@@ -1715,17 +1710,9 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
1715 | /* | 1710 | /* |
1716 | * Request the regions. | 1711 | * Request the regions. |
1717 | */ | 1712 | */ |
1718 | if (!request_mem_region(res->start, resource_size(res), | 1713 | base = devm_request_and_ioremap(&pdev->dev, res); |
1719 | PXA_CAM_DRV_NAME)) { | 1714 | if (!base) |
1720 | err = -EBUSY; | 1715 | return -ENOMEM; |
1721 | goto exit_clk; | ||
1722 | } | ||
1723 | |||
1724 | base = ioremap(res->start, resource_size(res)); | ||
1725 | if (!base) { | ||
1726 | err = -ENOMEM; | ||
1727 | goto exit_release; | ||
1728 | } | ||
1729 | pcdev->irq = irq; | 1716 | pcdev->irq = irq; |
1730 | pcdev->base = base; | 1717 | pcdev->base = base; |
1731 | 1718 | ||
@@ -1734,7 +1721,7 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
1734 | pxa_camera_dma_irq_y, pcdev); | 1721 | pxa_camera_dma_irq_y, pcdev); |
1735 | if (err < 0) { | 1722 | if (err < 0) { |
1736 | dev_err(&pdev->dev, "Can't request DMA for Y\n"); | 1723 | dev_err(&pdev->dev, "Can't request DMA for Y\n"); |
1737 | goto exit_iounmap; | 1724 | return err; |
1738 | } | 1725 | } |
1739 | pcdev->dma_chans[0] = err; | 1726 | pcdev->dma_chans[0] = err; |
1740 | dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); | 1727 | dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); |
@@ -1762,10 +1749,10 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
1762 | DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD; | 1749 | DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD; |
1763 | 1750 | ||
1764 | /* request irq */ | 1751 | /* request irq */ |
1765 | err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME, | 1752 | err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0, |
1766 | pcdev); | 1753 | PXA_CAM_DRV_NAME, pcdev); |
1767 | if (err) { | 1754 | if (err) { |
1768 | dev_err(&pdev->dev, "Camera interrupt register failed \n"); | 1755 | dev_err(&pdev->dev, "Camera interrupt register failed\n"); |
1769 | goto exit_free_dma; | 1756 | goto exit_free_dma; |
1770 | } | 1757 | } |
1771 | 1758 | ||
@@ -1777,27 +1764,16 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
1777 | 1764 | ||
1778 | err = soc_camera_host_register(&pcdev->soc_host); | 1765 | err = soc_camera_host_register(&pcdev->soc_host); |
1779 | if (err) | 1766 | if (err) |
1780 | goto exit_free_irq; | 1767 | goto exit_free_dma; |
1781 | 1768 | ||
1782 | return 0; | 1769 | return 0; |
1783 | 1770 | ||
1784 | exit_free_irq: | ||
1785 | free_irq(pcdev->irq, pcdev); | ||
1786 | exit_free_dma: | 1771 | exit_free_dma: |
1787 | pxa_free_dma(pcdev->dma_chans[2]); | 1772 | pxa_free_dma(pcdev->dma_chans[2]); |
1788 | exit_free_dma_u: | 1773 | exit_free_dma_u: |
1789 | pxa_free_dma(pcdev->dma_chans[1]); | 1774 | pxa_free_dma(pcdev->dma_chans[1]); |
1790 | exit_free_dma_y: | 1775 | exit_free_dma_y: |
1791 | pxa_free_dma(pcdev->dma_chans[0]); | 1776 | pxa_free_dma(pcdev->dma_chans[0]); |
1792 | exit_iounmap: | ||
1793 | iounmap(base); | ||
1794 | exit_release: | ||
1795 | release_mem_region(res->start, resource_size(res)); | ||
1796 | exit_clk: | ||
1797 | clk_put(pcdev->clk); | ||
1798 | exit_kfree: | ||
1799 | kfree(pcdev); | ||
1800 | exit: | ||
1801 | return err; | 1777 | return err; |
1802 | } | 1778 | } |
1803 | 1779 | ||
@@ -1806,24 +1782,13 @@ static int pxa_camera_remove(struct platform_device *pdev) | |||
1806 | struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); | 1782 | struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); |
1807 | struct pxa_camera_dev *pcdev = container_of(soc_host, | 1783 | struct pxa_camera_dev *pcdev = container_of(soc_host, |
1808 | struct pxa_camera_dev, soc_host); | 1784 | struct pxa_camera_dev, soc_host); |
1809 | struct resource *res; | ||
1810 | |||
1811 | clk_put(pcdev->clk); | ||
1812 | 1785 | ||
1813 | pxa_free_dma(pcdev->dma_chans[0]); | 1786 | pxa_free_dma(pcdev->dma_chans[0]); |
1814 | pxa_free_dma(pcdev->dma_chans[1]); | 1787 | pxa_free_dma(pcdev->dma_chans[1]); |
1815 | pxa_free_dma(pcdev->dma_chans[2]); | 1788 | pxa_free_dma(pcdev->dma_chans[2]); |
1816 | free_irq(pcdev->irq, pcdev); | ||
1817 | 1789 | ||
1818 | soc_camera_host_unregister(soc_host); | 1790 | soc_camera_host_unregister(soc_host); |
1819 | 1791 | ||
1820 | iounmap(pcdev->base); | ||
1821 | |||
1822 | res = pcdev->res; | ||
1823 | release_mem_region(res->start, resource_size(res)); | ||
1824 | |||
1825 | kfree(pcdev); | ||
1826 | |||
1827 | dev_info(&pdev->dev, "PXA Camera driver unloaded\n"); | 1792 | dev_info(&pdev->dev, "PXA Camera driver unloaded\n"); |
1828 | 1793 | ||
1829 | return 0; | 1794 | return 0; |
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index ebbc126e71a6..bb08a46432f4 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | |||
@@ -516,7 +516,7 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) | |||
516 | pcdev->active = NULL; | 516 | pcdev->active = NULL; |
517 | 517 | ||
518 | ret = sh_mobile_ceu_capture(pcdev); | 518 | ret = sh_mobile_ceu_capture(pcdev); |
519 | do_gettimeofday(&vb->v4l2_buf.timestamp); | 519 | v4l2_get_timestamp(&vb->v4l2_buf.timestamp); |
520 | if (!ret) { | 520 | if (!ret) { |
521 | vb->v4l2_buf.field = pcdev->field; | 521 | vb->v4l2_buf.field = pcdev->field; |
522 | vb->v4l2_buf.sequence = pcdev->sequence++; | 522 | vb->v4l2_buf.sequence = pcdev->sequence++; |
@@ -543,7 +543,7 @@ static struct v4l2_subdev *find_csi2(struct sh_mobile_ceu_dev *pcdev) | |||
543 | return NULL; | 543 | return NULL; |
544 | } | 544 | } |
545 | 545 | ||
546 | /* Called with .video_lock held */ | 546 | /* Called with .host_lock held */ |
547 | static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | 547 | static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) |
548 | { | 548 | { |
549 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 549 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
@@ -572,7 +572,7 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
572 | 572 | ||
573 | ret = v4l2_subdev_call(csi2_sd, core, s_power, 1); | 573 | ret = v4l2_subdev_call(csi2_sd, core, s_power, 1); |
574 | if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) { | 574 | if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) { |
575 | pm_runtime_put_sync(ici->v4l2_dev.dev); | 575 | pm_runtime_put(ici->v4l2_dev.dev); |
576 | return ret; | 576 | return ret; |
577 | } | 577 | } |
578 | 578 | ||
@@ -587,7 +587,7 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
587 | return 0; | 587 | return 0; |
588 | } | 588 | } |
589 | 589 | ||
590 | /* Called with .video_lock held */ | 590 | /* Called with .host_lock held */ |
591 | static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | 591 | static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) |
592 | { | 592 | { |
593 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 593 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
@@ -612,7 +612,7 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
612 | } | 612 | } |
613 | spin_unlock_irq(&pcdev->lock); | 613 | spin_unlock_irq(&pcdev->lock); |
614 | 614 | ||
615 | pm_runtime_put_sync(ici->v4l2_dev.dev); | 615 | pm_runtime_put(ici->v4l2_dev.dev); |
616 | 616 | ||
617 | dev_info(icd->parent, | 617 | dev_info(icd->parent, |
618 | "SuperH Mobile CEU driver detached from camera %d\n", | 618 | "SuperH Mobile CEU driver detached from camera %d\n", |
@@ -1064,7 +1064,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int | |||
1064 | 1064 | ||
1065 | /* Add our control */ | 1065 | /* Add our control */ |
1066 | v4l2_ctrl_new_std(&icd->ctrl_handler, &sh_mobile_ceu_ctrl_ops, | 1066 | v4l2_ctrl_new_std(&icd->ctrl_handler, &sh_mobile_ceu_ctrl_ops, |
1067 | V4L2_CID_SHARPNESS, 0, 1, 1, 0); | 1067 | V4L2_CID_SHARPNESS, 0, 1, 1, 1); |
1068 | if (icd->ctrl_handler.error) | 1068 | if (icd->ctrl_handler.error) |
1069 | return icd->ctrl_handler.error; | 1069 | return icd->ctrl_handler.error; |
1070 | 1070 | ||
@@ -2088,15 +2088,13 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) | |||
2088 | irq = platform_get_irq(pdev, 0); | 2088 | irq = platform_get_irq(pdev, 0); |
2089 | if (!res || (int)irq <= 0) { | 2089 | if (!res || (int)irq <= 0) { |
2090 | dev_err(&pdev->dev, "Not enough CEU platform resources.\n"); | 2090 | dev_err(&pdev->dev, "Not enough CEU platform resources.\n"); |
2091 | err = -ENODEV; | 2091 | return -ENODEV; |
2092 | goto exit; | ||
2093 | } | 2092 | } |
2094 | 2093 | ||
2095 | pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); | 2094 | pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL); |
2096 | if (!pcdev) { | 2095 | if (!pcdev) { |
2097 | dev_err(&pdev->dev, "Could not allocate pcdev\n"); | 2096 | dev_err(&pdev->dev, "Could not allocate pcdev\n"); |
2098 | err = -ENOMEM; | 2097 | return -ENOMEM; |
2099 | goto exit; | ||
2100 | } | 2098 | } |
2101 | 2099 | ||
2102 | INIT_LIST_HEAD(&pcdev->capture); | 2100 | INIT_LIST_HEAD(&pcdev->capture); |
@@ -2105,19 +2103,17 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) | |||
2105 | 2103 | ||
2106 | pcdev->pdata = pdev->dev.platform_data; | 2104 | pcdev->pdata = pdev->dev.platform_data; |
2107 | if (!pcdev->pdata) { | 2105 | if (!pcdev->pdata) { |
2108 | err = -EINVAL; | ||
2109 | dev_err(&pdev->dev, "CEU platform data not set.\n"); | 2106 | dev_err(&pdev->dev, "CEU platform data not set.\n"); |
2110 | goto exit_kfree; | 2107 | return -EINVAL; |
2111 | } | 2108 | } |
2112 | 2109 | ||
2113 | pcdev->max_width = pcdev->pdata->max_width ? : 2560; | 2110 | pcdev->max_width = pcdev->pdata->max_width ? : 2560; |
2114 | pcdev->max_height = pcdev->pdata->max_height ? : 1920; | 2111 | pcdev->max_height = pcdev->pdata->max_height ? : 1920; |
2115 | 2112 | ||
2116 | base = ioremap_nocache(res->start, resource_size(res)); | 2113 | base = devm_request_and_ioremap(&pdev->dev, res); |
2117 | if (!base) { | 2114 | if (!base) { |
2118 | err = -ENXIO; | ||
2119 | dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n"); | 2115 | dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n"); |
2120 | goto exit_kfree; | 2116 | return -ENXIO; |
2121 | } | 2117 | } |
2122 | 2118 | ||
2123 | pcdev->irq = irq; | 2119 | pcdev->irq = irq; |
@@ -2133,16 +2129,15 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) | |||
2133 | DMA_MEMORY_EXCLUSIVE); | 2129 | DMA_MEMORY_EXCLUSIVE); |
2134 | if (!err) { | 2130 | if (!err) { |
2135 | dev_err(&pdev->dev, "Unable to declare CEU memory.\n"); | 2131 | dev_err(&pdev->dev, "Unable to declare CEU memory.\n"); |
2136 | err = -ENXIO; | 2132 | return -ENXIO; |
2137 | goto exit_iounmap; | ||
2138 | } | 2133 | } |
2139 | 2134 | ||
2140 | pcdev->video_limit = resource_size(res); | 2135 | pcdev->video_limit = resource_size(res); |
2141 | } | 2136 | } |
2142 | 2137 | ||
2143 | /* request irq */ | 2138 | /* request irq */ |
2144 | err = request_irq(pcdev->irq, sh_mobile_ceu_irq, IRQF_DISABLED, | 2139 | err = devm_request_irq(&pdev->dev, pcdev->irq, sh_mobile_ceu_irq, |
2145 | dev_name(&pdev->dev), pcdev); | 2140 | IRQF_DISABLED, dev_name(&pdev->dev), pcdev); |
2146 | if (err) { | 2141 | if (err) { |
2147 | dev_err(&pdev->dev, "Unable to register CEU interrupt.\n"); | 2142 | dev_err(&pdev->dev, "Unable to register CEU interrupt.\n"); |
2148 | goto exit_release_mem; | 2143 | goto exit_release_mem; |
@@ -2246,15 +2241,9 @@ exit_free_ctx: | |||
2246 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | 2241 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); |
2247 | exit_free_clk: | 2242 | exit_free_clk: |
2248 | pm_runtime_disable(&pdev->dev); | 2243 | pm_runtime_disable(&pdev->dev); |
2249 | free_irq(pcdev->irq, pcdev); | ||
2250 | exit_release_mem: | 2244 | exit_release_mem: |
2251 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) | 2245 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) |
2252 | dma_release_declared_memory(&pdev->dev); | 2246 | dma_release_declared_memory(&pdev->dev); |
2253 | exit_iounmap: | ||
2254 | iounmap(base); | ||
2255 | exit_kfree: | ||
2256 | kfree(pcdev); | ||
2257 | exit: | ||
2258 | return err; | 2247 | return err; |
2259 | } | 2248 | } |
2260 | 2249 | ||
@@ -2267,10 +2256,8 @@ static int sh_mobile_ceu_remove(struct platform_device *pdev) | |||
2267 | 2256 | ||
2268 | soc_camera_host_unregister(soc_host); | 2257 | soc_camera_host_unregister(soc_host); |
2269 | pm_runtime_disable(&pdev->dev); | 2258 | pm_runtime_disable(&pdev->dev); |
2270 | free_irq(pcdev->irq, pcdev); | ||
2271 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) | 2259 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) |
2272 | dma_release_declared_memory(&pdev->dev); | 2260 | dma_release_declared_memory(&pdev->dev); |
2273 | iounmap(pcdev->base); | ||
2274 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | 2261 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); |
2275 | if (csi2_pdev && csi2_pdev->dev.driver) { | 2262 | if (csi2_pdev && csi2_pdev->dev.driver) { |
2276 | struct module *csi2_drv = csi2_pdev->dev.driver->owner; | 2263 | struct module *csi2_drv = csi2_pdev->dev.driver->owner; |
@@ -2279,7 +2266,6 @@ static int sh_mobile_ceu_remove(struct platform_device *pdev) | |||
2279 | platform_device_put(csi2_pdev); | 2266 | platform_device_put(csi2_pdev); |
2280 | module_put(csi2_drv); | 2267 | module_put(csi2_drv); |
2281 | } | 2268 | } |
2282 | kfree(pcdev); | ||
2283 | 2269 | ||
2284 | return 0; | 2270 | return 0; |
2285 | } | 2271 | } |
diff --git a/drivers/media/platform/soc_camera/sh_mobile_csi2.c b/drivers/media/platform/soc_camera/sh_mobile_csi2.c index a17aba9a0104..42c559eb4937 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_csi2.c +++ b/drivers/media/platform/soc_camera/sh_mobile_csi2.c | |||
@@ -318,23 +318,16 @@ static int sh_csi2_probe(struct platform_device *pdev) | |||
318 | return -EINVAL; | 318 | return -EINVAL; |
319 | } | 319 | } |
320 | 320 | ||
321 | priv = kzalloc(sizeof(struct sh_csi2), GFP_KERNEL); | 321 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_csi2), GFP_KERNEL); |
322 | if (!priv) | 322 | if (!priv) |
323 | return -ENOMEM; | 323 | return -ENOMEM; |
324 | 324 | ||
325 | priv->irq = irq; | 325 | priv->irq = irq; |
326 | 326 | ||
327 | if (!request_mem_region(res->start, resource_size(res), pdev->name)) { | 327 | priv->base = devm_request_and_ioremap(&pdev->dev, res); |
328 | dev_err(&pdev->dev, "CSI2 register region already claimed\n"); | ||
329 | ret = -EBUSY; | ||
330 | goto ereqreg; | ||
331 | } | ||
332 | |||
333 | priv->base = ioremap(res->start, resource_size(res)); | ||
334 | if (!priv->base) { | 328 | if (!priv->base) { |
335 | ret = -ENXIO; | ||
336 | dev_err(&pdev->dev, "Unable to ioremap CSI2 registers.\n"); | 329 | dev_err(&pdev->dev, "Unable to ioremap CSI2 registers.\n"); |
337 | goto eremap; | 330 | return -ENXIO; |
338 | } | 331 | } |
339 | 332 | ||
340 | priv->pdev = pdev; | 333 | priv->pdev = pdev; |
@@ -357,11 +350,7 @@ static int sh_csi2_probe(struct platform_device *pdev) | |||
357 | return 0; | 350 | return 0; |
358 | 351 | ||
359 | esdreg: | 352 | esdreg: |
360 | iounmap(priv->base); | 353 | platform_set_drvdata(pdev, NULL); |
361 | eremap: | ||
362 | release_mem_region(res->start, resource_size(res)); | ||
363 | ereqreg: | ||
364 | kfree(priv); | ||
365 | 354 | ||
366 | return ret; | 355 | return ret; |
367 | } | 356 | } |
@@ -369,14 +358,10 @@ ereqreg: | |||
369 | static int sh_csi2_remove(struct platform_device *pdev) | 358 | static int sh_csi2_remove(struct platform_device *pdev) |
370 | { | 359 | { |
371 | struct sh_csi2 *priv = platform_get_drvdata(pdev); | 360 | struct sh_csi2 *priv = platform_get_drvdata(pdev); |
372 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
373 | 361 | ||
374 | v4l2_device_unregister_subdev(&priv->subdev); | 362 | v4l2_device_unregister_subdev(&priv->subdev); |
375 | pm_runtime_disable(&pdev->dev); | 363 | pm_runtime_disable(&pdev->dev); |
376 | iounmap(priv->base); | ||
377 | release_mem_region(res->start, resource_size(res)); | ||
378 | platform_set_drvdata(pdev, NULL); | 364 | platform_set_drvdata(pdev, NULL); |
379 | kfree(priv); | ||
380 | 365 | ||
381 | return 0; | 366 | return 0; |
382 | } | 367 | } |
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 2ec90eae6ba0..8ec98051ea73 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c | |||
@@ -50,22 +50,22 @@ static LIST_HEAD(hosts); | |||
50 | static LIST_HEAD(devices); | 50 | static LIST_HEAD(devices); |
51 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ | 51 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ |
52 | 52 | ||
53 | int soc_camera_power_on(struct device *dev, struct soc_camera_link *icl) | 53 | int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd) |
54 | { | 54 | { |
55 | int ret = regulator_bulk_enable(icl->num_regulators, | 55 | int ret = regulator_bulk_enable(ssdd->num_regulators, |
56 | icl->regulators); | 56 | ssdd->regulators); |
57 | if (ret < 0) { | 57 | if (ret < 0) { |
58 | dev_err(dev, "Cannot enable regulators\n"); | 58 | dev_err(dev, "Cannot enable regulators\n"); |
59 | return ret; | 59 | return ret; |
60 | } | 60 | } |
61 | 61 | ||
62 | if (icl->power) { | 62 | if (ssdd->power) { |
63 | ret = icl->power(dev, 1); | 63 | ret = ssdd->power(dev, 1); |
64 | if (ret < 0) { | 64 | if (ret < 0) { |
65 | dev_err(dev, | 65 | dev_err(dev, |
66 | "Platform failed to power-on the camera.\n"); | 66 | "Platform failed to power-on the camera.\n"); |
67 | regulator_bulk_disable(icl->num_regulators, | 67 | regulator_bulk_disable(ssdd->num_regulators, |
68 | icl->regulators); | 68 | ssdd->regulators); |
69 | } | 69 | } |
70 | } | 70 | } |
71 | 71 | ||
@@ -73,13 +73,13 @@ int soc_camera_power_on(struct device *dev, struct soc_camera_link *icl) | |||
73 | } | 73 | } |
74 | EXPORT_SYMBOL(soc_camera_power_on); | 74 | EXPORT_SYMBOL(soc_camera_power_on); |
75 | 75 | ||
76 | int soc_camera_power_off(struct device *dev, struct soc_camera_link *icl) | 76 | int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd) |
77 | { | 77 | { |
78 | int ret = 0; | 78 | int ret = 0; |
79 | int err; | 79 | int err; |
80 | 80 | ||
81 | if (icl->power) { | 81 | if (ssdd->power) { |
82 | err = icl->power(dev, 0); | 82 | err = ssdd->power(dev, 0); |
83 | if (err < 0) { | 83 | if (err < 0) { |
84 | dev_err(dev, | 84 | dev_err(dev, |
85 | "Platform failed to power-off the camera.\n"); | 85 | "Platform failed to power-off the camera.\n"); |
@@ -87,8 +87,8 @@ int soc_camera_power_off(struct device *dev, struct soc_camera_link *icl) | |||
87 | } | 87 | } |
88 | } | 88 | } |
89 | 89 | ||
90 | err = regulator_bulk_disable(icl->num_regulators, | 90 | err = regulator_bulk_disable(ssdd->num_regulators, |
91 | icl->regulators); | 91 | ssdd->regulators); |
92 | if (err < 0) { | 92 | if (err < 0) { |
93 | dev_err(dev, "Cannot disable regulators\n"); | 93 | dev_err(dev, "Cannot disable regulators\n"); |
94 | ret = ret ? : err; | 94 | ret = ret ? : err; |
@@ -136,29 +136,29 @@ EXPORT_SYMBOL(soc_camera_xlate_by_fourcc); | |||
136 | 136 | ||
137 | /** | 137 | /** |
138 | * soc_camera_apply_board_flags() - apply platform SOCAM_SENSOR_INVERT_* flags | 138 | * soc_camera_apply_board_flags() - apply platform SOCAM_SENSOR_INVERT_* flags |
139 | * @icl: camera platform parameters | 139 | * @ssdd: camera platform parameters |
140 | * @cfg: media bus configuration | 140 | * @cfg: media bus configuration |
141 | * @return: resulting flags | 141 | * @return: resulting flags |
142 | */ | 142 | */ |
143 | unsigned long soc_camera_apply_board_flags(struct soc_camera_link *icl, | 143 | unsigned long soc_camera_apply_board_flags(struct soc_camera_subdev_desc *ssdd, |
144 | const struct v4l2_mbus_config *cfg) | 144 | const struct v4l2_mbus_config *cfg) |
145 | { | 145 | { |
146 | unsigned long f, flags = cfg->flags; | 146 | unsigned long f, flags = cfg->flags; |
147 | 147 | ||
148 | /* If only one of the two polarities is supported, switch to the opposite */ | 148 | /* If only one of the two polarities is supported, switch to the opposite */ |
149 | if (icl->flags & SOCAM_SENSOR_INVERT_HSYNC) { | 149 | if (ssdd->flags & SOCAM_SENSOR_INVERT_HSYNC) { |
150 | f = flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW); | 150 | f = flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW); |
151 | if (f == V4L2_MBUS_HSYNC_ACTIVE_HIGH || f == V4L2_MBUS_HSYNC_ACTIVE_LOW) | 151 | if (f == V4L2_MBUS_HSYNC_ACTIVE_HIGH || f == V4L2_MBUS_HSYNC_ACTIVE_LOW) |
152 | flags ^= V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW; | 152 | flags ^= V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW; |
153 | } | 153 | } |
154 | 154 | ||
155 | if (icl->flags & SOCAM_SENSOR_INVERT_VSYNC) { | 155 | if (ssdd->flags & SOCAM_SENSOR_INVERT_VSYNC) { |
156 | f = flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW); | 156 | f = flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW); |
157 | if (f == V4L2_MBUS_VSYNC_ACTIVE_HIGH || f == V4L2_MBUS_VSYNC_ACTIVE_LOW) | 157 | if (f == V4L2_MBUS_VSYNC_ACTIVE_HIGH || f == V4L2_MBUS_VSYNC_ACTIVE_LOW) |
158 | flags ^= V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW; | 158 | flags ^= V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW; |
159 | } | 159 | } |
160 | 160 | ||
161 | if (icl->flags & SOCAM_SENSOR_INVERT_PCLK) { | 161 | if (ssdd->flags & SOCAM_SENSOR_INVERT_PCLK) { |
162 | f = flags & (V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING); | 162 | f = flags & (V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING); |
163 | if (f == V4L2_MBUS_PCLK_SAMPLE_RISING || f == V4L2_MBUS_PCLK_SAMPLE_FALLING) | 163 | if (f == V4L2_MBUS_PCLK_SAMPLE_RISING || f == V4L2_MBUS_PCLK_SAMPLE_FALLING) |
164 | flags ^= V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING; | 164 | flags ^= V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING; |
@@ -383,7 +383,7 @@ static int soc_camera_prepare_buf(struct file *file, void *priv, | |||
383 | return vb2_prepare_buf(&icd->vb2_vidq, b); | 383 | return vb2_prepare_buf(&icd->vb2_vidq, b); |
384 | } | 384 | } |
385 | 385 | ||
386 | /* Always entered with .video_lock held */ | 386 | /* Always entered with .host_lock held */ |
387 | static int soc_camera_init_user_formats(struct soc_camera_device *icd) | 387 | static int soc_camera_init_user_formats(struct soc_camera_device *icd) |
388 | { | 388 | { |
389 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 389 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
@@ -450,7 +450,7 @@ egfmt: | |||
450 | return ret; | 450 | return ret; |
451 | } | 451 | } |
452 | 452 | ||
453 | /* Always entered with .video_lock held */ | 453 | /* Always entered with .host_lock held */ |
454 | static void soc_camera_free_user_formats(struct soc_camera_device *icd) | 454 | static void soc_camera_free_user_formats(struct soc_camera_device *icd) |
455 | { | 455 | { |
456 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 456 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
@@ -509,7 +509,7 @@ static int soc_camera_open(struct file *file) | |||
509 | { | 509 | { |
510 | struct video_device *vdev = video_devdata(file); | 510 | struct video_device *vdev = video_devdata(file); |
511 | struct soc_camera_device *icd = dev_get_drvdata(vdev->parent); | 511 | struct soc_camera_device *icd = dev_get_drvdata(vdev->parent); |
512 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 512 | struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); |
513 | struct soc_camera_host *ici; | 513 | struct soc_camera_host *ici; |
514 | int ret; | 514 | int ret; |
515 | 515 | ||
@@ -517,9 +517,16 @@ static int soc_camera_open(struct file *file) | |||
517 | /* No device driver attached */ | 517 | /* No device driver attached */ |
518 | return -ENODEV; | 518 | return -ENODEV; |
519 | 519 | ||
520 | /* | ||
521 | * Don't mess with the host during probe: wait until the loop in | ||
522 | * scan_add_host() completes | ||
523 | */ | ||
524 | if (mutex_lock_interruptible(&list_lock)) | ||
525 | return -ERESTARTSYS; | ||
520 | ici = to_soc_camera_host(icd->parent); | 526 | ici = to_soc_camera_host(icd->parent); |
527 | mutex_unlock(&list_lock); | ||
521 | 528 | ||
522 | if (mutex_lock_interruptible(&icd->video_lock)) | 529 | if (mutex_lock_interruptible(&ici->host_lock)) |
523 | return -ERESTARTSYS; | 530 | return -ERESTARTSYS; |
524 | if (!try_module_get(ici->ops->owner)) { | 531 | if (!try_module_get(ici->ops->owner)) { |
525 | dev_err(icd->pdev, "Couldn't lock capture bus driver.\n"); | 532 | dev_err(icd->pdev, "Couldn't lock capture bus driver.\n"); |
@@ -545,13 +552,10 @@ static int soc_camera_open(struct file *file) | |||
545 | }; | 552 | }; |
546 | 553 | ||
547 | /* The camera could have been already on, try to reset */ | 554 | /* The camera could have been already on, try to reset */ |
548 | if (icl->reset) | 555 | if (sdesc->subdev_desc.reset) |
549 | icl->reset(icd->pdev); | 556 | sdesc->subdev_desc.reset(icd->pdev); |
550 | 557 | ||
551 | /* Don't mess with the host during probe */ | ||
552 | mutex_lock(&ici->host_lock); | ||
553 | ret = ici->ops->add(icd); | 558 | ret = ici->ops->add(icd); |
554 | mutex_unlock(&ici->host_lock); | ||
555 | if (ret < 0) { | 559 | if (ret < 0) { |
556 | dev_err(icd->pdev, "Couldn't activate the camera: %d\n", ret); | 560 | dev_err(icd->pdev, "Couldn't activate the camera: %d\n", ret); |
557 | goto eiciadd; | 561 | goto eiciadd; |
@@ -570,7 +574,7 @@ static int soc_camera_open(struct file *file) | |||
570 | * Try to configure with default parameters. Notice: this is the | 574 | * Try to configure with default parameters. Notice: this is the |
571 | * very first open, so, we cannot race against other calls, | 575 | * very first open, so, we cannot race against other calls, |
572 | * apart from someone else calling open() simultaneously, but | 576 | * apart from someone else calling open() simultaneously, but |
573 | * .video_lock is protecting us against it. | 577 | * .host_lock is protecting us against it. |
574 | */ | 578 | */ |
575 | ret = soc_camera_set_fmt(icd, &f); | 579 | ret = soc_camera_set_fmt(icd, &f); |
576 | if (ret < 0) | 580 | if (ret < 0) |
@@ -585,7 +589,7 @@ static int soc_camera_open(struct file *file) | |||
585 | } | 589 | } |
586 | v4l2_ctrl_handler_setup(&icd->ctrl_handler); | 590 | v4l2_ctrl_handler_setup(&icd->ctrl_handler); |
587 | } | 591 | } |
588 | mutex_unlock(&icd->video_lock); | 592 | mutex_unlock(&ici->host_lock); |
589 | 593 | ||
590 | file->private_data = icd; | 594 | file->private_data = icd; |
591 | dev_dbg(icd->pdev, "camera device open\n"); | 595 | dev_dbg(icd->pdev, "camera device open\n"); |
@@ -593,7 +597,7 @@ static int soc_camera_open(struct file *file) | |||
593 | return 0; | 597 | return 0; |
594 | 598 | ||
595 | /* | 599 | /* |
596 | * First four errors are entered with the .video_lock held | 600 | * First four errors are entered with the .host_lock held |
597 | * and use_count == 1 | 601 | * and use_count == 1 |
598 | */ | 602 | */ |
599 | einitvb: | 603 | einitvb: |
@@ -607,7 +611,7 @@ eiciadd: | |||
607 | icd->use_count--; | 611 | icd->use_count--; |
608 | module_put(ici->ops->owner); | 612 | module_put(ici->ops->owner); |
609 | emodule: | 613 | emodule: |
610 | mutex_unlock(&icd->video_lock); | 614 | mutex_unlock(&ici->host_lock); |
611 | 615 | ||
612 | return ret; | 616 | return ret; |
613 | } | 617 | } |
@@ -617,7 +621,7 @@ static int soc_camera_close(struct file *file) | |||
617 | struct soc_camera_device *icd = file->private_data; | 621 | struct soc_camera_device *icd = file->private_data; |
618 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 622 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
619 | 623 | ||
620 | mutex_lock(&icd->video_lock); | 624 | mutex_lock(&ici->host_lock); |
621 | icd->use_count--; | 625 | icd->use_count--; |
622 | if (!icd->use_count) { | 626 | if (!icd->use_count) { |
623 | pm_runtime_suspend(&icd->vdev->dev); | 627 | pm_runtime_suspend(&icd->vdev->dev); |
@@ -632,7 +636,7 @@ static int soc_camera_close(struct file *file) | |||
632 | 636 | ||
633 | if (icd->streamer == file) | 637 | if (icd->streamer == file) |
634 | icd->streamer = NULL; | 638 | icd->streamer = NULL; |
635 | mutex_unlock(&icd->video_lock); | 639 | mutex_unlock(&ici->host_lock); |
636 | 640 | ||
637 | module_put(ici->ops->owner); | 641 | module_put(ici->ops->owner); |
638 | 642 | ||
@@ -669,13 +673,13 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) | |||
669 | if (icd->streamer != file) | 673 | if (icd->streamer != file) |
670 | return -EBUSY; | 674 | return -EBUSY; |
671 | 675 | ||
672 | if (mutex_lock_interruptible(&icd->video_lock)) | 676 | if (mutex_lock_interruptible(&ici->host_lock)) |
673 | return -ERESTARTSYS; | 677 | return -ERESTARTSYS; |
674 | if (ici->ops->init_videobuf) | 678 | if (ici->ops->init_videobuf) |
675 | err = videobuf_mmap_mapper(&icd->vb_vidq, vma); | 679 | err = videobuf_mmap_mapper(&icd->vb_vidq, vma); |
676 | else | 680 | else |
677 | err = vb2_mmap(&icd->vb2_vidq, vma); | 681 | err = vb2_mmap(&icd->vb2_vidq, vma); |
678 | mutex_unlock(&icd->video_lock); | 682 | mutex_unlock(&ici->host_lock); |
679 | 683 | ||
680 | dev_dbg(icd->pdev, "vma start=0x%08lx, size=%ld, ret=%d\n", | 684 | dev_dbg(icd->pdev, "vma start=0x%08lx, size=%ld, ret=%d\n", |
681 | (unsigned long)vma->vm_start, | 685 | (unsigned long)vma->vm_start, |
@@ -694,26 +698,28 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) | |||
694 | if (icd->streamer != file) | 698 | if (icd->streamer != file) |
695 | return POLLERR; | 699 | return POLLERR; |
696 | 700 | ||
697 | mutex_lock(&icd->video_lock); | 701 | mutex_lock(&ici->host_lock); |
698 | if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream)) | 702 | if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream)) |
699 | dev_err(icd->pdev, "Trying to poll with no queued buffers!\n"); | 703 | dev_err(icd->pdev, "Trying to poll with no queued buffers!\n"); |
700 | else | 704 | else |
701 | res = ici->ops->poll(file, pt); | 705 | res = ici->ops->poll(file, pt); |
702 | mutex_unlock(&icd->video_lock); | 706 | mutex_unlock(&ici->host_lock); |
703 | return res; | 707 | return res; |
704 | } | 708 | } |
705 | 709 | ||
706 | void soc_camera_lock(struct vb2_queue *vq) | 710 | void soc_camera_lock(struct vb2_queue *vq) |
707 | { | 711 | { |
708 | struct soc_camera_device *icd = vb2_get_drv_priv(vq); | 712 | struct soc_camera_device *icd = vb2_get_drv_priv(vq); |
709 | mutex_lock(&icd->video_lock); | 713 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
714 | mutex_lock(&ici->host_lock); | ||
710 | } | 715 | } |
711 | EXPORT_SYMBOL(soc_camera_lock); | 716 | EXPORT_SYMBOL(soc_camera_lock); |
712 | 717 | ||
713 | void soc_camera_unlock(struct vb2_queue *vq) | 718 | void soc_camera_unlock(struct vb2_queue *vq) |
714 | { | 719 | { |
715 | struct soc_camera_device *icd = vb2_get_drv_priv(vq); | 720 | struct soc_camera_device *icd = vb2_get_drv_priv(vq); |
716 | mutex_unlock(&icd->video_lock); | 721 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
722 | mutex_unlock(&ici->host_lock); | ||
717 | } | 723 | } |
718 | EXPORT_SYMBOL(soc_camera_unlock); | 724 | EXPORT_SYMBOL(soc_camera_unlock); |
719 | 725 | ||
@@ -908,6 +914,8 @@ static int soc_camera_s_crop(struct file *file, void *fh, | |||
908 | dev_dbg(icd->pdev, "S_CROP(%ux%u@%u:%u)\n", | 914 | dev_dbg(icd->pdev, "S_CROP(%ux%u@%u:%u)\n", |
909 | rect->width, rect->height, rect->left, rect->top); | 915 | rect->width, rect->height, rect->left, rect->top); |
910 | 916 | ||
917 | current_crop.type = a->type; | ||
918 | |||
911 | /* If get_crop fails, we'll let host and / or client drivers decide */ | 919 | /* If get_crop fails, we'll let host and / or client drivers decide */ |
912 | ret = ici->ops->get_crop(icd, ¤t_crop); | 920 | ret = ici->ops->get_crop(icd, ¤t_crop); |
913 | 921 | ||
@@ -1050,7 +1058,7 @@ static void scan_add_host(struct soc_camera_host *ici) | |||
1050 | { | 1058 | { |
1051 | struct soc_camera_device *icd; | 1059 | struct soc_camera_device *icd; |
1052 | 1060 | ||
1053 | mutex_lock(&ici->host_lock); | 1061 | mutex_lock(&list_lock); |
1054 | 1062 | ||
1055 | list_for_each_entry(icd, &devices, list) { | 1063 | list_for_each_entry(icd, &devices, list) { |
1056 | if (icd->iface == ici->nr) { | 1064 | if (icd->iface == ici->nr) { |
@@ -1059,28 +1067,29 @@ static void scan_add_host(struct soc_camera_host *ici) | |||
1059 | } | 1067 | } |
1060 | } | 1068 | } |
1061 | 1069 | ||
1062 | mutex_unlock(&ici->host_lock); | 1070 | mutex_unlock(&list_lock); |
1063 | } | 1071 | } |
1064 | 1072 | ||
1065 | #ifdef CONFIG_I2C_BOARDINFO | 1073 | #ifdef CONFIG_I2C_BOARDINFO |
1066 | static int soc_camera_init_i2c(struct soc_camera_device *icd, | 1074 | static int soc_camera_init_i2c(struct soc_camera_device *icd, |
1067 | struct soc_camera_link *icl) | 1075 | struct soc_camera_desc *sdesc) |
1068 | { | 1076 | { |
1069 | struct i2c_client *client; | 1077 | struct i2c_client *client; |
1070 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 1078 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
1071 | struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); | 1079 | struct soc_camera_host_desc *shd = &sdesc->host_desc; |
1080 | struct i2c_adapter *adap = i2c_get_adapter(shd->i2c_adapter_id); | ||
1072 | struct v4l2_subdev *subdev; | 1081 | struct v4l2_subdev *subdev; |
1073 | 1082 | ||
1074 | if (!adap) { | 1083 | if (!adap) { |
1075 | dev_err(icd->pdev, "Cannot get I2C adapter #%d. No driver?\n", | 1084 | dev_err(icd->pdev, "Cannot get I2C adapter #%d. No driver?\n", |
1076 | icl->i2c_adapter_id); | 1085 | shd->i2c_adapter_id); |
1077 | goto ei2cga; | 1086 | goto ei2cga; |
1078 | } | 1087 | } |
1079 | 1088 | ||
1080 | icl->board_info->platform_data = icl; | 1089 | shd->board_info->platform_data = &sdesc->subdev_desc; |
1081 | 1090 | ||
1082 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, | 1091 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, |
1083 | icl->board_info, NULL); | 1092 | shd->board_info, NULL); |
1084 | if (!subdev) | 1093 | if (!subdev) |
1085 | goto ei2cnd; | 1094 | goto ei2cnd; |
1086 | 1095 | ||
@@ -1108,7 +1117,7 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd) | |||
1108 | i2c_put_adapter(adap); | 1117 | i2c_put_adapter(adap); |
1109 | } | 1118 | } |
1110 | #else | 1119 | #else |
1111 | #define soc_camera_init_i2c(icd, icl) (-ENODEV) | 1120 | #define soc_camera_init_i2c(icd, sdesc) (-ENODEV) |
1112 | #define soc_camera_free_i2c(icd) do {} while (0) | 1121 | #define soc_camera_free_i2c(icd) do {} while (0) |
1113 | #endif | 1122 | #endif |
1114 | 1123 | ||
@@ -1118,7 +1127,9 @@ static int video_dev_create(struct soc_camera_device *icd); | |||
1118 | static int soc_camera_probe(struct soc_camera_device *icd) | 1127 | static int soc_camera_probe(struct soc_camera_device *icd) |
1119 | { | 1128 | { |
1120 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 1129 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
1121 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 1130 | struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); |
1131 | struct soc_camera_host_desc *shd = &sdesc->host_desc; | ||
1132 | struct soc_camera_subdev_desc *ssdd = &sdesc->subdev_desc; | ||
1122 | struct device *control = NULL; | 1133 | struct device *control = NULL; |
1123 | struct v4l2_subdev *sd; | 1134 | struct v4l2_subdev *sd; |
1124 | struct v4l2_mbus_framefmt mf; | 1135 | struct v4l2_mbus_framefmt mf; |
@@ -1137,16 +1148,13 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1137 | if (ret < 0) | 1148 | if (ret < 0) |
1138 | return ret; | 1149 | return ret; |
1139 | 1150 | ||
1140 | ret = regulator_bulk_get(icd->pdev, icl->num_regulators, | ||
1141 | icl->regulators); | ||
1142 | if (ret < 0) | ||
1143 | goto ereg; | ||
1144 | |||
1145 | /* The camera could have been already on, try to reset */ | 1151 | /* The camera could have been already on, try to reset */ |
1146 | if (icl->reset) | 1152 | if (ssdd->reset) |
1147 | icl->reset(icd->pdev); | 1153 | ssdd->reset(icd->pdev); |
1148 | 1154 | ||
1155 | mutex_lock(&ici->host_lock); | ||
1149 | ret = ici->ops->add(icd); | 1156 | ret = ici->ops->add(icd); |
1157 | mutex_unlock(&ici->host_lock); | ||
1150 | if (ret < 0) | 1158 | if (ret < 0) |
1151 | goto eadd; | 1159 | goto eadd; |
1152 | 1160 | ||
@@ -1156,18 +1164,18 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1156 | goto evdc; | 1164 | goto evdc; |
1157 | 1165 | ||
1158 | /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */ | 1166 | /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */ |
1159 | if (icl->board_info) { | 1167 | if (shd->board_info) { |
1160 | ret = soc_camera_init_i2c(icd, icl); | 1168 | ret = soc_camera_init_i2c(icd, sdesc); |
1161 | if (ret < 0) | 1169 | if (ret < 0) |
1162 | goto eadddev; | 1170 | goto eadddev; |
1163 | } else if (!icl->add_device || !icl->del_device) { | 1171 | } else if (!shd->add_device || !shd->del_device) { |
1164 | ret = -EINVAL; | 1172 | ret = -EINVAL; |
1165 | goto eadddev; | 1173 | goto eadddev; |
1166 | } else { | 1174 | } else { |
1167 | if (icl->module_name) | 1175 | if (shd->module_name) |
1168 | ret = request_module(icl->module_name); | 1176 | ret = request_module(shd->module_name); |
1169 | 1177 | ||
1170 | ret = icl->add_device(icd); | 1178 | ret = shd->add_device(icd); |
1171 | if (ret < 0) | 1179 | if (ret < 0) |
1172 | goto eadddev; | 1180 | goto eadddev; |
1173 | 1181 | ||
@@ -1178,7 +1186,7 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1178 | control = to_soc_camera_control(icd); | 1186 | control = to_soc_camera_control(icd); |
1179 | if (!control || !control->driver || !dev_get_drvdata(control) || | 1187 | if (!control || !control->driver || !dev_get_drvdata(control) || |
1180 | !try_module_get(control->driver->owner)) { | 1188 | !try_module_get(control->driver->owner)) { |
1181 | icl->del_device(icd); | 1189 | shd->del_device(icd); |
1182 | ret = -ENODEV; | 1190 | ret = -ENODEV; |
1183 | goto enodrv; | 1191 | goto enodrv; |
1184 | } | 1192 | } |
@@ -1204,7 +1212,7 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1204 | * itself is protected against concurrent open() calls, but we also have | 1212 | * itself is protected against concurrent open() calls, but we also have |
1205 | * to protect our data. | 1213 | * to protect our data. |
1206 | */ | 1214 | */ |
1207 | mutex_lock(&icd->video_lock); | 1215 | mutex_lock(&ici->host_lock); |
1208 | 1216 | ||
1209 | ret = soc_camera_video_start(icd); | 1217 | ret = soc_camera_video_start(icd); |
1210 | if (ret < 0) | 1218 | if (ret < 0) |
@@ -1220,19 +1228,19 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1220 | 1228 | ||
1221 | ici->ops->remove(icd); | 1229 | ici->ops->remove(icd); |
1222 | 1230 | ||
1223 | mutex_unlock(&icd->video_lock); | 1231 | mutex_unlock(&ici->host_lock); |
1224 | 1232 | ||
1225 | return 0; | 1233 | return 0; |
1226 | 1234 | ||
1227 | evidstart: | 1235 | evidstart: |
1228 | mutex_unlock(&icd->video_lock); | 1236 | mutex_unlock(&ici->host_lock); |
1229 | soc_camera_free_user_formats(icd); | 1237 | soc_camera_free_user_formats(icd); |
1230 | eiufmt: | 1238 | eiufmt: |
1231 | ectrl: | 1239 | ectrl: |
1232 | if (icl->board_info) { | 1240 | if (shd->board_info) { |
1233 | soc_camera_free_i2c(icd); | 1241 | soc_camera_free_i2c(icd); |
1234 | } else { | 1242 | } else { |
1235 | icl->del_device(icd); | 1243 | shd->del_device(icd); |
1236 | module_put(control->driver->owner); | 1244 | module_put(control->driver->owner); |
1237 | } | 1245 | } |
1238 | enodrv: | 1246 | enodrv: |
@@ -1240,10 +1248,10 @@ eadddev: | |||
1240 | video_device_release(icd->vdev); | 1248 | video_device_release(icd->vdev); |
1241 | icd->vdev = NULL; | 1249 | icd->vdev = NULL; |
1242 | evdc: | 1250 | evdc: |
1251 | mutex_lock(&ici->host_lock); | ||
1243 | ici->ops->remove(icd); | 1252 | ici->ops->remove(icd); |
1253 | mutex_unlock(&ici->host_lock); | ||
1244 | eadd: | 1254 | eadd: |
1245 | regulator_bulk_free(icl->num_regulators, icl->regulators); | ||
1246 | ereg: | ||
1247 | v4l2_ctrl_handler_free(&icd->ctrl_handler); | 1255 | v4l2_ctrl_handler_free(&icd->ctrl_handler); |
1248 | return ret; | 1256 | return ret; |
1249 | } | 1257 | } |
@@ -1254,7 +1262,7 @@ ereg: | |||
1254 | */ | 1262 | */ |
1255 | static int soc_camera_remove(struct soc_camera_device *icd) | 1263 | static int soc_camera_remove(struct soc_camera_device *icd) |
1256 | { | 1264 | { |
1257 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 1265 | struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); |
1258 | struct video_device *vdev = icd->vdev; | 1266 | struct video_device *vdev = icd->vdev; |
1259 | 1267 | ||
1260 | BUG_ON(!icd->parent); | 1268 | BUG_ON(!icd->parent); |
@@ -1265,19 +1273,17 @@ static int soc_camera_remove(struct soc_camera_device *icd) | |||
1265 | icd->vdev = NULL; | 1273 | icd->vdev = NULL; |
1266 | } | 1274 | } |
1267 | 1275 | ||
1268 | if (icl->board_info) { | 1276 | if (sdesc->host_desc.board_info) { |
1269 | soc_camera_free_i2c(icd); | 1277 | soc_camera_free_i2c(icd); |
1270 | } else { | 1278 | } else { |
1271 | struct device_driver *drv = to_soc_camera_control(icd)->driver; | 1279 | struct device_driver *drv = to_soc_camera_control(icd)->driver; |
1272 | if (drv) { | 1280 | if (drv) { |
1273 | icl->del_device(icd); | 1281 | sdesc->host_desc.del_device(icd); |
1274 | module_put(drv->owner); | 1282 | module_put(drv->owner); |
1275 | } | 1283 | } |
1276 | } | 1284 | } |
1277 | soc_camera_free_user_formats(icd); | 1285 | soc_camera_free_user_formats(icd); |
1278 | 1286 | ||
1279 | regulator_bulk_free(icl->num_regulators, icl->regulators); | ||
1280 | |||
1281 | return 0; | 1287 | return 0; |
1282 | } | 1288 | } |
1283 | 1289 | ||
@@ -1442,7 +1448,6 @@ static int soc_camera_device_register(struct soc_camera_device *icd) | |||
1442 | icd->devnum = num; | 1448 | icd->devnum = num; |
1443 | icd->use_count = 0; | 1449 | icd->use_count = 0; |
1444 | icd->host_priv = NULL; | 1450 | icd->host_priv = NULL; |
1445 | mutex_init(&icd->video_lock); | ||
1446 | 1451 | ||
1447 | list_add_tail(&icd->list, &devices); | 1452 | list_add_tail(&icd->list, &devices); |
1448 | 1453 | ||
@@ -1500,7 +1505,7 @@ static int video_dev_create(struct soc_camera_device *icd) | |||
1500 | vdev->release = video_device_release; | 1505 | vdev->release = video_device_release; |
1501 | vdev->tvnorms = V4L2_STD_UNKNOWN; | 1506 | vdev->tvnorms = V4L2_STD_UNKNOWN; |
1502 | vdev->ctrl_handler = &icd->ctrl_handler; | 1507 | vdev->ctrl_handler = &icd->ctrl_handler; |
1503 | vdev->lock = &icd->video_lock; | 1508 | vdev->lock = &ici->host_lock; |
1504 | 1509 | ||
1505 | icd->vdev = vdev; | 1510 | icd->vdev = vdev; |
1506 | 1511 | ||
@@ -1508,7 +1513,7 @@ static int video_dev_create(struct soc_camera_device *icd) | |||
1508 | } | 1513 | } |
1509 | 1514 | ||
1510 | /* | 1515 | /* |
1511 | * Called from soc_camera_probe() above (with .video_lock held???) | 1516 | * Called from soc_camera_probe() above with .host_lock held |
1512 | */ | 1517 | */ |
1513 | static int soc_camera_video_start(struct soc_camera_device *icd) | 1518 | static int soc_camera_video_start(struct soc_camera_device *icd) |
1514 | { | 1519 | { |
@@ -1532,18 +1537,25 @@ static int soc_camera_video_start(struct soc_camera_device *icd) | |||
1532 | 1537 | ||
1533 | static int soc_camera_pdrv_probe(struct platform_device *pdev) | 1538 | static int soc_camera_pdrv_probe(struct platform_device *pdev) |
1534 | { | 1539 | { |
1535 | struct soc_camera_link *icl = pdev->dev.platform_data; | 1540 | struct soc_camera_desc *sdesc = pdev->dev.platform_data; |
1541 | struct soc_camera_subdev_desc *ssdd = &sdesc->subdev_desc; | ||
1536 | struct soc_camera_device *icd; | 1542 | struct soc_camera_device *icd; |
1543 | int ret; | ||
1537 | 1544 | ||
1538 | if (!icl) | 1545 | if (!sdesc) |
1539 | return -EINVAL; | 1546 | return -EINVAL; |
1540 | 1547 | ||
1541 | icd = devm_kzalloc(&pdev->dev, sizeof(*icd), GFP_KERNEL); | 1548 | icd = devm_kzalloc(&pdev->dev, sizeof(*icd), GFP_KERNEL); |
1542 | if (!icd) | 1549 | if (!icd) |
1543 | return -ENOMEM; | 1550 | return -ENOMEM; |
1544 | 1551 | ||
1545 | icd->iface = icl->bus_id; | 1552 | ret = devm_regulator_bulk_get(&pdev->dev, ssdd->num_regulators, |
1546 | icd->link = icl; | 1553 | ssdd->regulators); |
1554 | if (ret < 0) | ||
1555 | return ret; | ||
1556 | |||
1557 | icd->iface = sdesc->host_desc.bus_id; | ||
1558 | icd->sdesc = sdesc; | ||
1547 | icd->pdev = &pdev->dev; | 1559 | icd->pdev = &pdev->dev; |
1548 | platform_set_drvdata(pdev, icd); | 1560 | platform_set_drvdata(pdev, icd); |
1549 | 1561 | ||
diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c index 7cf7fd16481f..ce3b1d6a4734 100644 --- a/drivers/media/platform/soc_camera/soc_camera_platform.c +++ b/drivers/media/platform/soc_camera/soc_camera_platform.c | |||
@@ -54,7 +54,7 @@ static int soc_camera_platform_s_power(struct v4l2_subdev *sd, int on) | |||
54 | { | 54 | { |
55 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); | 55 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); |
56 | 56 | ||
57 | return soc_camera_set_power(p->icd->control, p->icd->link, on); | 57 | return soc_camera_set_power(p->icd->control, &p->icd->sdesc->subdev_desc, on); |
58 | } | 58 | } |
59 | 59 | ||
60 | static struct v4l2_subdev_core_ops platform_subdev_core_ops = { | 60 | static struct v4l2_subdev_core_ops platform_subdev_core_ops = { |
@@ -148,7 +148,7 @@ static int soc_camera_platform_probe(struct platform_device *pdev) | |||
148 | return -EINVAL; | 148 | return -EINVAL; |
149 | } | 149 | } |
150 | 150 | ||
151 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 151 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
152 | if (!priv) | 152 | if (!priv) |
153 | return -ENOMEM; | 153 | return -ENOMEM; |
154 | 154 | ||
@@ -173,7 +173,6 @@ static int soc_camera_platform_probe(struct platform_device *pdev) | |||
173 | 173 | ||
174 | evdrs: | 174 | evdrs: |
175 | platform_set_drvdata(pdev, NULL); | 175 | platform_set_drvdata(pdev, NULL); |
176 | kfree(priv); | ||
177 | return ret; | 176 | return ret; |
178 | } | 177 | } |
179 | 178 | ||
@@ -185,7 +184,6 @@ static int soc_camera_platform_remove(struct platform_device *pdev) | |||
185 | p->icd->control = NULL; | 184 | p->icd->control = NULL; |
186 | v4l2_device_unregister_subdev(&priv->subdev); | 185 | v4l2_device_unregister_subdev(&priv->subdev); |
187 | platform_set_drvdata(pdev, NULL); | 186 | platform_set_drvdata(pdev, NULL); |
188 | kfree(priv); | ||
189 | return 0; | 187 | return 0; |
190 | } | 188 | } |
191 | 189 | ||
diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c index a397812635d6..89dce097a827 100644 --- a/drivers/media/platform/soc_camera/soc_mediabus.c +++ b/drivers/media/platform/soc_camera/soc_mediabus.c | |||
@@ -378,9 +378,6 @@ EXPORT_SYMBOL(soc_mbus_samples_per_pixel); | |||
378 | 378 | ||
379 | s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf) | 379 | s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf) |
380 | { | 380 | { |
381 | if (mf->fourcc == V4L2_PIX_FMT_JPEG) | ||
382 | return 0; | ||
383 | |||
384 | if (mf->layout != SOC_MBUS_LAYOUT_PACKED) | 381 | if (mf->layout != SOC_MBUS_LAYOUT_PACKED) |
385 | return width * mf->bits_per_sample / 8; | 382 | return width * mf->bits_per_sample / 8; |
386 | 383 | ||
@@ -403,9 +400,6 @@ EXPORT_SYMBOL(soc_mbus_bytes_per_line); | |||
403 | s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf, | 400 | s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf, |
404 | u32 bytes_per_line, u32 height) | 401 | u32 bytes_per_line, u32 height) |
405 | { | 402 | { |
406 | if (mf->fourcc == V4L2_PIX_FMT_JPEG) | ||
407 | return 0; | ||
408 | |||
409 | if (mf->layout == SOC_MBUS_LAYOUT_PACKED) | 403 | if (mf->layout == SOC_MBUS_LAYOUT_PACKED) |
410 | return bytes_per_line * height; | 404 | return bytes_per_line * height; |
411 | 405 | ||
diff --git a/drivers/media/platform/timblogiw.c b/drivers/media/platform/timblogiw.c index d854d08a6c7f..c3a2a4484401 100644 --- a/drivers/media/platform/timblogiw.c +++ b/drivers/media/platform/timblogiw.c | |||
@@ -130,7 +130,7 @@ static void timblogiw_dma_cb(void *data) | |||
130 | 130 | ||
131 | if (vb->state != VIDEOBUF_ERROR) { | 131 | if (vb->state != VIDEOBUF_ERROR) { |
132 | list_del(&vb->queue); | 132 | list_del(&vb->queue); |
133 | do_gettimeofday(&vb->ts); | 133 | v4l2_get_timestamp(&vb->ts); |
134 | vb->field_count = fh->frame_count * 2; | 134 | vb->field_count = fh->frame_count * 2; |
135 | vb->state = VIDEOBUF_DONE; | 135 | vb->state = VIDEOBUF_DONE; |
136 | 136 | ||
diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index 63e8c3461239..b051c4a28554 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <media/v4l2-device.h> | 18 | #include <media/v4l2-device.h> |
19 | #include <media/v4l2-ioctl.h> | 19 | #include <media/v4l2-ioctl.h> |
20 | #include <media/v4l2-chip-ident.h> | 20 | #include <media/v4l2-chip-ident.h> |
21 | #include <media/v4l2-ctrls.h> | ||
21 | #include <media/ov7670.h> | 22 | #include <media/ov7670.h> |
22 | #include <media/videobuf-dma-sg.h> | 23 | #include <media/videobuf-dma-sg.h> |
23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
@@ -63,6 +64,7 @@ enum viacam_opstate { S_IDLE = 0, S_RUNNING = 1 }; | |||
63 | 64 | ||
64 | struct via_camera { | 65 | struct via_camera { |
65 | struct v4l2_device v4l2_dev; | 66 | struct v4l2_device v4l2_dev; |
67 | struct v4l2_ctrl_handler ctrl_handler; | ||
66 | struct video_device vdev; | 68 | struct video_device vdev; |
67 | struct v4l2_subdev *sensor; | 69 | struct v4l2_subdev *sensor; |
68 | struct platform_device *platdev; | 70 | struct platform_device *platdev; |
@@ -818,47 +820,6 @@ static int viacam_g_chip_ident(struct file *file, void *priv, | |||
818 | } | 820 | } |
819 | 821 | ||
820 | /* | 822 | /* |
821 | * Control ops are passed through to the sensor. | ||
822 | */ | ||
823 | static int viacam_queryctrl(struct file *filp, void *priv, | ||
824 | struct v4l2_queryctrl *qc) | ||
825 | { | ||
826 | struct via_camera *cam = priv; | ||
827 | int ret; | ||
828 | |||
829 | mutex_lock(&cam->lock); | ||
830 | ret = sensor_call(cam, core, queryctrl, qc); | ||
831 | mutex_unlock(&cam->lock); | ||
832 | return ret; | ||
833 | } | ||
834 | |||
835 | |||
836 | static int viacam_g_ctrl(struct file *filp, void *priv, | ||
837 | struct v4l2_control *ctrl) | ||
838 | { | ||
839 | struct via_camera *cam = priv; | ||
840 | int ret; | ||
841 | |||
842 | mutex_lock(&cam->lock); | ||
843 | ret = sensor_call(cam, core, g_ctrl, ctrl); | ||
844 | mutex_unlock(&cam->lock); | ||
845 | return ret; | ||
846 | } | ||
847 | |||
848 | |||
849 | static int viacam_s_ctrl(struct file *filp, void *priv, | ||
850 | struct v4l2_control *ctrl) | ||
851 | { | ||
852 | struct via_camera *cam = priv; | ||
853 | int ret; | ||
854 | |||
855 | mutex_lock(&cam->lock); | ||
856 | ret = sensor_call(cam, core, s_ctrl, ctrl); | ||
857 | mutex_unlock(&cam->lock); | ||
858 | return ret; | ||
859 | } | ||
860 | |||
861 | /* | ||
862 | * Only one input. | 823 | * Only one input. |
863 | */ | 824 | */ |
864 | static int viacam_enum_input(struct file *filp, void *priv, | 825 | static int viacam_enum_input(struct file *filp, void *priv, |
@@ -1214,9 +1175,6 @@ static int viacam_enum_frameintervals(struct file *filp, void *priv, | |||
1214 | 1175 | ||
1215 | static const struct v4l2_ioctl_ops viacam_ioctl_ops = { | 1176 | static const struct v4l2_ioctl_ops viacam_ioctl_ops = { |
1216 | .vidioc_g_chip_ident = viacam_g_chip_ident, | 1177 | .vidioc_g_chip_ident = viacam_g_chip_ident, |
1217 | .vidioc_queryctrl = viacam_queryctrl, | ||
1218 | .vidioc_g_ctrl = viacam_g_ctrl, | ||
1219 | .vidioc_s_ctrl = viacam_s_ctrl, | ||
1220 | .vidioc_enum_input = viacam_enum_input, | 1178 | .vidioc_enum_input = viacam_enum_input, |
1221 | .vidioc_g_input = viacam_g_input, | 1179 | .vidioc_g_input = viacam_g_input, |
1222 | .vidioc_s_input = viacam_s_input, | 1180 | .vidioc_s_input = viacam_s_input, |
@@ -1418,8 +1376,12 @@ static int viacam_probe(struct platform_device *pdev) | |||
1418 | ret = v4l2_device_register(&pdev->dev, &cam->v4l2_dev); | 1376 | ret = v4l2_device_register(&pdev->dev, &cam->v4l2_dev); |
1419 | if (ret) { | 1377 | if (ret) { |
1420 | dev_err(&pdev->dev, "Unable to register v4l2 device\n"); | 1378 | dev_err(&pdev->dev, "Unable to register v4l2 device\n"); |
1421 | return ret; | 1379 | goto out_free; |
1422 | } | 1380 | } |
1381 | ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10); | ||
1382 | if (ret) | ||
1383 | goto out_unregister; | ||
1384 | cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler; | ||
1423 | /* | 1385 | /* |
1424 | * Convince the system that we can do DMA. | 1386 | * Convince the system that we can do DMA. |
1425 | */ | 1387 | */ |
@@ -1436,7 +1398,7 @@ static int viacam_probe(struct platform_device *pdev) | |||
1436 | */ | 1398 | */ |
1437 | ret = via_sensor_power_setup(cam); | 1399 | ret = via_sensor_power_setup(cam); |
1438 | if (ret) | 1400 | if (ret) |
1439 | goto out_unregister; | 1401 | goto out_ctrl_hdl_free; |
1440 | via_sensor_power_up(cam); | 1402 | via_sensor_power_up(cam); |
1441 | 1403 | ||
1442 | /* | 1404 | /* |
@@ -1485,8 +1447,12 @@ out_irq: | |||
1485 | free_irq(viadev->pdev->irq, cam); | 1447 | free_irq(viadev->pdev->irq, cam); |
1486 | out_power_down: | 1448 | out_power_down: |
1487 | via_sensor_power_release(cam); | 1449 | via_sensor_power_release(cam); |
1450 | out_ctrl_hdl_free: | ||
1451 | v4l2_ctrl_handler_free(&cam->ctrl_handler); | ||
1488 | out_unregister: | 1452 | out_unregister: |
1489 | v4l2_device_unregister(&cam->v4l2_dev); | 1453 | v4l2_device_unregister(&cam->v4l2_dev); |
1454 | out_free: | ||
1455 | kfree(cam); | ||
1490 | return ret; | 1456 | return ret; |
1491 | } | 1457 | } |
1492 | 1458 | ||
@@ -1499,6 +1465,8 @@ static int viacam_remove(struct platform_device *pdev) | |||
1499 | v4l2_device_unregister(&cam->v4l2_dev); | 1465 | v4l2_device_unregister(&cam->v4l2_dev); |
1500 | free_irq(viadev->pdev->irq, cam); | 1466 | free_irq(viadev->pdev->irq, cam); |
1501 | via_sensor_power_release(cam); | 1467 | via_sensor_power_release(cam); |
1468 | v4l2_ctrl_handler_free(&cam->ctrl_handler); | ||
1469 | kfree(cam); | ||
1502 | via_cam_info = NULL; | 1470 | via_cam_info = NULL; |
1503 | return 0; | 1471 | return 0; |
1504 | } | 1472 | } |
diff --git a/drivers/media/platform/vino.c b/drivers/media/platform/vino.c index 70b0bf4b2900..eb5d6f955709 100644 --- a/drivers/media/platform/vino.c +++ b/drivers/media/platform/vino.c | |||
@@ -2474,8 +2474,8 @@ static irqreturn_t vino_interrupt(int irq, void *dev_id) | |||
2474 | 2474 | ||
2475 | if ((!handled_a) && (done_a || skip_a)) { | 2475 | if ((!handled_a) && (done_a || skip_a)) { |
2476 | if (!skip_a) { | 2476 | if (!skip_a) { |
2477 | do_gettimeofday(&vino_drvdata-> | 2477 | v4l2_get_timestamp( |
2478 | a.int_data.timestamp); | 2478 | &vino_drvdata->a.int_data.timestamp); |
2479 | vino_drvdata->a.int_data.frame_counter = fc_a; | 2479 | vino_drvdata->a.int_data.frame_counter = fc_a; |
2480 | } | 2480 | } |
2481 | vino_drvdata->a.int_data.skip = skip_a; | 2481 | vino_drvdata->a.int_data.skip = skip_a; |
@@ -2489,8 +2489,8 @@ static irqreturn_t vino_interrupt(int irq, void *dev_id) | |||
2489 | 2489 | ||
2490 | if ((!handled_b) && (done_b || skip_b)) { | 2490 | if ((!handled_b) && (done_b || skip_b)) { |
2491 | if (!skip_b) { | 2491 | if (!skip_b) { |
2492 | do_gettimeofday(&vino_drvdata-> | 2492 | v4l2_get_timestamp( |
2493 | b.int_data.timestamp); | 2493 | &vino_drvdata->b.int_data.timestamp); |
2494 | vino_drvdata->b.int_data.frame_counter = fc_b; | 2494 | vino_drvdata->b.int_data.frame_counter = fc_b; |
2495 | } | 2495 | } |
2496 | vino_drvdata->b.int_data.skip = skip_b; | 2496 | vino_drvdata->b.int_data.skip = skip_b; |
@@ -3410,6 +3410,9 @@ static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs, | |||
3410 | if (fb->map_count > 0) | 3410 | if (fb->map_count > 0) |
3411 | b->flags |= V4L2_BUF_FLAG_MAPPED; | 3411 | b->flags |= V4L2_BUF_FLAG_MAPPED; |
3412 | 3412 | ||
3413 | b->flags &= ~V4L2_BUF_FLAG_TIMESTAMP_MASK; | ||
3414 | b->flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
3415 | |||
3413 | b->index = fb->id; | 3416 | b->index = fb->id; |
3414 | b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ? | 3417 | b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ? |
3415 | V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR; | 3418 | V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR; |
diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c index 0d59b9db83cb..8a33a712f480 100644 --- a/drivers/media/platform/vivi.c +++ b/drivers/media/platform/vivi.c | |||
@@ -36,9 +36,17 @@ | |||
36 | 36 | ||
37 | #define VIVI_MODULE_NAME "vivi" | 37 | #define VIVI_MODULE_NAME "vivi" |
38 | 38 | ||
39 | /* Wake up at about 30 fps */ | 39 | /* Maximum allowed frame rate |
40 | #define WAKE_NUMERATOR 30 | 40 | * |
41 | #define WAKE_DENOMINATOR 1001 | 41 | * Vivi will allow setting timeperframe in [1/FPS_MAX - FPS_MAX/1] range. |
42 | * | ||
43 | * Ideally FPS_MAX should be infinity, i.e. practically UINT_MAX, but that | ||
44 | * might hit application errors when they manipulate these values. | ||
45 | * | ||
46 | * Besides, for tpf < 1ms image-generation logic should be changed, to avoid | ||
47 | * producing frames with equal content. | ||
48 | */ | ||
49 | #define FPS_MAX 1000 | ||
42 | 50 | ||
43 | #define MAX_WIDTH 1920 | 51 | #define MAX_WIDTH 1920 |
44 | #define MAX_HEIGHT 1200 | 52 | #define MAX_HEIGHT 1200 |
@@ -69,6 +77,12 @@ MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); | |||
69 | /* Global font descriptor */ | 77 | /* Global font descriptor */ |
70 | static const u8 *font8x16; | 78 | static const u8 *font8x16; |
71 | 79 | ||
80 | /* timeperframe: min/max and default */ | ||
81 | static const struct v4l2_fract | ||
82 | tpf_min = {.numerator = 1, .denominator = FPS_MAX}, | ||
83 | tpf_max = {.numerator = FPS_MAX, .denominator = 1}, | ||
84 | tpf_default = {.numerator = 1001, .denominator = 30000}; /* NTSC */ | ||
85 | |||
72 | #define dprintk(dev, level, fmt, arg...) \ | 86 | #define dprintk(dev, level, fmt, arg...) \ |
73 | v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) | 87 | v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) |
74 | 88 | ||
@@ -77,13 +91,13 @@ static const u8 *font8x16; | |||
77 | ------------------------------------------------------------------*/ | 91 | ------------------------------------------------------------------*/ |
78 | 92 | ||
79 | struct vivi_fmt { | 93 | struct vivi_fmt { |
80 | char *name; | 94 | const char *name; |
81 | u32 fourcc; /* v4l2 format id */ | 95 | u32 fourcc; /* v4l2 format id */ |
82 | u8 depth; | 96 | u8 depth; |
83 | bool is_yuv; | 97 | bool is_yuv; |
84 | }; | 98 | }; |
85 | 99 | ||
86 | static struct vivi_fmt formats[] = { | 100 | static const struct vivi_fmt formats[] = { |
87 | { | 101 | { |
88 | .name = "4:2:2, packed, YUYV", | 102 | .name = "4:2:2, packed, YUYV", |
89 | .fourcc = V4L2_PIX_FMT_YUYV, | 103 | .fourcc = V4L2_PIX_FMT_YUYV, |
@@ -150,14 +164,14 @@ static struct vivi_fmt formats[] = { | |||
150 | }, | 164 | }, |
151 | }; | 165 | }; |
152 | 166 | ||
153 | static struct vivi_fmt *get_format(struct v4l2_format *f) | 167 | static const struct vivi_fmt *__get_format(u32 pixelformat) |
154 | { | 168 | { |
155 | struct vivi_fmt *fmt; | 169 | const struct vivi_fmt *fmt; |
156 | unsigned int k; | 170 | unsigned int k; |
157 | 171 | ||
158 | for (k = 0; k < ARRAY_SIZE(formats); k++) { | 172 | for (k = 0; k < ARRAY_SIZE(formats); k++) { |
159 | fmt = &formats[k]; | 173 | fmt = &formats[k]; |
160 | if (fmt->fourcc == f->fmt.pix.pixelformat) | 174 | if (fmt->fourcc == pixelformat) |
161 | break; | 175 | break; |
162 | } | 176 | } |
163 | 177 | ||
@@ -167,12 +181,17 @@ static struct vivi_fmt *get_format(struct v4l2_format *f) | |||
167 | return &formats[k]; | 181 | return &formats[k]; |
168 | } | 182 | } |
169 | 183 | ||
184 | static const struct vivi_fmt *get_format(struct v4l2_format *f) | ||
185 | { | ||
186 | return __get_format(f->fmt.pix.pixelformat); | ||
187 | } | ||
188 | |||
170 | /* buffer for one video frame */ | 189 | /* buffer for one video frame */ |
171 | struct vivi_buffer { | 190 | struct vivi_buffer { |
172 | /* common v4l buffer stuff -- must be first */ | 191 | /* common v4l buffer stuff -- must be first */ |
173 | struct vb2_buffer vb; | 192 | struct vb2_buffer vb; |
174 | struct list_head list; | 193 | struct list_head list; |
175 | struct vivi_fmt *fmt; | 194 | const struct vivi_fmt *fmt; |
176 | }; | 195 | }; |
177 | 196 | ||
178 | struct vivi_dmaqueue { | 197 | struct vivi_dmaqueue { |
@@ -231,15 +250,17 @@ struct vivi_dev { | |||
231 | int input; | 250 | int input; |
232 | 251 | ||
233 | /* video capture */ | 252 | /* video capture */ |
234 | struct vivi_fmt *fmt; | 253 | const struct vivi_fmt *fmt; |
254 | struct v4l2_fract timeperframe; | ||
235 | unsigned int width, height; | 255 | unsigned int width, height; |
236 | struct vb2_queue vb_vidq; | 256 | struct vb2_queue vb_vidq; |
237 | unsigned int field_count; | 257 | unsigned int field_count; |
238 | 258 | ||
239 | u8 bars[9][3]; | 259 | u8 bars[9][3]; |
240 | u8 line[MAX_WIDTH * 8]; | 260 | u8 line[MAX_WIDTH * 8] __attribute__((__aligned__(4))); |
241 | unsigned int pixelsize; | 261 | unsigned int pixelsize; |
242 | u8 alpha_component; | 262 | u8 alpha_component; |
263 | u32 textfg, textbg; | ||
243 | }; | 264 | }; |
244 | 265 | ||
245 | /* ------------------------------------------------------------------ | 266 | /* ------------------------------------------------------------------ |
@@ -276,7 +297,7 @@ struct bar_std { | |||
276 | 297 | ||
277 | /* Maximum number of bars are 10 - otherwise, the input print code | 298 | /* Maximum number of bars are 10 - otherwise, the input print code |
278 | should be modified */ | 299 | should be modified */ |
279 | static struct bar_std bars[] = { | 300 | static const struct bar_std bars[] = { |
280 | { /* Standard ITU-R color bar sequence */ | 301 | { /* Standard ITU-R color bar sequence */ |
281 | { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN, | 302 | { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN, |
282 | COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK } | 303 | COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK } |
@@ -511,66 +532,100 @@ static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos, bool odd) | |||
511 | 532 | ||
512 | static void precalculate_line(struct vivi_dev *dev) | 533 | static void precalculate_line(struct vivi_dev *dev) |
513 | { | 534 | { |
514 | int w; | 535 | unsigned pixsize = dev->pixelsize; |
515 | 536 | unsigned pixsize2 = 2*pixsize; | |
516 | for (w = 0; w < dev->width * 2; w++) { | 537 | int colorpos; |
517 | int colorpos = w / (dev->width / 8) % 8; | 538 | u8 *pos; |
518 | 539 | ||
519 | gen_twopix(dev, dev->line + w * dev->pixelsize, colorpos, w & 1); | 540 | for (colorpos = 0; colorpos < 16; ++colorpos) { |
541 | u8 pix[8]; | ||
542 | int wstart = colorpos * dev->width / 8; | ||
543 | int wend = (colorpos+1) * dev->width / 8; | ||
544 | int w; | ||
545 | |||
546 | gen_twopix(dev, &pix[0], colorpos % 8, 0); | ||
547 | gen_twopix(dev, &pix[pixsize], colorpos % 8, 1); | ||
548 | |||
549 | for (w = wstart/2*2, pos = dev->line + w*pixsize; w < wend; w += 2, pos += pixsize2) | ||
550 | memcpy(pos, pix, pixsize2); | ||
520 | } | 551 | } |
521 | } | 552 | } |
522 | 553 | ||
554 | /* need this to do rgb24 rendering */ | ||
555 | typedef struct { u16 __; u8 _; } __attribute__((packed)) x24; | ||
556 | |||
523 | static void gen_text(struct vivi_dev *dev, char *basep, | 557 | static void gen_text(struct vivi_dev *dev, char *basep, |
524 | int y, int x, char *text) | 558 | int y, int x, char *text) |
525 | { | 559 | { |
526 | int line; | 560 | int line; |
561 | unsigned int width = dev->width; | ||
527 | 562 | ||
528 | /* Checks if it is possible to show string */ | 563 | /* Checks if it is possible to show string */ |
529 | if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width) | 564 | if (y + 16 >= dev->height || x + strlen(text) * 8 >= width) |
530 | return; | 565 | return; |
531 | 566 | ||
532 | /* Print stream time */ | 567 | /* Print stream time */ |
533 | for (line = y; line < y + 16; line++) { | 568 | #define PRINTSTR(PIXTYPE) do { \ |
534 | int j = 0; | 569 | PIXTYPE fg; \ |
535 | char *pos = basep + line * dev->width * dev->pixelsize + x * dev->pixelsize; | 570 | PIXTYPE bg; \ |
536 | char *s; | 571 | memcpy(&fg, &dev->textfg, sizeof(PIXTYPE)); \ |
537 | 572 | memcpy(&bg, &dev->textbg, sizeof(PIXTYPE)); \ | |
538 | for (s = text; *s; s++) { | 573 | \ |
539 | u8 chr = font8x16[*s * 16 + line - y]; | 574 | for (line = 0; line < 16; line++) { \ |
540 | int i; | 575 | PIXTYPE *pos = (PIXTYPE *)( basep + ((y + line) * width + x) * sizeof(PIXTYPE) ); \ |
541 | 576 | u8 *s; \ | |
542 | for (i = 0; i < 7; i++, j++) { | 577 | \ |
543 | /* Draw white font on black background */ | 578 | for (s = text; *s; s++) { \ |
544 | if (chr & (1 << (7 - i))) | 579 | u8 chr = font8x16[*s * 16 + line]; \ |
545 | gen_twopix(dev, pos + j * dev->pixelsize, WHITE, (x+y) & 1); | 580 | \ |
546 | else | 581 | pos[0] = (chr & (0x01 << 7) ? fg : bg); \ |
547 | gen_twopix(dev, pos + j * dev->pixelsize, TEXT_BLACK, (x+y) & 1); | 582 | pos[1] = (chr & (0x01 << 6) ? fg : bg); \ |
548 | } | 583 | pos[2] = (chr & (0x01 << 5) ? fg : bg); \ |
549 | } | 584 | pos[3] = (chr & (0x01 << 4) ? fg : bg); \ |
585 | pos[4] = (chr & (0x01 << 3) ? fg : bg); \ | ||
586 | pos[5] = (chr & (0x01 << 2) ? fg : bg); \ | ||
587 | pos[6] = (chr & (0x01 << 1) ? fg : bg); \ | ||
588 | pos[7] = (chr & (0x01 << 0) ? fg : bg); \ | ||
589 | \ | ||
590 | pos += 8; \ | ||
591 | } \ | ||
592 | } \ | ||
593 | } while (0) | ||
594 | |||
595 | switch (dev->pixelsize) { | ||
596 | case 2: | ||
597 | PRINTSTR(u16); break; | ||
598 | case 4: | ||
599 | PRINTSTR(u32); break; | ||
600 | case 3: | ||
601 | PRINTSTR(x24); break; | ||
550 | } | 602 | } |
551 | } | 603 | } |
552 | 604 | ||
553 | static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) | 605 | static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) |
554 | { | 606 | { |
555 | int wmax = dev->width; | 607 | int stride = dev->width * dev->pixelsize; |
556 | int hmax = dev->height; | 608 | int hmax = dev->height; |
557 | struct timeval ts; | ||
558 | void *vbuf = vb2_plane_vaddr(&buf->vb, 0); | 609 | void *vbuf = vb2_plane_vaddr(&buf->vb, 0); |
559 | unsigned ms; | 610 | unsigned ms; |
560 | char str[100]; | 611 | char str[100]; |
561 | int h, line = 1; | 612 | int h, line = 1; |
613 | u8 *linestart; | ||
562 | s32 gain; | 614 | s32 gain; |
563 | 615 | ||
564 | if (!vbuf) | 616 | if (!vbuf) |
565 | return; | 617 | return; |
566 | 618 | ||
619 | linestart = dev->line + (dev->mv_count % dev->width) * dev->pixelsize; | ||
620 | |||
567 | for (h = 0; h < hmax; h++) | 621 | for (h = 0; h < hmax; h++) |
568 | memcpy(vbuf + h * wmax * dev->pixelsize, | 622 | memcpy(vbuf + h * stride, linestart, stride); |
569 | dev->line + (dev->mv_count % wmax) * dev->pixelsize, | ||
570 | wmax * dev->pixelsize); | ||
571 | 623 | ||
572 | /* Updates stream time */ | 624 | /* Updates stream time */ |
573 | 625 | ||
626 | gen_twopix(dev, (u8 *)&dev->textbg, TEXT_BLACK, /*odd=*/ 0); | ||
627 | gen_twopix(dev, (u8 *)&dev->textfg, WHITE, /*odd=*/ 0); | ||
628 | |||
574 | dev->ms += jiffies_to_msecs(jiffies - dev->jiffies); | 629 | dev->ms += jiffies_to_msecs(jiffies - dev->jiffies); |
575 | dev->jiffies = jiffies; | 630 | dev->jiffies = jiffies; |
576 | ms = dev->ms; | 631 | ms = dev->ms; |
@@ -622,8 +677,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) | |||
622 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; | 677 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; |
623 | dev->field_count++; | 678 | dev->field_count++; |
624 | buf->vb.v4l2_buf.sequence = dev->field_count >> 1; | 679 | buf->vb.v4l2_buf.sequence = dev->field_count >> 1; |
625 | do_gettimeofday(&ts); | 680 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); |
626 | buf->vb.v4l2_buf.timestamp = ts; | ||
627 | } | 681 | } |
628 | 682 | ||
629 | static void vivi_thread_tick(struct vivi_dev *dev) | 683 | static void vivi_thread_tick(struct vivi_dev *dev) |
@@ -645,7 +699,7 @@ static void vivi_thread_tick(struct vivi_dev *dev) | |||
645 | list_del(&buf->list); | 699 | list_del(&buf->list); |
646 | spin_unlock_irqrestore(&dev->slock, flags); | 700 | spin_unlock_irqrestore(&dev->slock, flags); |
647 | 701 | ||
648 | do_gettimeofday(&buf->vb.v4l2_buf.timestamp); | 702 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); |
649 | 703 | ||
650 | /* Fill buffer */ | 704 | /* Fill buffer */ |
651 | vivi_fillbuff(dev, buf); | 705 | vivi_fillbuff(dev, buf); |
@@ -655,8 +709,8 @@ static void vivi_thread_tick(struct vivi_dev *dev) | |||
655 | dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index); | 709 | dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index); |
656 | } | 710 | } |
657 | 711 | ||
658 | #define frames_to_ms(frames) \ | 712 | #define frames_to_ms(dev, frames) \ |
659 | ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) | 713 | ((frames * dev->timeperframe.numerator * 1000) / dev->timeperframe.denominator) |
660 | 714 | ||
661 | static void vivi_sleep(struct vivi_dev *dev) | 715 | static void vivi_sleep(struct vivi_dev *dev) |
662 | { | 716 | { |
@@ -672,7 +726,7 @@ static void vivi_sleep(struct vivi_dev *dev) | |||
672 | goto stop_task; | 726 | goto stop_task; |
673 | 727 | ||
674 | /* Calculate time to wake up */ | 728 | /* Calculate time to wake up */ |
675 | timeout = msecs_to_jiffies(frames_to_ms(1)); | 729 | timeout = msecs_to_jiffies(frames_to_ms(dev, 1)); |
676 | 730 | ||
677 | vivi_thread_tick(dev); | 731 | vivi_thread_tick(dev); |
678 | 732 | ||
@@ -872,7 +926,7 @@ static void vivi_unlock(struct vb2_queue *vq) | |||
872 | } | 926 | } |
873 | 927 | ||
874 | 928 | ||
875 | static struct vb2_ops vivi_video_qops = { | 929 | static const struct vb2_ops vivi_video_qops = { |
876 | .queue_setup = queue_setup, | 930 | .queue_setup = queue_setup, |
877 | .buf_prepare = buffer_prepare, | 931 | .buf_prepare = buffer_prepare, |
878 | .buf_queue = buffer_queue, | 932 | .buf_queue = buffer_queue, |
@@ -903,7 +957,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
903 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | 957 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
904 | struct v4l2_fmtdesc *f) | 958 | struct v4l2_fmtdesc *f) |
905 | { | 959 | { |
906 | struct vivi_fmt *fmt; | 960 | const struct vivi_fmt *fmt; |
907 | 961 | ||
908 | if (f->index >= ARRAY_SIZE(formats)) | 962 | if (f->index >= ARRAY_SIZE(formats)) |
909 | return -EINVAL; | 963 | return -EINVAL; |
@@ -939,7 +993,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
939 | struct v4l2_format *f) | 993 | struct v4l2_format *f) |
940 | { | 994 | { |
941 | struct vivi_dev *dev = video_drvdata(file); | 995 | struct vivi_dev *dev = video_drvdata(file); |
942 | struct vivi_fmt *fmt; | 996 | const struct vivi_fmt *fmt; |
943 | 997 | ||
944 | fmt = get_format(f); | 998 | fmt = get_format(f); |
945 | if (!fmt) { | 999 | if (!fmt) { |
@@ -1044,6 +1098,70 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
1044 | return 0; | 1098 | return 0; |
1045 | } | 1099 | } |
1046 | 1100 | ||
1101 | /* timeperframe is arbitrary and continous */ | ||
1102 | static int vidioc_enum_frameintervals(struct file *file, void *priv, | ||
1103 | struct v4l2_frmivalenum *fival) | ||
1104 | { | ||
1105 | const struct vivi_fmt *fmt; | ||
1106 | |||
1107 | if (fival->index) | ||
1108 | return -EINVAL; | ||
1109 | |||
1110 | fmt = __get_format(fival->pixel_format); | ||
1111 | if (!fmt) | ||
1112 | return -EINVAL; | ||
1113 | |||
1114 | /* regarding width & height - we support any */ | ||
1115 | |||
1116 | fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; | ||
1117 | |||
1118 | /* fill in stepwise (step=1.0 is requred by V4L2 spec) */ | ||
1119 | fival->stepwise.min = tpf_min; | ||
1120 | fival->stepwise.max = tpf_max; | ||
1121 | fival->stepwise.step = (struct v4l2_fract) {1, 1}; | ||
1122 | |||
1123 | return 0; | ||
1124 | } | ||
1125 | |||
1126 | static int vidioc_g_parm(struct file *file, void *priv, | ||
1127 | struct v4l2_streamparm *parm) | ||
1128 | { | ||
1129 | struct vivi_dev *dev = video_drvdata(file); | ||
1130 | |||
1131 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1132 | return -EINVAL; | ||
1133 | |||
1134 | parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; | ||
1135 | parm->parm.capture.timeperframe = dev->timeperframe; | ||
1136 | parm->parm.capture.readbuffers = 1; | ||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | #define FRACT_CMP(a, OP, b) \ | ||
1141 | ((u64)(a).numerator * (b).denominator OP (u64)(b).numerator * (a).denominator) | ||
1142 | |||
1143 | static int vidioc_s_parm(struct file *file, void *priv, | ||
1144 | struct v4l2_streamparm *parm) | ||
1145 | { | ||
1146 | struct vivi_dev *dev = video_drvdata(file); | ||
1147 | struct v4l2_fract tpf; | ||
1148 | |||
1149 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1150 | return -EINVAL; | ||
1151 | |||
1152 | tpf = parm->parm.capture.timeperframe; | ||
1153 | |||
1154 | /* tpf: {*, 0} resets timing; clip to [min, max]*/ | ||
1155 | tpf = tpf.denominator ? tpf : tpf_default; | ||
1156 | tpf = FRACT_CMP(tpf, <, tpf_min) ? tpf_min : tpf; | ||
1157 | tpf = FRACT_CMP(tpf, >, tpf_max) ? tpf_max : tpf; | ||
1158 | |||
1159 | dev->timeperframe = tpf; | ||
1160 | parm->parm.capture.timeperframe = tpf; | ||
1161 | parm->parm.capture.readbuffers = 1; | ||
1162 | return 0; | ||
1163 | } | ||
1164 | |||
1047 | /* --- controls ---------------------------------------------- */ | 1165 | /* --- controls ---------------------------------------------- */ |
1048 | 1166 | ||
1049 | static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | 1167 | static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
@@ -1202,6 +1320,9 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { | |||
1202 | .vidioc_enum_input = vidioc_enum_input, | 1320 | .vidioc_enum_input = vidioc_enum_input, |
1203 | .vidioc_g_input = vidioc_g_input, | 1321 | .vidioc_g_input = vidioc_g_input, |
1204 | .vidioc_s_input = vidioc_s_input, | 1322 | .vidioc_s_input = vidioc_s_input, |
1323 | .vidioc_enum_frameintervals = vidioc_enum_frameintervals, | ||
1324 | .vidioc_g_parm = vidioc_g_parm, | ||
1325 | .vidioc_s_parm = vidioc_s_parm, | ||
1205 | .vidioc_streamon = vb2_ioctl_streamon, | 1326 | .vidioc_streamon = vb2_ioctl_streamon, |
1206 | .vidioc_streamoff = vb2_ioctl_streamoff, | 1327 | .vidioc_streamoff = vb2_ioctl_streamoff, |
1207 | .vidioc_log_status = v4l2_ctrl_log_status, | 1328 | .vidioc_log_status = v4l2_ctrl_log_status, |
@@ -1209,7 +1330,7 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { | |||
1209 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | 1330 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
1210 | }; | 1331 | }; |
1211 | 1332 | ||
1212 | static struct video_device vivi_template = { | 1333 | static const struct video_device vivi_template = { |
1213 | .name = "vivi", | 1334 | .name = "vivi", |
1214 | .fops = &vivi_fops, | 1335 | .fops = &vivi_fops, |
1215 | .ioctl_ops = &vivi_ioctl_ops, | 1336 | .ioctl_ops = &vivi_ioctl_ops, |
@@ -1260,6 +1381,7 @@ static int __init vivi_create_instance(int inst) | |||
1260 | goto free_dev; | 1381 | goto free_dev; |
1261 | 1382 | ||
1262 | dev->fmt = &formats[0]; | 1383 | dev->fmt = &formats[0]; |
1384 | dev->timeperframe = tpf_default; | ||
1263 | dev->width = 640; | 1385 | dev->width = 640; |
1264 | dev->height = 480; | 1386 | dev->height = 480; |
1265 | dev->pixelsize = dev->fmt->depth / 8; | 1387 | dev->pixelsize = dev->fmt->depth / 8; |