linux-omap 2.6.37: sync with OE .dev
[glsdk/meta-ti-glsdk.git] / recipes-bsp / linux / linux-omap / media / 0043-OMAP3-ISP-driver.patch
1 From f12978691d5189949c9296bceb43c5b272c9c03c Mon Sep 17 00:00:00 2001
2 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3 Date: Tue, 17 Feb 2009 09:23:45 -0600
4 Subject: [PATCH 43/43] OMAP3 ISP driver
6 Last 10 commits from upstream are
8 omap3isp: Autoidle enabled for ISP
9 omap3isp: enable AUTOIDLE through module parameter
10 omap3isp: preview: Fix defect correct config function
11 omap3isp: video: Replace BUG with WARN_ON in case of buffer queue error
12 omap3isp: Add module device table
13 omap3isp: csi2: Print registers on stream on
14 v4l: OMAP3 ISP CCDC: Add support for 8bit greyscale sensors
15 omap3isp: ccdc: Set default DC subtract value to 0
16 omap3isp: Prefix all public symbols with omap3isp_
17 omap3isp: Fix dependencies and mark as experimental
19 Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
20 Signed-off-by: Sakari Ailus <sakari.ailus@nokia.com>
21 Signed-off-by: David Cohen <david.cohen@nokia.com>
22 Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
23 Signed-off-by: Vimarsh Zutshi <vimarsh.zutshi@nokia.com>
24 Signed-off-by: Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
25 Signed-off-by: Sergio Aguirre <saaguirre@ti.com>
26 Signed-off-by: Antti Koskipaa <antti.koskipaa@nokia.com>
27 Signed-off-by: Ivan T. Ivanov <iivanov@mm-sol.com>
28 Signed-off-by: RaniSuneela <r-m@ti.com>
29 Signed-off-by: Atanas Filipov <afilipov@mm-sol.com>
30 Signed-off-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com>
31 Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
32 Signed-off-by: Nayden Kanchev <nkanchev@mm-sol.com>
33 Signed-off-by: Phil Carmody <ext-phil.2.carmody@nokia.com>
34 Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
35 Signed-off-by: Dominic Curran <dcurran@ti.com>
36 Signed-off-by: Ilkka Myllyperkio <ilkka.myllyperkio@sofica.fi>
37 Signed-off-by: Pallavi Kulkarni <p-kulkarni@ti.com>
38 Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
39 ---
40  drivers/media/video/Kconfig                  |   13 +
41  drivers/media/video/Makefile                 |    2 +
42  drivers/media/video/isp/Makefile             |   13 +
43  drivers/media/video/isp/cfa_coef_table.h     |  601 +++++++
44  drivers/media/video/isp/gamma_table.h        |   90 +
45  drivers/media/video/isp/isp.c                | 2221 +++++++++++++++++++++++++
46  drivers/media/video/isp/isp.h                |  427 +++++
47  drivers/media/video/isp/ispccdc.c            | 2280 ++++++++++++++++++++++++++
48  drivers/media/video/isp/ispccdc.h            |  223 +++
49  drivers/media/video/isp/ispccp2.c            | 1189 ++++++++++++++
50  drivers/media/video/isp/ispccp2.h            |  101 ++
51  drivers/media/video/isp/ispcsi2.c            | 1332 +++++++++++++++
52  drivers/media/video/isp/ispcsi2.h            |  169 ++
53  drivers/media/video/isp/ispcsiphy.c          |  247 +++
54  drivers/media/video/isp/ispcsiphy.h          |   74 +
55  drivers/media/video/isp/isph3a.h             |  117 ++
56  drivers/media/video/isp/isph3a_aewb.c        |  374 +++++
57  drivers/media/video/isp/isph3a_af.c          |  429 +++++
58  drivers/media/video/isp/isphist.c            |  520 ++++++
59  drivers/media/video/isp/isphist.h            |   40 +
60  drivers/media/video/isp/isppreview.c         | 2120 ++++++++++++++++++++++++
61  drivers/media/video/isp/isppreview.h         |  214 +++
62  drivers/media/video/isp/ispqueue.c           | 1136 +++++++++++++
63  drivers/media/video/isp/ispqueue.h           |  185 +++
64  drivers/media/video/isp/ispreg.h             | 1589 ++++++++++++++++++
65  drivers/media/video/isp/ispresizer.c         | 1710 +++++++++++++++++++
66  drivers/media/video/isp/ispresizer.h         |  150 ++
67  drivers/media/video/isp/ispstat.c            | 1100 +++++++++++++
68  drivers/media/video/isp/ispstat.h            |  169 ++
69  drivers/media/video/isp/ispvideo.c           | 1264 ++++++++++++++
70  drivers/media/video/isp/ispvideo.h           |  202 +++
71  drivers/media/video/isp/luma_enhance_table.h |  154 ++
72  drivers/media/video/isp/noise_filter_table.h |   90 +
73  include/linux/Kbuild                         |    1 +
74  include/linux/omap3isp.h                     |  631 +++++++
75  35 files changed, 21177 insertions(+), 0 deletions(-)
76  create mode 100644 drivers/media/video/isp/Makefile
77  create mode 100644 drivers/media/video/isp/cfa_coef_table.h
78  create mode 100644 drivers/media/video/isp/gamma_table.h
79  create mode 100644 drivers/media/video/isp/isp.c
80  create mode 100644 drivers/media/video/isp/isp.h
81  create mode 100644 drivers/media/video/isp/ispccdc.c
82  create mode 100644 drivers/media/video/isp/ispccdc.h
83  create mode 100644 drivers/media/video/isp/ispccp2.c
84  create mode 100644 drivers/media/video/isp/ispccp2.h
85  create mode 100644 drivers/media/video/isp/ispcsi2.c
86  create mode 100644 drivers/media/video/isp/ispcsi2.h
87  create mode 100644 drivers/media/video/isp/ispcsiphy.c
88  create mode 100644 drivers/media/video/isp/ispcsiphy.h
89  create mode 100644 drivers/media/video/isp/isph3a.h
90  create mode 100644 drivers/media/video/isp/isph3a_aewb.c
91  create mode 100644 drivers/media/video/isp/isph3a_af.c
92  create mode 100644 drivers/media/video/isp/isphist.c
93  create mode 100644 drivers/media/video/isp/isphist.h
94  create mode 100644 drivers/media/video/isp/isppreview.c
95  create mode 100644 drivers/media/video/isp/isppreview.h
96  create mode 100644 drivers/media/video/isp/ispqueue.c
97  create mode 100644 drivers/media/video/isp/ispqueue.h
98  create mode 100644 drivers/media/video/isp/ispreg.h
99  create mode 100644 drivers/media/video/isp/ispresizer.c
100  create mode 100644 drivers/media/video/isp/ispresizer.h
101  create mode 100644 drivers/media/video/isp/ispstat.c
102  create mode 100644 drivers/media/video/isp/ispstat.h
103  create mode 100644 drivers/media/video/isp/ispvideo.c
104  create mode 100644 drivers/media/video/isp/ispvideo.h
105  create mode 100644 drivers/media/video/isp/luma_enhance_table.h
106  create mode 100644 drivers/media/video/isp/noise_filter_table.h
107  create mode 100644 include/linux/omap3isp.h
109 diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
110 index 6830d28..60c2bf0 100644
111 --- a/drivers/media/video/Kconfig
112 +++ b/drivers/media/video/Kconfig
113 @@ -722,6 +722,19 @@ config VIDEO_VIA_CAMERA
114            Chrome9 chipsets.  Currently only tested on OLPC xo-1.5 systems
115            with ov7670 sensors.
116  
117 +config VIDEO_OMAP3
118 +       tristate "OMAP 3 Camera support (EXPERIMENTAL)"
119 +       select OMAP_IOMMU
120 +       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
121 +       ---help---
122 +         Driver for an OMAP 3 camera controller.
124 +config VIDEO_OMAP3_DEBUG
125 +       bool "OMAP 3 Camera debug messages"
126 +       depends on VIDEO_OMAP3
127 +       ---help---
128 +         Enable debug messages on OMAP 3 camera controller driver.
130  config SOC_CAMERA
131         tristate "SoC camera support"
132         depends on VIDEO_V4L2 && HAS_DMA && I2C
133 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
134 index adc1bd5..bd2f556 100644
135 --- a/drivers/media/video/Makefile
136 +++ b/drivers/media/video/Makefile
137 @@ -124,6 +124,8 @@ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
138  
139  obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
140  
141 +obj-$(CONFIG_VIDEO_OMAP3)      += isp/
143  obj-$(CONFIG_USB_DABUSB)        += dabusb.o
144  obj-$(CONFIG_USB_SE401)         += se401.o
145  obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
146 diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
147 new file mode 100644
148 index 0000000..b1b3447
149 --- /dev/null
150 +++ b/drivers/media/video/isp/Makefile
151 @@ -0,0 +1,13 @@
152 +# Makefile for OMAP3 ISP driver
154 +ifdef CONFIG_VIDEO_OMAP3_DEBUG
155 +EXTRA_CFLAGS += -DDEBUG
156 +endif
158 +omap3-isp-objs += \
159 +       isp.o ispqueue.o ispvideo.o \
160 +       ispcsiphy.o ispccp2.o ispcsi2.o \
161 +       ispccdc.o isppreview.o ispresizer.o \
162 +       ispstat.o isph3a_aewb.o isph3a_af.o isphist.o
164 +obj-$(CONFIG_VIDEO_OMAP3) += omap3-isp.o
165 diff --git a/drivers/media/video/isp/cfa_coef_table.h b/drivers/media/video/isp/cfa_coef_table.h
166 new file mode 100644
167 index 0000000..4ec3fff
168 --- /dev/null
169 +++ b/drivers/media/video/isp/cfa_coef_table.h
170 @@ -0,0 +1,601 @@
171 +/*
172 + * cfa_coef_table.h
173 + *
174 + * TI OMAP3 ISP - CFA coefficients table
175 + *
176 + * Copyright (C) 2009-2010 Nokia Corporation
177 + *
178 + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
179 + *          Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
180 + *
181 + * This program is free software; you can redistribute it and/or
182 + * modify it under the terms of the GNU General Public License
183 + * version 2 as published by the Free Software Foundation.
184 + *
185 + * This program is distributed in the hope that it will be useful, but
186 + * WITHOUT ANY WARRANTY; without even the implied warranty of
187 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
188 + * General Public License for more details.
189 + *
190 + * You should have received a copy of the GNU General Public License
191 + * along with this program; if not, write to the Free Software
192 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
193 + * 02110-1301 USA
194 + */
196 +244,
197 +0,
198 +247,
199 +0,
200 +12,
201 +27,
202 +36,
203 +247,
204 +250,
205 +0,
206 +27,
207 +0,
208 +4,
209 +250,
210 +12,
211 +244,
212 +248,
213 +0,
214 +0,
215 +0,
216 +0,
217 +40,
218 +0,
219 +0,
220 +244,
221 +12,
222 +250,
223 +4,
224 +0,
225 +27,
226 +0,
227 +250,
228 +247,
229 +36,
230 +27,
231 +12,
232 +0,
233 +247,
234 +0,
235 +244,
236 +0,
237 +0,
238 +40,
239 +0,
240 +0,
241 +0,
242 +0,
243 +248,
244 +244,
245 +0,
246 +247,
247 +0,
248 +12,
249 +27,
250 +36,
251 +247,
252 +250,
253 +0,
254 +27,
255 +0,
256 +4,
257 +250,
258 +12,
259 +244,
260 +248,
261 +0,
262 +0,
263 +0,
264 +0,
265 +40,
266 +0,
267 +0,
268 +244,
269 +12,
270 +250,
271 +4,
272 +0,
273 +27,
274 +0,
275 +250,
276 +247,
277 +36,
278 +27,
279 +12,
280 +0,
281 +247,
282 +0,
283 +244,
284 +0,
285 +0,
286 +40,
287 +0,
288 +0,
289 +0,
290 +0,
291 +248,
292 +244,
293 +0,
294 +247,
295 +0,
296 +12,
297 +27,
298 +36,
299 +247,
300 +250,
301 +0,
302 +27,
303 +0,
304 +4,
305 +250,
306 +12,
307 +244,
308 +248,
309 +0,
310 +0,
311 +0,
312 +0,
313 +40,
314 +0,
315 +0,
316 +244,
317 +12,
318 +250,
319 +4,
320 +0,
321 +27,
322 +0,
323 +250,
324 +247,
325 +36,
326 +27,
327 +12,
328 +0,
329 +247,
330 +0,
331 +244,
332 +0,
333 +0,
334 +40,
335 +0,
336 +0,
337 +0,
338 +0,
339 +248,
340 +0,
341 +247,
342 +0,
343 +244,
344 +247,
345 +36,
346 +27,
347 +12,
348 +0,
349 +27,
350 +0,
351 +250,
352 +244,
353 +12,
354 +250,
355 +4,
356 +0,
357 +0,
358 +0,
359 +248,
360 +0,
361 +0,
362 +40,
363 +0,
364 +4,
365 +250,
366 +12,
367 +244,
368 +250,
369 +0,
370 +27,
371 +0,
372 +12,
373 +27,
374 +36,
375 +247,
376 +244,
377 +0,
378 +247,
379 +0,
380 +0,
381 +40,
382 +0,
383 +0,
384 +248,
385 +0,
386 +0,
387 +0,
388 +0,
389 +247,
390 +0,
391 +244,
392 +247,
393 +36,
394 +27,
395 +12,
396 +0,
397 +27,
398 +0,
399 +250,
400 +244,
401 +12,
402 +250,
403 +4,
404 +0,
405 +0,
406 +0,
407 +248,
408 +0,
409 +0,
410 +40,
411 +0,
412 +4,
413 +250,
414 +12,
415 +244,
416 +250,
417 +0,
418 +27,
419 +0,
420 +12,
421 +27,
422 +36,
423 +247,
424 +244,
425 +0,
426 +247,
427 +0,
428 +0,
429 +40,
430 +0,
431 +0,
432 +248,
433 +0,
434 +0,
435 +0,
436 +0,
437 +247,
438 +0,
439 +244,
440 +247,
441 +36,
442 +27,
443 +12,
444 +0,
445 +27,
446 +0,
447 +250,
448 +244,
449 +12,
450 +250,
451 +4,
452 +0,
453 +0,
454 +0,
455 +248,
456 +0,
457 +0,
458 +40,
459 +0,
460 +4,
461 +250,
462 +12,
463 +244,
464 +250,
465 +0,
466 +27,
467 +0,
468 +12,
469 +27,
470 +36,
471 +247,
472 +244,
473 +0,
474 +247,
475 +0,
476 +0,
477 +40,
478 +0,
479 +0,
480 +248,
481 +0,
482 +0,
483 +0,
484 +4,
485 +250,
486 +12,
487 +244,
488 +250,
489 +0,
490 +27,
491 +0,
492 +12,
493 +27,
494 +36,
495 +247,
496 +244,
497 +0,
498 +247,
499 +0,
500 +0,
501 +0,
502 +0,
503 +248,
504 +0,
505 +0,
506 +40,
507 +0,
508 +0,
509 +247,
510 +0,
511 +244,
512 +247,
513 +36,
514 +27,
515 +12,
516 +0,
517 +27,
518 +0,
519 +250,
520 +244,
521 +12,
522 +250,
523 +4,
524 +0,
525 +40,
526 +0,
527 +0,
528 +248,
529 +0,
530 +0,
531 +0,
532 +4,
533 +250,
534 +12,
535 +244,
536 +250,
537 +0,
538 +27,
539 +0,
540 +12,
541 +27,
542 +36,
543 +247,
544 +244,
545 +0,
546 +247,
547 +0,
548 +0,
549 +0,
550 +0,
551 +248,
552 +0,
553 +0,
554 +40,
555 +0,
556 +0,
557 +247,
558 +0,
559 +244,
560 +247,
561 +36,
562 +27,
563 +12,
564 +0,
565 +27,
566 +0,
567 +250,
568 +244,
569 +12,
570 +250,
571 +4,
572 +0,
573 +40,
574 +0,
575 +0,
576 +248,
577 +0,
578 +0,
579 +0,
580 +4,
581 +250,
582 +12,
583 +244,
584 +250,
585 +0,
586 +27,
587 +0,
588 +12,
589 +27,
590 +36,
591 +247,
592 +244,
593 +0,
594 +247,
595 +0,
596 +0,
597 +0,
598 +0,
599 +248,
600 +0,
601 +0,
602 +40,
603 +0,
604 +0,
605 +247,
606 +0,
607 +244,
608 +247,
609 +36,
610 +27,
611 +12,
612 +0,
613 +27,
614 +0,
615 +250,
616 +244,
617 +12,
618 +250,
619 +4,
620 +0,
621 +40,
622 +0,
623 +0,
624 +248,
625 +0,
626 +0,
627 +0,
628 +244,
629 +12,
630 +250,
631 +4,
632 +0,
633 +27,
634 +0,
635 +250,
636 +247,
637 +36,
638 +27,
639 +12,
640 +0,
641 +247,
642 +0,
643 +244,
644 +248,
645 +0,
646 +0,
647 +0,
648 +0,
649 +40,
650 +0,
651 +0,
652 +244,
653 +0,
654 +247,
655 +0,
656 +12,
657 +27,
658 +36,
659 +247,
660 +250,
661 +0,
662 +27,
663 +0,
664 +4,
665 +250,
666 +12,
667 +244,
668 +0,
669 +0,
670 +40,
671 +0,
672 +0,
673 +0,
674 +0,
675 +248,
676 +244,
677 +12,
678 +250,
679 +4,
680 +0,
681 +27,
682 +0,
683 +250,
684 +247,
685 +36,
686 +27,
687 +12,
688 +0,
689 +247,
690 +0,
691 +244,
692 +248,
693 +0,
694 +0,
695 +0,
696 +0,
697 +40,
698 +0,
699 +0,
700 +244,
701 +0,
702 +247,
703 +0,
704 +12,
705 +27,
706 +36,
707 +247,
708 +250,
709 +0,
710 +27,
711 +0,
712 +4,
713 +250,
714 +12,
715 +244,
716 +0,
717 +0,
718 +40,
719 +0,
720 +0,
721 +0,
722 +0,
723 +248,
724 +244,
725 +12,
726 +250,
727 +4,
728 +0,
729 +27,
730 +0,
731 +250,
732 +247,
733 +36,
734 +27,
735 +12,
736 +0,
737 +247,
738 +0,
739 +244,
740 +248,
741 +0,
742 +0,
743 +0,
744 +0,
745 +40,
746 +0,
747 +0,
748 +244,
749 +0,
750 +247,
751 +0,
752 +12,
753 +27,
754 +36,
755 +247,
756 +250,
757 +0,
758 +27,
759 +0,
760 +4,
761 +250,
762 +12,
763 +244,
764 +0,
765 +0,
766 +40,
767 +0,
768 +0,
769 +0,
770 +0,
771 +248
772 diff --git a/drivers/media/video/isp/gamma_table.h b/drivers/media/video/isp/gamma_table.h
773 new file mode 100644
774 index 0000000..c2f7ec1
775 --- /dev/null
776 +++ b/drivers/media/video/isp/gamma_table.h
777 @@ -0,0 +1,90 @@
778 +/*
779 + * gamma_table.h
780 + *
781 + * TI OMAP3 ISP - Default gamma table for all components
782 + *
783 + * Copyright (C) 2010 Nokia Corporation
784 + * Copyright (C) 2009 Texas Instruments, Inc.
785 + *
786 + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
787 + *          Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
788 + *
789 + * This program is free software; you can redistribute it and/or modify
790 + * it under the terms of the GNU General Public License version 2 as
791 + * published by the Free Software Foundation.
792 + *
793 + * This program is distributed in the hope that it will be useful, but
794 + * WITHOUT ANY WARRANTY; without even the implied warranty of
795 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
796 + * General Public License for more details.
797 + *
798 + * You should have received a copy of the GNU General Public License
799 + * along with this program; if not, write to the Free Software
800 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
801 + * 02110-1301 USA
802 + */
804 +  0,   0,   1,   2,   3,   3,   4,   5,   6,   8,  10,  12,  14,  16,  18,  20,
805 + 22,  23,  25,  26,  28,  29,  31,  32,  34,  35,  36,  37,  39,  40,  41,  42,
806 + 43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  52,  53,  54,  55,  56,  57,
807 + 58,  59,  60,  61,  62,  63,  63,  64,  65,  66,  66,  67,  68,  69,  69,  70,
808 + 71,  72,  72,  73,  74,  75,  75,  76,  77,  78,  78,  79,  80,  81,  81,  82,
809 + 83,  84,  84,  85,  86,  87,  88,  88,  89,  90,  91,  91,  92,  93,  94,  94,
810 + 95,  96,  97,  97,  98,  98,  99,  99, 100, 100, 101, 101, 102, 103, 104, 104,
811 +105, 106, 107, 108, 108, 109, 110, 111, 111, 112, 113, 114, 114, 115, 116, 117,
812 +117, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125,
813 +126, 126, 127, 127, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 133,
814 +134, 134, 135, 135, 136, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141,
815 +142, 142, 143, 143, 144, 144, 145, 145, 146, 146, 147, 147, 148, 148, 149, 149,
816 +150, 150, 151, 151, 152, 152, 153, 153, 153, 153, 154, 154, 154, 154, 155, 155,
817 +156, 156, 157, 157, 158, 158, 158, 159, 159, 159, 160, 160, 160, 161, 161, 162,
818 +162, 163, 163, 164, 164, 164, 164, 165, 165, 165, 165, 166, 166, 167, 167, 168,
819 +168, 169, 169, 170, 170, 170, 170, 171, 171, 171, 171, 172, 172, 173, 173, 174,
820 +174, 175, 175, 176, 176, 176, 176, 177, 177, 177, 177, 178, 178, 178, 178, 179,
821 +179, 179, 179, 180, 180, 180, 180, 181, 181, 181, 181, 182, 182, 182, 182, 183,
822 +183, 183, 183, 184, 184, 184, 184, 185, 185, 185, 185, 186, 186, 186, 186, 187,
823 +187, 187, 187, 188, 188, 188, 188, 189, 189, 189, 189, 190, 190, 190, 190, 191,
824 +191, 191, 191, 192, 192, 192, 192, 193, 193, 193, 193, 194, 194, 194, 194, 195,
825 +195, 195, 195, 196, 196, 196, 196, 197, 197, 197, 197, 198, 198, 198, 198, 199,
826 +199, 199, 199, 200, 200, 200, 200, 201, 201, 201, 201, 202, 202, 202, 203, 203,
827 +203, 203, 204, 204, 204, 204, 205, 205, 205, 205, 206, 206, 206, 206, 207, 207,
828 +207, 207, 208, 208, 208, 208, 209, 209, 209, 209, 210, 210, 210, 210, 210, 210,
829 +210, 210, 210, 210, 210, 210, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
830 +211, 212, 212, 212, 212, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
831 +213, 214, 214, 214, 214, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
832 +216, 216, 216, 216, 217, 217, 217, 217, 218, 218, 218, 218, 219, 219, 219, 219,
833 +219, 219, 219, 219, 219, 219, 219, 219, 220, 220, 220, 220, 221, 221, 221, 221,
834 +221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 223, 223, 223, 223, 223,
835 +223, 223, 223, 223, 223, 223, 223, 224, 224, 224, 224, 225, 225, 225, 225, 225,
836 +225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 226, 226,
837 +226, 226, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 228, 228,
838 +228, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 230, 230, 230,
839 +230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 232, 232, 232,
840 +232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
841 +233, 233, 233, 233, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 235,
842 +235, 235, 235, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236,
843 +236, 236, 236, 236, 236, 236, 237, 237, 237, 237, 238, 238, 238, 238, 238, 238,
844 +238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
845 +238, 238, 238, 238, 238, 239, 239, 239, 239, 240, 240, 240, 240, 240, 240, 240,
846 +240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
847 +240, 240, 240, 240, 241, 241, 241, 241, 242, 242, 242, 242, 242, 242, 242, 242,
848 +242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242,
849 +242, 242, 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
850 +244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
851 +244, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246,
852 +246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246,
853 +246, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 248, 248, 248, 248, 248,
854 +248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
855 +248, 248, 248, 248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 250, 250,
856 +250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
857 +250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
858 +250, 250, 250, 250, 251, 251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 252,
859 +252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
860 +252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
861 +252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
862 +252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253, 253,
863 +253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
864 +253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
865 +253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
866 +253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
867 +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
868 diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
869 new file mode 100644
870 index 0000000..6f8527c
871 --- /dev/null
872 +++ b/drivers/media/video/isp/isp.c
873 @@ -0,0 +1,2221 @@
874 +/*
875 + * isp.c
876 + *
877 + * TI OMAP3 ISP - Core
878 + *
879 + * Copyright (C) 2006-2010 Nokia Corporation
880 + * Copyright (C) 2007-2009 Texas Instruments, Inc.
881 + *
882 + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
883 + *          Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
884 + *
885 + * Contributors:
886 + *     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
887 + *     Sakari Ailus <sakari.ailus@nokia.com>
888 + *     David Cohen <david.cohen@nokia.com>
889 + *     Stanimir Varbanov <svarbanov@mm-sol.com>
890 + *     Vimarsh Zutshi <vimarsh.zutshi@nokia.com>
891 + *     Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
892 + *     Sergio Aguirre <saaguirre@ti.com>
893 + *     Antti Koskipaa <antti.koskipaa@nokia.com>
894 + *     Ivan T. Ivanov <iivanov@mm-sol.com>
895 + *     RaniSuneela <r-m@ti.com>
896 + *     Atanas Filipov <afilipov@mm-sol.com>
897 + *     Gjorgji Rosikopulos <grosikopulos@mm-sol.com>
898 + *     Hiroshi DOYU <hiroshi.doyu@nokia.com>
899 + *     Nayden Kanchev <nkanchev@mm-sol.com>
900 + *     Phil Carmody <ext-phil.2.carmody@nokia.com>
901 + *     Artem Bityutskiy <artem.bityutskiy@nokia.com>
902 + *     Dominic Curran <dcurran@ti.com>
903 + *     Ilkka Myllyperkio <ilkka.myllyperkio@sofica.fi>
904 + *     Pallavi Kulkarni <p-kulkarni@ti.com>
905 + *     Vaibhav Hiremath <hvaibhav@ti.com>
906 + *     Mohit Jalori <mjalori@ti.com>
907 + *     Sameer Venkatraman <sameerv@ti.com>
908 + *     Senthilvadivu Guruswamy <svadivu@ti.com>
909 + *     Thara Gopinath <thara@ti.com>
910 + *     Toni Leinonen <toni.leinonen@nokia.com>
911 + *     Troy Laramy <t-laramy@ti.com>
912 + *
913 + * This program is free software; you can redistribute it and/or modify
914 + * it under the terms of the GNU General Public License version 2 as
915 + * published by the Free Software Foundation.
916 + *
917 + * This program is distributed in the hope that it will be useful, but
918 + * WITHOUT ANY WARRANTY; without even the implied warranty of
919 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
920 + * General Public License for more details.
921 + *
922 + * You should have received a copy of the GNU General Public License
923 + * along with this program; if not, write to the Free Software
924 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
925 + * 02110-1301 USA
926 + */
928 +#include <asm/cacheflush.h>
930 +#include <linux/clk.h>
931 +#include <linux/delay.h>
932 +#include <linux/device.h>
933 +#include <linux/dma-mapping.h>
934 +#include <linux/i2c.h>
935 +#include <linux/interrupt.h>
936 +#include <linux/module.h>
937 +#include <linux/platform_device.h>
938 +#include <linux/regulator/consumer.h>
939 +#include <linux/slab.h>
940 +#include <linux/sched.h>
941 +#include <linux/vmalloc.h>
943 +#include <media/v4l2-common.h>
944 +#include <media/v4l2-device.h>
946 +#include "isp.h"
947 +#include "ispreg.h"
948 +#include "ispccdc.h"
949 +#include "isppreview.h"
950 +#include "ispresizer.h"
951 +#include "ispcsi2.h"
952 +#include "ispccp2.h"
953 +#include "isph3a.h"
954 +#include "isphist.h"
956 +static unsigned int autoidle;
957 +module_param(autoidle, int, 0444);
958 +MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support");
960 +static void isp_save_ctx(struct isp_device *isp);
962 +static void isp_restore_ctx(struct isp_device *isp);
964 +static const struct isp_res_mapping isp_res_maps[] = {
965 +       {
966 +               .isp_rev = ISP_REVISION_2_0,
967 +               .map = 1 << OMAP3_ISP_IOMEM_MAIN |
968 +                      1 << OMAP3_ISP_IOMEM_CCP2 |
969 +                      1 << OMAP3_ISP_IOMEM_CCDC |
970 +                      1 << OMAP3_ISP_IOMEM_HIST |
971 +                      1 << OMAP3_ISP_IOMEM_H3A |
972 +                      1 << OMAP3_ISP_IOMEM_PREV |
973 +                      1 << OMAP3_ISP_IOMEM_RESZ |
974 +                      1 << OMAP3_ISP_IOMEM_SBL |
975 +                      1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
976 +                      1 << OMAP3_ISP_IOMEM_CSIPHY2,
977 +       },
978 +       {
979 +               .isp_rev = ISP_REVISION_15_0,
980 +               .map = 1 << OMAP3_ISP_IOMEM_MAIN |
981 +                      1 << OMAP3_ISP_IOMEM_CCP2 |
982 +                      1 << OMAP3_ISP_IOMEM_CCDC |
983 +                      1 << OMAP3_ISP_IOMEM_HIST |
984 +                      1 << OMAP3_ISP_IOMEM_H3A |
985 +                      1 << OMAP3_ISP_IOMEM_PREV |
986 +                      1 << OMAP3_ISP_IOMEM_RESZ |
987 +                      1 << OMAP3_ISP_IOMEM_SBL |
988 +                      1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
989 +                      1 << OMAP3_ISP_IOMEM_CSIPHY2 |
990 +                      1 << OMAP3_ISP_IOMEM_CSI2A_REGS2 |
991 +                      1 << OMAP3_ISP_IOMEM_CSI2C_REGS1 |
992 +                      1 << OMAP3_ISP_IOMEM_CSIPHY1 |
993 +                      1 << OMAP3_ISP_IOMEM_CSI2C_REGS2,
994 +       },
995 +};
997 +/* Structure for saving/restoring ISP module registers */
998 +static struct isp_reg isp_reg_list[] = {
999 +       {OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG, 0},
1000 +       {OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, 0},
1001 +       {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL, 0},
1002 +       {0, ISP_TOK_TERM, 0}
1003 +};
1005 +/*
1006 + * omap3isp_flush - Post pending L3 bus writes by doing a register readback
1007 + * @isp: OMAP3 ISP device
1008 + *
1009 + * In order to force posting of pending writes, we need to write and
1010 + * readback the same register, in this case the revision register.
1011 + *
1012 + * See this link for reference:
1013 + *   http://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html
1014 + */
1015 +void omap3isp_flush(struct isp_device *isp)
1016 +{
1017 +       isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
1018 +       isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
1019 +}
1021 +/*
1022 + * isp_enable_interrupts - Enable ISP interrupts.
1023 + * @isp: OMAP3 ISP device
1024 + */
1025 +static void isp_enable_interrupts(struct isp_device *isp)
1026 +{
1027 +       static const u32 irq = IRQ0ENABLE_CSIA_IRQ
1028 +                            | IRQ0ENABLE_CSIB_IRQ
1029 +                            | IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ
1030 +                            | IRQ0ENABLE_CCDC_LSC_DONE_IRQ
1031 +                            | IRQ0ENABLE_CCDC_VD0_IRQ
1032 +                            | IRQ0ENABLE_CCDC_VD1_IRQ
1033 +                            | IRQ0ENABLE_HS_VS_IRQ
1034 +                            | IRQ0ENABLE_HIST_DONE_IRQ
1035 +                            | IRQ0ENABLE_H3A_AWB_DONE_IRQ
1036 +                            | IRQ0ENABLE_H3A_AF_DONE_IRQ
1037 +                            | IRQ0ENABLE_PRV_DONE_IRQ
1038 +                            | IRQ0ENABLE_RSZ_DONE_IRQ;
1040 +       isp_reg_writel(isp, irq, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
1041 +       isp_reg_writel(isp, irq, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE);
1042 +}
1044 +/*
1045 + * isp_disable_interrupts - Disable ISP interrupts.
1046 + * @isp: OMAP3 ISP device
1047 + */
1048 +static void isp_disable_interrupts(struct isp_device *isp)
1049 +{
1050 +       isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE);
1051 +}
1053 +/**
1054 + * isp_set_xclk - Configures the specified cam_xclk to the desired frequency.
1055 + * @isp: OMAP3 ISP device
1056 + * @xclk: Desired frequency of the clock in Hz. 0 = stable low, 1 is stable high
1057 + * @xclksel: XCLK to configure (0 = A, 1 = B).
1058 + *
1059 + * Configures the specified MCLK divisor in the ISP timing control register
1060 + * (TCTRL_CTRL) to generate the desired xclk clock value.
1061 + *
1062 + * Divisor = cam_mclk_hz / xclk
1063 + *
1064 + * Returns the final frequency that is actually being generated
1065 + **/
1066 +static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
1067 +{
1068 +       u32 divisor;
1069 +       u32 currentxclk;
1070 +       unsigned long mclk_hz;
1072 +       if (!omap3isp_get(isp))
1073 +               return 0;
1075 +       mclk_hz = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
1077 +       if (xclk >= mclk_hz) {
1078 +               divisor = ISPTCTRL_CTRL_DIV_BYPASS;
1079 +               currentxclk = mclk_hz;
1080 +       } else if (xclk >= 2) {
1081 +               divisor = mclk_hz / xclk;
1082 +               if (divisor >= ISPTCTRL_CTRL_DIV_BYPASS)
1083 +                       divisor = ISPTCTRL_CTRL_DIV_BYPASS - 1;
1084 +               currentxclk = mclk_hz / divisor;
1085 +       } else {
1086 +               divisor = xclk;
1087 +               currentxclk = 0;
1088 +       }
1090 +       switch (xclksel) {
1091 +       case 0:
1092 +               isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
1093 +                               ISPTCTRL_CTRL_DIVA_MASK,
1094 +                               divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
1095 +               dev_dbg(isp->dev, "isp_set_xclk(): cam_xclka set to %d Hz\n",
1096 +                       currentxclk);
1097 +               break;
1098 +       case 1:
1099 +               isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
1100 +                               ISPTCTRL_CTRL_DIVB_MASK,
1101 +                               divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
1102 +               dev_dbg(isp->dev, "isp_set_xclk(): cam_xclkb set to %d Hz\n",
1103 +                       currentxclk);
1104 +               break;
1105 +       default:
1106 +               omap3isp_put(isp);
1107 +               dev_dbg(isp->dev, "ISP_ERR: isp_set_xclk(): Invalid requested "
1108 +                       "xclk. Must be 0 (A) or 1 (B).\n");
1109 +               return -EINVAL;
1110 +       }
1112 +       /* Do we go from stable whatever to clock? */
1113 +       if (divisor >= 2 && isp->xclk_divisor[xclksel] < 2)
1114 +               omap3isp_get(isp);
1115 +       /* Stopping the clock. */
1116 +       else if (divisor < 2 && isp->xclk_divisor[xclksel] >= 2)
1117 +               omap3isp_put(isp);
1119 +       isp->xclk_divisor[xclksel] = divisor;
1121 +       omap3isp_put(isp);
1123 +       return currentxclk;
1124 +}
1126 +/*
1127 + * isp_power_settings - Sysconfig settings, for Power Management.
1128 + * @isp: OMAP3 ISP device
1129 + * @idle: Consider idle state.
1130 + *
1131 + * Sets the power settings for the ISP, and SBL bus.
1132 + */
1133 +static void isp_power_settings(struct isp_device *isp, int idle)
1134 +{
1135 +       isp_reg_writel(isp,
1136 +                      ((idle ? ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY :
1137 +                               ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY) <<
1138 +                       ISP_SYSCONFIG_MIDLEMODE_SHIFT) |
1139 +                       ((isp->revision == ISP_REVISION_15_0) ?
1140 +                          ISP_SYSCONFIG_AUTOIDLE : 0),
1141 +                      OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
1143 +       if (isp->autoidle)
1144 +               isp_reg_writel(isp, ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
1145 +                              ISP_CTRL);
1146 +}
1148 +/*
1149 + * Configure the bridge and lane shifter. Valid inputs are
1150 + *
1151 + * CCDC_INPUT_PARALLEL: Parallel interface
1152 + * CCDC_INPUT_CSI2A: CSI2a receiver
1153 + * CCDC_INPUT_CCP2B: CCP2b receiver
1154 + * CCDC_INPUT_CSI2C: CSI2c receiver
1155 + *
1156 + * The bridge and lane shifter are configured according to the selected input
1157 + * and the ISP platform data.
1158 + */
1159 +void omap3isp_configure_bridge(struct isp_device *isp,
1160 +                              enum ccdc_input_entity input,
1161 +                              const struct isp_parallel_platform_data *pdata)
1162 +{
1163 +       u32 ispctrl_val;
1165 +       ispctrl_val  = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
1166 +       ispctrl_val &= ~ISPCTRL_SHIFT_MASK;
1167 +       ispctrl_val &= ~ISPCTRL_PAR_CLK_POL_INV;
1168 +       ispctrl_val &= ~ISPCTRL_PAR_SER_CLK_SEL_MASK;
1169 +       ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_MASK;
1171 +       switch (input) {
1172 +       case CCDC_INPUT_PARALLEL:
1173 +               ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
1174 +               ispctrl_val |= pdata->data_lane_shift << ISPCTRL_SHIFT_SHIFT;
1175 +               ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
1176 +               ispctrl_val |= pdata->bridge << ISPCTRL_PAR_BRIDGE_SHIFT;
1177 +               break;
1179 +       case CCDC_INPUT_CSI2A:
1180 +               ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIA;
1181 +               break;
1183 +       case CCDC_INPUT_CCP2B:
1184 +               ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIB;
1185 +               break;
1187 +       case CCDC_INPUT_CSI2C:
1188 +               ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIC;
1189 +               break;
1191 +       default:
1192 +               return;
1193 +       }
1195 +       ispctrl_val &= ~ISPCTRL_SYNC_DETECT_MASK;
1196 +       ispctrl_val |= ISPCTRL_SYNC_DETECT_VSRISE;
1198 +       isp_reg_writel(isp, ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
1199 +}
1201 +/**
1202 + * isp_set_pixel_clock - Configures the ISP pixel clock
1203 + * @isp: OMAP3 ISP device
1204 + * @pixelclk: Average pixel clock in Hz
1205 + *
1206 + * Set the average pixel clock required by the sensor. The ISP will use the
1207 + * lowest possible memory bandwidth settings compatible with the clock.
1208 + **/
1209 +static void isp_set_pixel_clock(struct isp_device *isp, unsigned int pixelclk)
1210 +{
1211 +       isp->isp_ccdc.vpcfg.pixelclk = pixelclk;
1212 +}
1214 +void omap3isp_hist_dma_done(struct isp_device *isp)
1215 +{
1216 +       if (omap3isp_ccdc_busy(&isp->isp_ccdc) ||
1217 +           omap3isp_stat_pcr_busy(&isp->isp_hist)) {
1218 +               /* Histogram cannot be enabled in this frame anymore */
1219 +               atomic_set(&isp->isp_hist.buf_err, 1);
1220 +               dev_dbg(isp->dev, "hist: Out of synchronization with "
1221 +                                 "CCDC. Ignoring next buffer.\n");
1222 +       }
1223 +}
1225 +static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus)
1226 +{
1227 +       static const char *name[] = {
1228 +               "CSIA_IRQ",
1229 +               "res1",
1230 +               "res2",
1231 +               "CSIB_LCM_IRQ",
1232 +               "CSIB_IRQ",
1233 +               "res5",
1234 +               "res6",
1235 +               "res7",
1236 +               "CCDC_VD0_IRQ",
1237 +               "CCDC_VD1_IRQ",
1238 +               "CCDC_VD2_IRQ",
1239 +               "CCDC_ERR_IRQ",
1240 +               "H3A_AF_DONE_IRQ",
1241 +               "H3A_AWB_DONE_IRQ",
1242 +               "res14",
1243 +               "res15",
1244 +               "HIST_DONE_IRQ",
1245 +               "CCDC_LSC_DONE",
1246 +               "CCDC_LSC_PREFETCH_COMPLETED",
1247 +               "CCDC_LSC_PREFETCH_ERROR",
1248 +               "PRV_DONE_IRQ",
1249 +               "CBUFF_IRQ",
1250 +               "res22",
1251 +               "res23",
1252 +               "RSZ_DONE_IRQ",
1253 +               "OVF_IRQ",
1254 +               "res26",
1255 +               "res27",
1256 +               "MMU_ERR_IRQ",
1257 +               "OCP_ERR_IRQ",
1258 +               "SEC_ERR_IRQ",
1259 +               "HS_VS_IRQ",
1260 +       };
1261 +       int i;
1263 +       dev_dbg(isp->dev, "");
1265 +       for (i = 0; i < ARRAY_SIZE(name); i++) {
1266 +               if ((1 << i) & irqstatus)
1267 +                       printk(KERN_CONT "%s ", name[i]);
1268 +       }
1269 +       printk(KERN_CONT "\n");
1270 +}
1272 +static void isp_isr_sbl(struct isp_device *isp)
1273 +{
1274 +       struct device *dev = isp->dev;
1275 +       u32 sbl_pcr;
1277 +       /*
1278 +        * Handle shared buffer logic overflows for video buffers.
1279 +        * ISPSBL_PCR_CCDCPRV_2_RSZ_OVF can be safely ignored.
1280 +        */
1281 +       sbl_pcr = isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_PCR);
1282 +       isp_reg_writel(isp, sbl_pcr, OMAP3_ISP_IOMEM_SBL, ISPSBL_PCR);
1283 +       sbl_pcr &= ~ISPSBL_PCR_CCDCPRV_2_RSZ_OVF;
1285 +       if (sbl_pcr)
1286 +               dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr);
1288 +       if (sbl_pcr & (ISPSBL_PCR_CCDC_WBL_OVF | ISPSBL_PCR_CSIA_WBL_OVF
1289 +                    | ISPSBL_PCR_CSIB_WBL_OVF)) {
1290 +               isp->isp_ccdc.error = 1;
1291 +               if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
1292 +                       isp->isp_prev.error = 1;
1293 +               if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)
1294 +                       isp->isp_res.error = 1;
1295 +       }
1297 +       if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) {
1298 +               isp->isp_prev.error = 1;
1299 +               if (isp->isp_res.input == RESIZER_INPUT_VP &&
1300 +                   !(isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER))
1301 +                       isp->isp_res.error = 1;
1302 +       }
1304 +       if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF
1305 +                      | ISPSBL_PCR_RSZ2_WBL_OVF
1306 +                      | ISPSBL_PCR_RSZ3_WBL_OVF
1307 +                      | ISPSBL_PCR_RSZ4_WBL_OVF))
1308 +               isp->isp_res.error = 1;
1310 +       if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF)
1311 +               omap3isp_stat_sbl_overflow(&isp->isp_af);
1313 +       if (sbl_pcr & ISPSBL_PCR_H3A_AEAWB_WBL_OVF)
1314 +               omap3isp_stat_sbl_overflow(&isp->isp_aewb);
1315 +}
1317 +/*
1318 + * isp_isr - Interrupt Service Routine for Camera ISP module.
1319 + * @irq: Not used currently.
1320 + * @_isp: Pointer to the OMAP3 ISP device
1321 + *
1322 + * Handles the corresponding callback if plugged in.
1323 + *
1324 + * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
1325 + * IRQ wasn't handled.
1326 + */
1327 +static irqreturn_t isp_isr(int irq, void *_isp)
1328 +{
1329 +       static const u32 ccdc_events = IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ |
1330 +                                      IRQ0STATUS_CCDC_LSC_DONE_IRQ |
1331 +                                      IRQ0STATUS_CCDC_VD0_IRQ |
1332 +                                      IRQ0STATUS_CCDC_VD1_IRQ |
1333 +                                      IRQ0STATUS_HS_VS_IRQ;
1334 +       struct isp_device *isp = _isp;
1335 +       u32 irqstatus;
1336 +       int ret;
1338 +       irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
1339 +       isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
1341 +       isp_isr_sbl(isp);
1343 +       if (irqstatus & IRQ0STATUS_CSIA_IRQ) {
1344 +               ret = omap3isp_csi2_isr(&isp->isp_csi2a);
1345 +               if (ret)
1346 +                       isp->isp_ccdc.error = 1;
1347 +       }
1349 +       if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
1350 +               ret = omap3isp_ccp2_isr(&isp->isp_ccp2);
1351 +               if (ret)
1352 +                       isp->isp_ccdc.error = 1;
1353 +       }
1355 +       if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) {
1356 +               if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
1357 +                       omap3isp_preview_isr_frame_sync(&isp->isp_prev);
1358 +               if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)
1359 +                       omap3isp_resizer_isr_frame_sync(&isp->isp_res);
1360 +               omap3isp_stat_isr_frame_sync(&isp->isp_aewb);
1361 +               omap3isp_stat_isr_frame_sync(&isp->isp_af);
1362 +               omap3isp_stat_isr_frame_sync(&isp->isp_hist);
1363 +       }
1365 +       if (irqstatus & ccdc_events)
1366 +               omap3isp_ccdc_isr(&isp->isp_ccdc, irqstatus & ccdc_events);
1368 +       if (irqstatus & IRQ0STATUS_PRV_DONE_IRQ) {
1369 +               if (isp->isp_prev.output & PREVIEW_OUTPUT_RESIZER)
1370 +                       omap3isp_resizer_isr_frame_sync(&isp->isp_res);
1371 +               omap3isp_preview_isr(&isp->isp_prev);
1372 +       }
1374 +       if (irqstatus & IRQ0STATUS_RSZ_DONE_IRQ)
1375 +               omap3isp_resizer_isr(&isp->isp_res);
1377 +       if (irqstatus & IRQ0STATUS_H3A_AWB_DONE_IRQ)
1378 +               omap3isp_stat_isr(&isp->isp_aewb);
1380 +       if (irqstatus & IRQ0STATUS_H3A_AF_DONE_IRQ)
1381 +               omap3isp_stat_isr(&isp->isp_af);
1383 +       if (irqstatus & IRQ0STATUS_HIST_DONE_IRQ)
1384 +               omap3isp_stat_isr(&isp->isp_hist);
1386 +       omap3isp_flush(isp);
1388 +#if defined(DEBUG) && defined(ISP_ISR_DEBUG)
1389 +       isp_isr_dbg(isp, irqstatus);
1390 +#endif
1392 +       return IRQ_HANDLED;
1393 +}
1395 +/* -----------------------------------------------------------------------------
1396 + * Pipeline power management
1397 + *
1398 + * Entities must be powered up when part of a pipeline that contains at least
1399 + * one open video device node.
1400 + *
1401 + * To achieve this use the entity use_count field to track the number of users.
1402 + * For entities corresponding to video device nodes the use_count field stores
1403 + * the users count of the node. For entities corresponding to subdevs the
1404 + * use_count field stores the total number of users of all video device nodes
1405 + * in the pipeline.
1406 + *
1407 + * The omap3isp_pipeline_pm_use() function must be called in the open() and
1408 + * close() handlers of video device nodes. It increments or decrements the use
1409 + * count of all subdev entities in the pipeline.
1410 + *
1411 + * To react to link management on powered pipelines, the link setup notification
1412 + * callback updates the use count of all entities in the source and sink sides
1413 + * of the link.
1414 + */
1416 +/*
1417 + * isp_pipeline_pm_use_count - Count the number of users of a pipeline
1418 + * @entity: The entity
1419 + *
1420 + * Return the total number of users of all video device nodes in the pipeline.
1421 + */
1422 +static int isp_pipeline_pm_use_count(struct media_entity *entity)
1423 +{
1424 +       struct media_entity_graph graph;
1425 +       int use = 0;
1427 +       media_entity_graph_walk_start(&graph, entity);
1429 +       while ((entity = media_entity_graph_walk_next(&graph))) {
1430 +               if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
1431 +                       use += entity->use_count;
1432 +       }
1434 +       return use;
1435 +}
1437 +/*
1438 + * isp_pipeline_pm_power_one - Apply power change to an entity
1439 + * @entity: The entity
1440 + * @change: Use count change
1441 + *
1442 + * Change the entity use count by @change. If the entity is a subdev update its
1443 + * power state by calling the core::s_power operation when the use count goes
1444 + * from 0 to != 0 or from != 0 to 0.
1445 + *
1446 + * Return 0 on success or a negative error code on failure.
1447 + */
1448 +static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
1449 +{
1450 +       struct v4l2_subdev *subdev;
1451 +       int ret;
1453 +       subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
1454 +              ? media_entity_to_v4l2_subdev(entity) : NULL;
1456 +       if (entity->use_count == 0 && change > 0 && subdev != NULL) {
1457 +               ret = v4l2_subdev_call(subdev, core, s_power, 1);
1458 +               if (ret < 0 && ret != -ENOIOCTLCMD)
1459 +                       return ret;
1460 +       }
1462 +       entity->use_count += change;
1463 +       WARN_ON(entity->use_count < 0);
1465 +       if (entity->use_count == 0 && change < 0 && subdev != NULL)
1466 +               v4l2_subdev_call(subdev, core, s_power, 0);
1468 +       return 0;
1469 +}
1471 +/*
1472 + * isp_pipeline_pm_power - Apply power change to all entities in a pipeline
1473 + * @entity: The entity
1474 + * @change: Use count change
1475 + *
1476 + * Walk the pipeline to update the use count and the power state of all non-node
1477 + * entities.
1478 + *
1479 + * Return 0 on success or a negative error code on failure.
1480 + */
1481 +static int isp_pipeline_pm_power(struct media_entity *entity, int change)
1482 +{
1483 +       struct media_entity_graph graph;
1484 +       struct media_entity *first = entity;
1485 +       int ret = 0;
1487 +       if (!change)
1488 +               return 0;
1490 +       media_entity_graph_walk_start(&graph, entity);
1492 +       while (!ret && (entity = media_entity_graph_walk_next(&graph)))
1493 +               if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
1494 +                       ret = isp_pipeline_pm_power_one(entity, change);
1496 +       if (!ret)
1497 +               return 0;
1499 +       media_entity_graph_walk_start(&graph, first);
1501 +       while ((first = media_entity_graph_walk_next(&graph))
1502 +              && first != entity)
1503 +               if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
1504 +                       isp_pipeline_pm_power_one(first, -change);
1506 +       return ret;
1507 +}
1509 +/*
1510 + * omap3isp_pipeline_pm_use - Update the use count of an entity
1511 + * @entity: The entity
1512 + * @use: Use (1) or stop using (0) the entity
1513 + *
1514 + * Update the use count of all entities in the pipeline and power entities on or
1515 + * off accordingly.
1516 + *
1517 + * Return 0 on success or a negative error code on failure. Powering entities
1518 + * off is assumed to never fail. No failure can occur when the use parameter is
1519 + * set to 0.
1520 + */
1521 +int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
1522 +{
1523 +       int change = use ? 1 : -1;
1524 +       int ret;
1526 +       mutex_lock(&entity->parent->graph_mutex);
1528 +       /* Apply use count to node. */
1529 +       entity->use_count += change;
1530 +       WARN_ON(entity->use_count < 0);
1532 +       /* Apply power change to connected non-nodes. */
1533 +       ret = isp_pipeline_pm_power(entity, change);
1535 +       mutex_unlock(&entity->parent->graph_mutex);
1537 +       return ret;
1538 +}
1540 +/*
1541 + * isp_pipeline_link_notify - Link management notification callback
1542 + * @source: Pad at the start of the link
1543 + * @sink: Pad at the end of the link
1544 + * @flags: New link flags that will be applied
1545 + *
1546 + * React to link management on powered pipelines by updating the use count of
1547 + * all entities in the source and sink sides of the link. Entities are powered
1548 + * on or off accordingly.
1549 + *
1550 + * Return 0 on success or a negative error code on failure. Powering entities
1551 + * off is assumed to never fail. This function will not fail for disconnection
1552 + * events.
1553 + */
1554 +static int isp_pipeline_link_notify(struct media_pad *source,
1555 +                                   struct media_pad *sink, u32 flags)
1556 +{
1557 +       int source_use = isp_pipeline_pm_use_count(source->entity);
1558 +       int sink_use = isp_pipeline_pm_use_count(sink->entity);
1559 +       int ret;
1561 +       if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1562 +               /* Powering off entities is assumed to never fail. */
1563 +               isp_pipeline_pm_power(source->entity, -sink_use);
1564 +               isp_pipeline_pm_power(sink->entity, -source_use);
1565 +               return 0;
1566 +       }
1568 +       ret = isp_pipeline_pm_power(source->entity, sink_use);
1569 +       if (ret < 0)
1570 +               return ret;
1572 +       ret = isp_pipeline_pm_power(sink->entity, source_use);
1573 +       if (ret < 0)
1574 +               isp_pipeline_pm_power(source->entity, -sink_use);
1576 +       return ret;
1577 +}
1579 +/* -----------------------------------------------------------------------------
1580 + * Pipeline stream management
1581 + */
1583 +/*
1584 + * isp_pipeline_enable - Enable streaming on a pipeline
1585 + * @pipe: ISP pipeline
1586 + * @mode: Stream mode (single shot or continuous)
1587 + *
1588 + * Walk the entities chain starting at the pipeline output video node and start
1589 + * all modules in the chain in the given mode.
1590 + *
1591 + * Return 0 if successfull, or the return value of the failed video::s_stream
1592 + * operation otherwise.
1593 + */
1594 +static int isp_pipeline_enable(struct isp_pipeline *pipe,
1595 +                              enum isp_pipeline_stream_state mode)
1596 +{
1597 +       struct isp_device *isp = pipe->output->isp;
1598 +       struct media_entity *entity;
1599 +       struct media_pad *pad;
1600 +       struct v4l2_subdev *subdev;
1601 +       unsigned long flags;
1602 +       int ret = 0;
1604 +       spin_lock_irqsave(&pipe->lock, flags);
1605 +       pipe->state &= ~(ISP_PIPELINE_IDLE_INPUT | ISP_PIPELINE_IDLE_OUTPUT);
1606 +       spin_unlock_irqrestore(&pipe->lock, flags);
1608 +       pipe->do_propagation = false;
1610 +       entity = &pipe->output->video.entity;
1611 +       while (1) {
1612 +               pad = &entity->pads[0];
1613 +               if (!(pad->flags & MEDIA_PAD_FL_INPUT))
1614 +                       break;
1616 +               pad = media_entity_remote_source(pad);
1617 +               if (pad == NULL ||
1618 +                   media_entity_type(pad->entity) !=
1619 +                               MEDIA_ENT_T_V4L2_SUBDEV)
1620 +                       break;
1622 +               entity = pad->entity;
1623 +               subdev = media_entity_to_v4l2_subdev(entity);
1625 +               ret = v4l2_subdev_call(subdev, video, s_stream, mode);
1626 +               if (ret < 0 && ret != -ENOIOCTLCMD)
1627 +                       break;
1629 +               if (subdev == &isp->isp_ccdc.subdev) {
1630 +                       v4l2_subdev_call(&isp->isp_aewb.subdev, video,
1631 +                                       s_stream, mode);
1632 +                       v4l2_subdev_call(&isp->isp_af.subdev, video,
1633 +                                       s_stream, mode);
1634 +                       v4l2_subdev_call(&isp->isp_hist.subdev, video,
1635 +                                       s_stream, mode);
1636 +                       pipe->do_propagation = true;
1637 +               }
1638 +       }
1640 +       /* Frame number propagation. In continuous streaming mode the number
1641 +        * is incremented in the frame start ISR. In mem-to-mem mode
1642 +        * singleshot is used and frame start IRQs are not available.
1643 +        * Thus we have to increment the number here.
1644 +        */
1645 +       if (pipe->do_propagation && mode == ISP_PIPELINE_STREAM_SINGLESHOT)
1646 +               atomic_inc(&pipe->frame_number);
1648 +       return ret;
1649 +}
1651 +static int isp_pipeline_wait_resizer(struct isp_device *isp)
1652 +{
1653 +       return omap3isp_resizer_busy(&isp->isp_res);
1654 +}
1656 +static int isp_pipeline_wait_preview(struct isp_device *isp)
1657 +{
1658 +       return omap3isp_preview_busy(&isp->isp_prev);
1659 +}
1661 +static int isp_pipeline_wait_ccdc(struct isp_device *isp)
1662 +{
1663 +       return omap3isp_stat_busy(&isp->isp_af)
1664 +           || omap3isp_stat_busy(&isp->isp_aewb)
1665 +           || omap3isp_stat_busy(&isp->isp_hist)
1666 +           || omap3isp_ccdc_busy(&isp->isp_ccdc);
1667 +}
1669 +#define ISP_STOP_TIMEOUT       msecs_to_jiffies(1000)
1671 +static int isp_pipeline_wait(struct isp_device *isp,
1672 +                            int(*busy)(struct isp_device *isp))
1673 +{
1674 +       unsigned long timeout = jiffies + ISP_STOP_TIMEOUT;
1676 +       while (!time_after(jiffies, timeout)) {
1677 +               if (!busy(isp))
1678 +                       return 0;
1679 +       }
1681 +       return 1;
1682 +}
1684 +/*
1685 + * isp_pipeline_disable - Disable streaming on a pipeline
1686 + * @pipe: ISP pipeline
1687 + *
1688 + * Walk the entities chain starting at the pipeline output video node and stop
1689 + * all modules in the chain. Wait synchronously for the modules to be stopped if
1690 + * necessary.
1691 + *
1692 + * Return 0 if all modules have been properly stopped, or -ETIMEDOUT if a module
1693 + * can't be stopped (in which case a software reset of the ISP is probably
1694 + * necessary).
1695 + */
1696 +static int isp_pipeline_disable(struct isp_pipeline *pipe)
1697 +{
1698 +       struct isp_device *isp = pipe->output->isp;
1699 +       struct media_entity *entity;
1700 +       struct media_pad *pad;
1701 +       struct v4l2_subdev *subdev;
1702 +       int failure = 0;
1703 +       int ret;
1705 +       /*
1706 +        * We need to stop all the modules after CCDC first or they'll
1707 +        * never stop since they may not get a full frame from CCDC.
1708 +        */
1709 +       entity = &pipe->output->video.entity;
1710 +       while (1) {
1711 +               pad = &entity->pads[0];
1712 +               if (!(pad->flags & MEDIA_PAD_FL_INPUT))
1713 +                       break;
1715 +               pad = media_entity_remote_source(pad);
1716 +               if (pad == NULL ||
1717 +                   media_entity_type(pad->entity) !=
1718 +                               MEDIA_ENT_T_V4L2_SUBDEV)
1719 +                       break;
1721 +               entity = pad->entity;
1722 +               subdev = media_entity_to_v4l2_subdev(entity);
1724 +               if (subdev == &isp->isp_ccdc.subdev) {
1725 +                       v4l2_subdev_call(&isp->isp_aewb.subdev,
1726 +                                        video, s_stream, 0);
1727 +                       v4l2_subdev_call(&isp->isp_af.subdev,
1728 +                                        video, s_stream, 0);
1729 +                       v4l2_subdev_call(&isp->isp_hist.subdev,
1730 +                                        video, s_stream, 0);
1731 +               }
1733 +               v4l2_subdev_call(subdev, video, s_stream, 0);
1735 +               if (subdev == &isp->isp_res.subdev) {
1736 +                       ret = isp_pipeline_wait(isp, isp_pipeline_wait_resizer);
1737 +               } else if (subdev == &isp->isp_prev.subdev) {
1738 +                       ret = isp_pipeline_wait(isp, isp_pipeline_wait_preview);
1739 +               } else if (subdev == &isp->isp_ccdc.subdev) {
1740 +                       ret = isp_pipeline_wait(isp, isp_pipeline_wait_ccdc);
1741 +               } else {
1742 +                       ret = 0;
1743 +               }
1745 +               if (ret) {
1746 +                       dev_info(isp->dev, "Unable to stop %s\n", subdev->name);
1747 +                       failure = -ETIMEDOUT;
1748 +               }
1749 +       }
1751 +       return failure;
1752 +}
1754 +/*
1755 + * omap3isp_pipeline_set_stream - Enable/disable streaming on a pipeline
1756 + * @pipe: ISP pipeline
1757 + * @state: Stream state (stopped, single shot or continuous)
1758 + *
1759 + * Set the pipeline to the given stream state. Pipelines can be started in
1760 + * single-shot or continuous mode.
1761 + *
1762 + * Return 0 if successfull, or the return value of the failed video::s_stream
1763 + * operation otherwise.
1764 + */
1765 +int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
1766 +                                enum isp_pipeline_stream_state state)
1767 +{
1768 +       int ret;
1770 +       if (state == ISP_PIPELINE_STREAM_STOPPED)
1771 +               ret = isp_pipeline_disable(pipe);
1772 +       else
1773 +               ret = isp_pipeline_enable(pipe, state);
1774 +       pipe->stream_state = state;
1776 +       return ret;
1777 +}
1779 +/*
1780 + * isp_pipeline_resume - Resume streaming on a pipeline
1781 + * @pipe: ISP pipeline
1782 + *
1783 + * Resume video output and input and re-enable pipeline.
1784 + */
1785 +static void isp_pipeline_resume(struct isp_pipeline *pipe)
1786 +{
1787 +       int singleshot = pipe->stream_state == ISP_PIPELINE_STREAM_SINGLESHOT;
1789 +       omap3isp_video_resume(pipe->output, !singleshot);
1790 +       if (singleshot)
1791 +               omap3isp_video_resume(pipe->input, 0);
1792 +       isp_pipeline_enable(pipe, pipe->stream_state);
1793 +}
1795 +/*
1796 + * isp_pipeline_suspend - Suspend streaming on a pipeline
1797 + * @pipe: ISP pipeline
1798 + *
1799 + * Suspend pipeline.
1800 + */
1801 +static void isp_pipeline_suspend(struct isp_pipeline *pipe)
1802 +{
1803 +       isp_pipeline_disable(pipe);
1804 +}
1806 +/*
1807 + * isp_pipeline_is_last - Verify if entity has an enbled link to the output
1808 + *                       video node
1809 + * @me: ISP module's media entity
1810 + *
1811 + * Returns 1 if the entity has an enabled link to the output video node or 0
1812 + * otherwise. It's true only while pipeline can have no more than one output
1813 + * node.
1814 + */
1815 +static int isp_pipeline_is_last(struct media_entity *me)
1816 +{
1817 +       struct isp_pipeline *pipe;
1818 +       struct media_pad *pad;
1820 +       if (!me->pipe)
1821 +               return 0;
1822 +       pipe = to_isp_pipeline(me);
1823 +       if (pipe->stream_state == ISP_PIPELINE_STREAM_STOPPED)
1824 +               return 0;
1825 +       pad = media_entity_remote_source(&pipe->output->pad);
1826 +       return pad->entity == me;
1827 +}
1829 +/*
1830 + * isp_suspend_module_pipeline - Suspend pipeline to which belongs the module
1831 + * @me: ISP module's media entity
1832 + *
1833 + * Suspend the whole pipeline if module's entity has an enabled link to the
1834 + * output video node. It works only while pipeline can have no more than one
1835 + * output node.
1836 + */
1837 +static void isp_suspend_module_pipeline(struct media_entity *me)
1838 +{
1839 +       if (isp_pipeline_is_last(me))
1840 +               isp_pipeline_suspend(to_isp_pipeline(me));
1841 +}
1843 +/*
1844 + * isp_resume_module_pipeline - Resume pipeline to which belongs the module
1845 + * @me: ISP module's media entity
1846 + *
1847 + * Resume the whole pipeline if module's entity has an enabled link to the
1848 + * output video node. It works only while pipeline can have no more than one
1849 + * output node.
1850 + */
1851 +static void isp_resume_module_pipeline(struct media_entity *me)
1852 +{
1853 +       if (isp_pipeline_is_last(me))
1854 +               isp_pipeline_resume(to_isp_pipeline(me));
1855 +}
1857 +/*
1858 + * isp_suspend_modules - Suspend ISP submodules.
1859 + * @isp: OMAP3 ISP device
1860 + *
1861 + * Returns 0 if suspend left in idle state all the submodules properly,
1862 + * or returns 1 if a general Reset is required to suspend the submodules.
1863 + */
1864 +static int isp_suspend_modules(struct isp_device *isp)
1865 +{
1866 +       unsigned long timeout;
1868 +       omap3isp_stat_suspend(&isp->isp_aewb);
1869 +       omap3isp_stat_suspend(&isp->isp_af);
1870 +       omap3isp_stat_suspend(&isp->isp_hist);
1871 +       isp_suspend_module_pipeline(&isp->isp_res.subdev.entity);
1872 +       isp_suspend_module_pipeline(&isp->isp_prev.subdev.entity);
1873 +       isp_suspend_module_pipeline(&isp->isp_ccdc.subdev.entity);
1874 +       isp_suspend_module_pipeline(&isp->isp_csi2a.subdev.entity);
1875 +       isp_suspend_module_pipeline(&isp->isp_ccp2.subdev.entity);
1877 +       timeout = jiffies + ISP_STOP_TIMEOUT;
1878 +       while (omap3isp_stat_busy(&isp->isp_af)
1879 +           || omap3isp_stat_busy(&isp->isp_aewb)
1880 +           || omap3isp_stat_busy(&isp->isp_hist)
1881 +           || omap3isp_preview_busy(&isp->isp_prev)
1882 +           || omap3isp_resizer_busy(&isp->isp_res)
1883 +           || omap3isp_ccdc_busy(&isp->isp_ccdc)) {
1884 +               if (time_after(jiffies, timeout)) {
1885 +                       dev_info(isp->dev, "can't stop modules.\n");
1886 +                       return 1;
1887 +               }
1888 +               msleep(1);
1889 +       }
1891 +       return 0;
1892 +}
1894 +/*
1895 + * isp_resume_modules - Resume ISP submodules.
1896 + * @isp: OMAP3 ISP device
1897 + */
1898 +static void isp_resume_modules(struct isp_device *isp)
1899 +{
1900 +       omap3isp_stat_resume(&isp->isp_aewb);
1901 +       omap3isp_stat_resume(&isp->isp_af);
1902 +       omap3isp_stat_resume(&isp->isp_hist);
1903 +       isp_resume_module_pipeline(&isp->isp_res.subdev.entity);
1904 +       isp_resume_module_pipeline(&isp->isp_prev.subdev.entity);
1905 +       isp_resume_module_pipeline(&isp->isp_ccdc.subdev.entity);
1906 +       isp_resume_module_pipeline(&isp->isp_csi2a.subdev.entity);
1907 +       isp_resume_module_pipeline(&isp->isp_ccp2.subdev.entity);
1908 +}
1910 +/*
1911 + * isp_reset - Reset ISP with a timeout wait for idle.
1912 + * @isp: OMAP3 ISP device
1913 + */
1914 +static int isp_reset(struct isp_device *isp)
1915 +{
1916 +       unsigned long timeout = 0;
1918 +       isp_reg_writel(isp,
1919 +                      isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG)
1920 +                      | ISP_SYSCONFIG_SOFTRESET,
1921 +                      OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
1922 +       while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN,
1923 +                              ISP_SYSSTATUS) & 0x1)) {
1924 +               if (timeout++ > 10000) {
1925 +                       dev_alert(isp->dev, "cannot reset ISP\n");
1926 +                       return -ETIMEDOUT;
1927 +               }
1928 +               udelay(1);
1929 +       }
1931 +       return 0;
1932 +}
1934 +/*
1935 + * isp_save_context - Saves the values of the ISP module registers.
1936 + * @isp: OMAP3 ISP device
1937 + * @reg_list: Structure containing pairs of register address and value to
1938 + *            modify on OMAP.
1939 + */
1940 +static void
1941 +isp_save_context(struct isp_device *isp, struct isp_reg *reg_list)
1942 +{
1943 +       struct isp_reg *next = reg_list;
1945 +       for (; next->reg != ISP_TOK_TERM; next++)
1946 +               next->val = isp_reg_readl(isp, next->mmio_range, next->reg);
1947 +}
1949 +/*
1950 + * isp_restore_context - Restores the values of the ISP module registers.
1951 + * @isp: OMAP3 ISP device
1952 + * @reg_list: Structure containing pairs of register address and value to
1953 + *            modify on OMAP.
1954 + */
1955 +static void
1956 +isp_restore_context(struct isp_device *isp, struct isp_reg *reg_list)
1957 +{
1958 +       struct isp_reg *next = reg_list;
1960 +       for (; next->reg != ISP_TOK_TERM; next++)
1961 +               isp_reg_writel(isp, next->val, next->mmio_range, next->reg);
1962 +}
1964 +/*
1965 + * isp_save_ctx - Saves ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
1966 + * @isp: OMAP3 ISP device
1967 + *
1968 + * Routine for saving the context of each module in the ISP.
1969 + * CCDC, HIST, H3A, PREV, RESZ and MMU.
1970 + */
1971 +static void isp_save_ctx(struct isp_device *isp)
1972 +{
1973 +       isp_save_context(isp, isp_reg_list);
1974 +       if (isp->iommu)
1975 +               iommu_save_ctx(isp->iommu);
1976 +}
1978 +/*
1979 + * isp_restore_ctx - Restores ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
1980 + * @isp: OMAP3 ISP device
1981 + *
1982 + * Routine for restoring the context of each module in the ISP.
1983 + * CCDC, HIST, H3A, PREV, RESZ and MMU.
1984 + */
1985 +static void isp_restore_ctx(struct isp_device *isp)
1986 +{
1987 +       isp_restore_context(isp, isp_reg_list);
1988 +       if (isp->iommu)
1989 +               iommu_restore_ctx(isp->iommu);
1990 +       omap3isp_ccdc_restore_context(isp);
1991 +       omap3isp_preview_restore_context(isp);
1992 +}
1994 +/* -----------------------------------------------------------------------------
1995 + * SBL resources management
1996 + */
1997 +#define OMAP3_ISP_SBL_READ     (OMAP3_ISP_SBL_CSI1_READ | \
1998 +                                OMAP3_ISP_SBL_CCDC_LSC_READ | \
1999 +                                OMAP3_ISP_SBL_PREVIEW_READ | \
2000 +                                OMAP3_ISP_SBL_RESIZER_READ)
2001 +#define OMAP3_ISP_SBL_WRITE    (OMAP3_ISP_SBL_CSI1_WRITE | \
2002 +                                OMAP3_ISP_SBL_CSI2A_WRITE | \
2003 +                                OMAP3_ISP_SBL_CSI2C_WRITE | \
2004 +                                OMAP3_ISP_SBL_CCDC_WRITE | \
2005 +                                OMAP3_ISP_SBL_PREVIEW_WRITE)
2007 +void omap3isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res)
2008 +{
2009 +       u32 sbl = 0;
2011 +       isp->sbl_resources |= res;
2013 +       if (isp->sbl_resources & OMAP3_ISP_SBL_CSI1_READ)
2014 +               sbl |= ISPCTRL_SBL_SHARED_RPORTA;
2016 +       if (isp->sbl_resources & OMAP3_ISP_SBL_CCDC_LSC_READ)
2017 +               sbl |= ISPCTRL_SBL_SHARED_RPORTB;
2019 +       if (isp->sbl_resources & OMAP3_ISP_SBL_CSI2C_WRITE)
2020 +               sbl |= ISPCTRL_SBL_SHARED_WPORTC;
2022 +       if (isp->sbl_resources & OMAP3_ISP_SBL_RESIZER_WRITE)
2023 +               sbl |= ISPCTRL_SBL_WR0_RAM_EN;
2025 +       if (isp->sbl_resources & OMAP3_ISP_SBL_WRITE)
2026 +               sbl |= ISPCTRL_SBL_WR1_RAM_EN;
2028 +       if (isp->sbl_resources & OMAP3_ISP_SBL_READ)
2029 +               sbl |= ISPCTRL_SBL_RD_RAM_EN;
2031 +       isp_reg_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, sbl);
2032 +}
2034 +void omap3isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res)
2035 +{
2036 +       u32 sbl = 0;
2038 +       isp->sbl_resources &= ~res;
2040 +       if (!(isp->sbl_resources & OMAP3_ISP_SBL_CSI1_READ))
2041 +               sbl |= ISPCTRL_SBL_SHARED_RPORTA;
2043 +       if (!(isp->sbl_resources & OMAP3_ISP_SBL_CCDC_LSC_READ))
2044 +               sbl |= ISPCTRL_SBL_SHARED_RPORTB;
2046 +       if (!(isp->sbl_resources & OMAP3_ISP_SBL_CSI2C_WRITE))
2047 +               sbl |= ISPCTRL_SBL_SHARED_WPORTC;
2049 +       if (!(isp->sbl_resources & OMAP3_ISP_SBL_RESIZER_WRITE))
2050 +               sbl |= ISPCTRL_SBL_WR0_RAM_EN;
2052 +       if (!(isp->sbl_resources & OMAP3_ISP_SBL_WRITE))
2053 +               sbl |= ISPCTRL_SBL_WR1_RAM_EN;
2055 +       if (!(isp->sbl_resources & OMAP3_ISP_SBL_READ))
2056 +               sbl |= ISPCTRL_SBL_RD_RAM_EN;
2058 +       isp_reg_clr(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, sbl);
2059 +}
2061 +/*
2062 + * isp_module_sync_idle - Helper to sync module with its idle state
2063 + * @me: ISP submodule's media entity
2064 + * @wait: ISP submodule's wait queue for streamoff/interrupt synchronization
2065 + * @stopping: flag which tells module wants to stop
2066 + *
2067 + * This function checks if ISP submodule needs to wait for next interrupt. If
2068 + * yes, makes the caller to sleep while waiting for such event.
2069 + */
2070 +int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
2071 +                             atomic_t *stopping)
2072 +{
2073 +       struct isp_pipeline *pipe = to_isp_pipeline(me);
2075 +       if (pipe->stream_state == ISP_PIPELINE_STREAM_STOPPED ||
2076 +           (pipe->stream_state == ISP_PIPELINE_STREAM_SINGLESHOT &&
2077 +            !isp_pipeline_ready(pipe)))
2078 +               return 0;
2080 +       /*
2081 +        * atomic_set() doesn't include memory barrier on ARM platform for SMP
2082 +        * scenario. We'll call it here to avoid race conditions.
2083 +        */
2084 +       atomic_set(stopping, 1);
2085 +       smp_mb();
2087 +       /*
2088 +        * If module is the last one, it's writing to memory. In this case,
2089 +        * it's necessary to check if the module is already paused due to
2090 +        * DMA queue underrun or if it has to wait for next interrupt to be
2091 +        * idle.
2092 +        * If it isn't the last one, the function won't sleep but *stopping
2093 +        * will still be set to warn next submodule caller's interrupt the
2094 +        * module wants to be idle.
2095 +        */
2096 +       if (isp_pipeline_is_last(me)) {
2097 +               struct isp_video *video = pipe->output;
2098 +               unsigned long flags;
2099 +               spin_lock_irqsave(&video->queue->irqlock, flags);
2100 +               if (video->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
2101 +                       spin_unlock_irqrestore(&video->queue->irqlock, flags);
2102 +                       atomic_set(stopping, 0);
2103 +                       smp_mb();
2104 +                       return 0;
2105 +               }
2106 +               spin_unlock_irqrestore(&video->queue->irqlock, flags);
2107 +               if (!wait_event_timeout(*wait, !atomic_read(stopping),
2108 +                                       msecs_to_jiffies(1000))) {
2109 +                       atomic_set(stopping, 0);
2110 +                       smp_mb();
2111 +                       return -ETIMEDOUT;
2112 +               }
2113 +       }
2115 +       return 0;
2116 +}
2118 +/*
2119 + * omap3isp_module_sync_is_stopped - Helper to verify if module was stopping
2120 + * @wait: ISP submodule's wait queue for streamoff/interrupt synchronization
2121 + * @stopping: flag which tells module wants to stop
2122 + *
2123 + * This function checks if ISP submodule was stopping. In case of yes, it
2124 + * notices the caller by setting stopping to 0 and waking up the wait queue.
2125 + * Returns 1 if it was stopping or 0 otherwise.
2126 + */
2127 +int omap3isp_module_sync_is_stopping(wait_queue_head_t *wait,
2128 +                                    atomic_t *stopping)
2129 +{
2130 +       if (atomic_cmpxchg(stopping, 1, 0)) {
2131 +               wake_up(wait);
2132 +               return 1;
2133 +       }
2135 +       return 0;
2136 +}
2138 +/* --------------------------------------------------------------------------
2139 + * Clock management
2140 + */
2142 +#define ISPCTRL_CLKS_MASK      (ISPCTRL_H3A_CLK_EN | \
2143 +                                ISPCTRL_HIST_CLK_EN | \
2144 +                                ISPCTRL_RSZ_CLK_EN | \
2145 +                                (ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN) | \
2146 +                                (ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN))
2148 +static void __isp_subclk_update(struct isp_device *isp)
2149 +{
2150 +       u32 clk = 0;
2152 +       if (isp->subclk_resources & OMAP3_ISP_SUBCLK_H3A)
2153 +               clk |= ISPCTRL_H3A_CLK_EN;
2155 +       if (isp->subclk_resources & OMAP3_ISP_SUBCLK_HIST)
2156 +               clk |= ISPCTRL_HIST_CLK_EN;
2158 +       if (isp->subclk_resources & OMAP3_ISP_SUBCLK_RESIZER)
2159 +               clk |= ISPCTRL_RSZ_CLK_EN;
2161 +       /* NOTE: For CCDC & Preview submodules, we need to affect internal
2162 +        *       RAM aswell.
2163 +        */
2164 +       if (isp->subclk_resources & OMAP3_ISP_SUBCLK_CCDC)
2165 +               clk |= ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN;
2167 +       if (isp->subclk_resources & OMAP3_ISP_SUBCLK_PREVIEW)
2168 +               clk |= ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN;
2170 +       isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
2171 +                       ISPCTRL_CLKS_MASK, clk);
2172 +}
2174 +void omap3isp_subclk_enable(struct isp_device *isp,
2175 +                           enum isp_subclk_resource res)
2176 +{
2177 +       isp->subclk_resources |= res;
2179 +       __isp_subclk_update(isp);
2180 +}
2182 +void omap3isp_subclk_disable(struct isp_device *isp,
2183 +                            enum isp_subclk_resource res)
2184 +{
2185 +       isp->subclk_resources &= ~res;
2187 +       __isp_subclk_update(isp);
2188 +}
2190 +/*
2191 + * isp_enable_clocks - Enable ISP clocks
2192 + * @isp: OMAP3 ISP device
2193 + *
2194 + * Return 0 if successful, or clk_enable return value if any of tthem fails.
2195 + */
2196 +static int isp_enable_clocks(struct isp_device *isp)
2197 +{
2198 +       int r;
2199 +       unsigned long rate;
2200 +       int divisor;
2202 +       /*
2203 +        * cam_mclk clock chain:
2204 +        *   dpll4 -> dpll4_m5 -> dpll4_m5x2 -> cam_mclk
2205 +        *
2206 +        * In OMAP3630 dpll4_m5x2 != 2 x dpll4_m5 but both are
2207 +        * set to the same value. Hence the rate set for dpll4_m5
2208 +        * has to be twice of what is set on OMAP3430 to get
2209 +        * the required value for cam_mclk
2210 +        */
2211 +       if (cpu_is_omap3630())
2212 +               divisor = 1;
2213 +       else
2214 +               divisor = 2;
2216 +       r = clk_enable(isp->clock[ISP_CLK_CAM_ICK]);
2217 +       if (r) {
2218 +               dev_err(isp->dev, "clk_enable cam_ick failed\n");
2219 +               goto out_clk_enable_ick;
2220 +       }
2221 +       r = clk_set_rate(isp->clock[ISP_CLK_DPLL4_M5_CK],
2222 +                        CM_CAM_MCLK_HZ/divisor);
2223 +       if (r) {
2224 +               dev_err(isp->dev, "clk_set_rate for dpll4_m5_ck failed\n");
2225 +               goto out_clk_enable_mclk;
2226 +       }
2227 +       r = clk_enable(isp->clock[ISP_CLK_CAM_MCLK]);
2228 +       if (r) {
2229 +               dev_err(isp->dev, "clk_enable cam_mclk failed\n");
2230 +               goto out_clk_enable_mclk;
2231 +       }
2232 +       rate = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
2233 +       if (rate != CM_CAM_MCLK_HZ)
2234 +               dev_warn(isp->dev, "unexpected cam_mclk rate:\n"
2235 +                                  " expected : %d\n"
2236 +                                  " actual   : %ld\n", CM_CAM_MCLK_HZ, rate);
2237 +       r = clk_enable(isp->clock[ISP_CLK_CSI2_FCK]);
2238 +       if (r) {
2239 +               dev_err(isp->dev, "clk_enable csi2_fck failed\n");
2240 +               goto out_clk_enable_csi2_fclk;
2241 +       }
2242 +       return 0;
2244 +out_clk_enable_csi2_fclk:
2245 +       clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
2246 +out_clk_enable_mclk:
2247 +       clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
2248 +out_clk_enable_ick:
2249 +       return r;
2250 +}
2252 +/*
2253 + * isp_disable_clocks - Disable ISP clocks
2254 + * @isp: OMAP3 ISP device
2255 + */
2256 +static void isp_disable_clocks(struct isp_device *isp)
2257 +{
2258 +       clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
2259 +       clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
2260 +       clk_disable(isp->clock[ISP_CLK_CSI2_FCK]);
2261 +}
2263 +static const char *isp_clocks[] = {
2264 +       "cam_ick",
2265 +       "cam_mclk",
2266 +       "dpll4_m5_ck",
2267 +       "csi2_96m_fck",
2268 +       "l3_ick",
2269 +};
2271 +static void isp_put_clocks(struct isp_device *isp)
2272 +{
2273 +       unsigned int i;
2275 +       for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
2276 +               if (isp->clock[i]) {
2277 +                       clk_put(isp->clock[i]);
2278 +                       isp->clock[i] = NULL;
2279 +               }
2280 +       }
2281 +}
2283 +static int isp_get_clocks(struct isp_device *isp)
2284 +{
2285 +       struct clk *clk;
2286 +       unsigned int i;
2288 +       for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
2289 +               clk = clk_get(isp->dev, isp_clocks[i]);
2290 +               if (IS_ERR(clk)) {
2291 +                       dev_err(isp->dev, "clk_get %s failed\n", isp_clocks[i]);
2292 +                       isp_put_clocks(isp);
2293 +                       return PTR_ERR(clk);
2294 +               }
2296 +               isp->clock[i] = clk;
2297 +       }
2299 +       return 0;
2300 +}
2302 +/*
2303 + * omap3isp_get - Acquire the ISP resource.
2304 + *
2305 + * Initializes the clocks for the first acquire.
2306 + *
2307 + * Increment the reference count on the ISP. If the first reference is taken,
2308 + * enable clocks and power-up all submodules.
2309 + *
2310 + * Return a pointer to the ISP device structure, or NULL if an error occured.
2311 + */
2312 +struct isp_device *omap3isp_get(struct isp_device *isp)
2313 +{
2314 +       struct isp_device *__isp = isp;
2316 +       if (isp == NULL)
2317 +               return NULL;
2319 +       mutex_lock(&isp->isp_mutex);
2320 +       if (isp->ref_count > 0)
2321 +               goto out;
2323 +       if (isp_enable_clocks(isp) < 0) {
2324 +               __isp = NULL;
2325 +               goto out;
2326 +       }
2328 +       /* We don't want to restore context before saving it! */
2329 +       if (isp->has_context)
2330 +               isp_restore_ctx(isp);
2331 +       else
2332 +               isp->has_context = 1;
2334 +       isp_enable_interrupts(isp);
2336 +out:
2337 +       if (__isp != NULL)
2338 +               isp->ref_count++;
2339 +       mutex_unlock(&isp->isp_mutex);
2341 +       return __isp;
2342 +}
2344 +/*
2345 + * omap3isp_put - Release the ISP
2346 + *
2347 + * Decrement the reference count on the ISP. If the last reference is released,
2348 + * power-down all submodules, disable clocks and free temporary buffers.
2349 + */
2350 +void omap3isp_put(struct isp_device *isp)
2351 +{
2352 +       if (isp == NULL)
2353 +               return;
2355 +       mutex_lock(&isp->isp_mutex);
2356 +       BUG_ON(isp->ref_count == 0);
2357 +       if (--isp->ref_count == 0) {
2358 +               isp_disable_interrupts(isp);
2359 +               isp_save_ctx(isp);
2360 +               isp_disable_clocks(isp);
2361 +       }
2362 +       mutex_unlock(&isp->isp_mutex);
2363 +}
2365 +/* --------------------------------------------------------------------------
2366 + * Platform device driver
2367 + */
2369 +/*
2370 + * omap3isp_print_status - Prints the values of the ISP Control Module registers
2371 + * @isp: OMAP3 ISP device
2372 + */
2373 +#define ISP_PRINT_REGISTER(isp, name)\
2374 +       dev_dbg(isp->dev, "###ISP " #name "=0x%08x\n", \
2375 +               isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_##name))
2376 +#define SBL_PRINT_REGISTER(isp, name)\
2377 +       dev_dbg(isp->dev, "###SBL " #name "=0x%08x\n", \
2378 +               isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_##name))
2380 +void omap3isp_print_status(struct isp_device *isp)
2381 +{
2382 +       dev_dbg(isp->dev, "-------------ISP Register dump--------------\n");
2384 +       ISP_PRINT_REGISTER(isp, SYSCONFIG);
2385 +       ISP_PRINT_REGISTER(isp, SYSSTATUS);
2386 +       ISP_PRINT_REGISTER(isp, IRQ0ENABLE);
2387 +       ISP_PRINT_REGISTER(isp, IRQ0STATUS);
2388 +       ISP_PRINT_REGISTER(isp, TCTRL_GRESET_LENGTH);
2389 +       ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_REPLAY);
2390 +       ISP_PRINT_REGISTER(isp, CTRL);
2391 +       ISP_PRINT_REGISTER(isp, TCTRL_CTRL);
2392 +       ISP_PRINT_REGISTER(isp, TCTRL_FRAME);
2393 +       ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_DELAY);
2394 +       ISP_PRINT_REGISTER(isp, TCTRL_STRB_DELAY);
2395 +       ISP_PRINT_REGISTER(isp, TCTRL_SHUT_DELAY);
2396 +       ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_LENGTH);
2397 +       ISP_PRINT_REGISTER(isp, TCTRL_STRB_LENGTH);
2398 +       ISP_PRINT_REGISTER(isp, TCTRL_SHUT_LENGTH);
2400 +       SBL_PRINT_REGISTER(isp, PCR);
2401 +       SBL_PRINT_REGISTER(isp, SDR_REQ_EXP);
2403 +       dev_dbg(isp->dev, "--------------------------------------------\n");
2404 +}
2406 +#ifdef CONFIG_PM
2408 +/*
2409 + * Power management support.
2410 + *
2411 + * As the ISP can't properly handle an input video stream interruption on a non
2412 + * frame boundary, the ISP pipelines need to be stopped before sensors get
2413 + * suspended. However, as suspending the sensors can require a running clock,
2414 + * which can be provided by the ISP, the ISP can't be completely suspended
2415 + * before the sensor.
2416 + *
2417 + * To solve this problem power management support is split into prepare/complete
2418 + * and suspend/resume operations. The pipelines are stopped in prepare() and the
2419 + * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in
2420 + * resume(), and the the pipelines are restarted in complete().
2421 + *
2422 + * TODO: PM dependencies between the ISP and sensors are not modeled explicitly
2423 + * yet.
2424 + */
2425 +static int isp_pm_prepare(struct device *dev)
2426 +{
2427 +       struct isp_device *isp = dev_get_drvdata(dev);
2428 +       int reset;
2430 +       WARN_ON(mutex_is_locked(&isp->isp_mutex));
2432 +       if (isp->ref_count == 0)
2433 +               return 0;
2435 +       reset = isp_suspend_modules(isp);
2436 +       isp_disable_interrupts(isp);
2437 +       isp_save_ctx(isp);
2438 +       if (reset)
2439 +               isp_reset(isp);
2441 +       return 0;
2442 +}
2444 +static int isp_pm_suspend(struct device *dev)
2445 +{
2446 +       struct isp_device *isp = dev_get_drvdata(dev);
2448 +       WARN_ON(mutex_is_locked(&isp->isp_mutex));
2450 +       if (isp->ref_count)
2451 +               isp_disable_clocks(isp);
2453 +       return 0;
2454 +}
2456 +static int isp_pm_resume(struct device *dev)
2457 +{
2458 +       struct isp_device *isp = dev_get_drvdata(dev);
2460 +       if (isp->ref_count == 0)
2461 +               return 0;
2463 +       return isp_enable_clocks(isp);
2464 +}
2466 +static void isp_pm_complete(struct device *dev)
2467 +{
2468 +       struct isp_device *isp = dev_get_drvdata(dev);
2470 +       if (isp->ref_count == 0)
2471 +               return;
2473 +       isp_restore_ctx(isp);
2474 +       isp_enable_interrupts(isp);
2475 +       isp_resume_modules(isp);
2476 +}
2478 +#else
2480 +#define isp_pm_prepare NULL
2481 +#define isp_pm_suspend NULL
2482 +#define isp_pm_resume  NULL
2483 +#define isp_pm_complete        NULL
2485 +#endif /* CONFIG_PM */
2487 +static void isp_unregister_entities(struct isp_device *isp)
2488 +{
2489 +       omap3isp_csi2_unregister_entities(&isp->isp_csi2a);
2490 +       omap3isp_ccp2_unregister_entities(&isp->isp_ccp2);
2491 +       omap3isp_ccdc_unregister_entities(&isp->isp_ccdc);
2492 +       omap3isp_preview_unregister_entities(&isp->isp_prev);
2493 +       omap3isp_resizer_unregister_entities(&isp->isp_res);
2494 +       omap3isp_stat_unregister_entities(&isp->isp_aewb);
2495 +       omap3isp_stat_unregister_entities(&isp->isp_af);
2496 +       omap3isp_stat_unregister_entities(&isp->isp_hist);
2498 +       v4l2_device_unregister(&isp->v4l2_dev);
2499 +       media_device_unregister(&isp->media_dev);
2500 +}
2502 +/*
2503 + * isp_register_subdev_group - Register a group of subdevices
2504 + * @isp: OMAP3 ISP device
2505 + * @board_info: I2C subdevs board information array
2506 + *
2507 + * Register all I2C subdevices in the board_info array. The array must be
2508 + * terminated by a NULL entry, and the first entry must be the sensor.
2509 + *
2510 + * Return a pointer to the sensor media entity if it has been successfully
2511 + * registered, or NULL otherwise.
2512 + */
2513 +static struct v4l2_subdev *
2514 +isp_register_subdev_group(struct isp_device *isp,
2515 +                    struct isp_subdev_i2c_board_info *board_info)
2516 +{
2517 +       struct v4l2_subdev *sensor = NULL;
2518 +       unsigned int first;
2520 +       if (board_info->board_info == NULL)
2521 +               return NULL;
2523 +       for (first = 1; board_info->board_info; ++board_info, first = 0) {
2524 +               struct v4l2_subdev *subdev;
2525 +               struct i2c_adapter *adapter;
2527 +               adapter = i2c_get_adapter(board_info->i2c_adapter_id);
2528 +               if (adapter == NULL) {
2529 +                       printk(KERN_ERR "%s: Unable to get I2C adapter %d for "
2530 +                               "device %s\n", __func__,
2531 +                               board_info->i2c_adapter_id,
2532 +                               board_info->board_info->type);
2533 +                       continue;
2534 +               }
2536 +               subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
2537 +                               board_info->board_info, NULL, 1);
2538 +               if (subdev == NULL) {
2539 +                       printk(KERN_ERR "%s: Unable to register subdev %s\n",
2540 +                               __func__, board_info->board_info->type);
2541 +                       continue;
2542 +               }
2544 +               if (first)
2545 +                       sensor = subdev;
2546 +       }
2548 +       return sensor;
2549 +}
2551 +static int isp_register_entities(struct isp_device *isp)
2552 +{
2553 +       struct isp_platform_data *pdata = isp->pdata;
2554 +       struct isp_v4l2_subdevs_group *subdevs;
2555 +       int ret;
2557 +       isp->media_dev.dev = isp->dev;
2558 +       strlcpy(isp->media_dev.model, "TI OMAP3 ISP",
2559 +               sizeof(isp->media_dev.model));
2560 +       isp->media_dev.link_notify = isp_pipeline_link_notify;
2561 +       ret = media_device_register(&isp->media_dev);
2562 +       if (ret < 0) {
2563 +               printk(KERN_ERR "%s: Media device registration failed (%d)\n",
2564 +                       __func__, ret);
2565 +               return ret;
2566 +       }
2568 +       isp->v4l2_dev.mdev = &isp->media_dev;
2569 +       ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
2570 +       if (ret < 0) {
2571 +               printk(KERN_ERR "%s: V4L2 device registration failed (%d)\n",
2572 +                       __func__, ret);
2573 +               goto done;
2574 +       }
2576 +       /* Register internal entities */
2577 +       ret = omap3isp_ccp2_register_entities(&isp->isp_ccp2, &isp->v4l2_dev);
2578 +       if (ret < 0)
2579 +               goto done;
2581 +       ret = omap3isp_csi2_register_entities(&isp->isp_csi2a, &isp->v4l2_dev);
2582 +       if (ret < 0)
2583 +               goto done;
2585 +       ret = omap3isp_ccdc_register_entities(&isp->isp_ccdc, &isp->v4l2_dev);
2586 +       if (ret < 0)
2587 +               goto done;
2589 +       ret = omap3isp_preview_register_entities(&isp->isp_prev,
2590 +                                                &isp->v4l2_dev);
2591 +       if (ret < 0)
2592 +               goto done;
2594 +       ret = omap3isp_resizer_register_entities(&isp->isp_res, &isp->v4l2_dev);
2595 +       if (ret < 0)
2596 +               goto done;
2598 +       ret = omap3isp_stat_register_entities(&isp->isp_aewb, &isp->v4l2_dev);
2599 +       if (ret < 0)
2600 +               goto done;
2602 +       ret = omap3isp_stat_register_entities(&isp->isp_af, &isp->v4l2_dev);
2603 +       if (ret < 0)
2604 +               goto done;
2606 +       ret = omap3isp_stat_register_entities(&isp->isp_hist, &isp->v4l2_dev);
2607 +       if (ret < 0)
2608 +               goto done;
2610 +       /* Register external entities */
2611 +       for (subdevs = pdata->subdevs; subdevs->subdevs; ++subdevs) {
2612 +               struct v4l2_subdev *sensor;
2613 +               struct media_entity *input;
2614 +               unsigned int flags;
2615 +               unsigned int pad;
2617 +               sensor = isp_register_subdev_group(isp, subdevs->subdevs);
2618 +               if (sensor == NULL)
2619 +                       continue;
2621 +               sensor->host_priv = subdevs;
2623 +               /* Connect the sensor to the correct interface module. Parallel
2624 +                * sensors are connected directly to the CCDC, while serial
2625 +                * sensors are connected to the CSI2a, CCP2b or CSI2c receiver
2626 +                * through CSIPHY1 or CSIPHY2.
2627 +                */
2628 +               switch (subdevs->interface) {
2629 +               case ISP_INTERFACE_PARALLEL:
2630 +                       input = &isp->isp_ccdc.subdev.entity;
2631 +                       pad = CCDC_PAD_SINK;
2632 +                       flags = 0;
2633 +                       break;
2635 +               case ISP_INTERFACE_CSI2A_PHY2:
2636 +                       input = &isp->isp_csi2a.subdev.entity;
2637 +                       pad = CSI2_PAD_SINK;
2638 +                       flags = MEDIA_LNK_FL_IMMUTABLE
2639 +                             | MEDIA_LNK_FL_ENABLED;
2640 +                       break;
2642 +               case ISP_INTERFACE_CCP2B_PHY1:
2643 +               case ISP_INTERFACE_CCP2B_PHY2:
2644 +                       input = &isp->isp_ccp2.subdev.entity;
2645 +                       pad = CCP2_PAD_SINK;
2646 +                       flags = 0;
2647 +                       break;
2649 +               case ISP_INTERFACE_CSI2C_PHY1:
2650 +                       input = &isp->isp_csi2c.subdev.entity;
2651 +                       pad = CSI2_PAD_SINK;
2652 +                       flags = MEDIA_LNK_FL_IMMUTABLE
2653 +                             | MEDIA_LNK_FL_ENABLED;
2654 +                       break;
2656 +               default:
2657 +                       printk(KERN_ERR "%s: invalid interface type %u\n",
2658 +                              __func__, subdevs->interface);
2659 +                       ret = -EINVAL;
2660 +                       goto done;
2661 +               }
2663 +               ret = media_entity_create_link(&sensor->entity, 0, input, pad,
2664 +                                              flags);
2665 +               if (ret < 0)
2666 +                       goto done;
2667 +       }
2669 +done:
2670 +       if (ret < 0)
2671 +               isp_unregister_entities(isp);
2673 +       return ret;
2674 +}
2676 +static void isp_cleanup_modules(struct isp_device *isp)
2677 +{
2678 +       omap3isp_h3a_aewb_cleanup(isp);
2679 +       omap3isp_h3a_af_cleanup(isp);
2680 +       omap3isp_hist_cleanup(isp);
2681 +       omap3isp_resizer_cleanup(isp);
2682 +       omap3isp_preview_cleanup(isp);
2683 +       omap3isp_ccdc_cleanup(isp);
2684 +       omap3isp_ccp2_cleanup(isp);
2685 +       omap3isp_csi2_cleanup(isp);
2686 +}
2688 +static int isp_initialize_modules(struct isp_device *isp)
2689 +{
2690 +       int ret;
2692 +       ret = omap3isp_csiphy_init(isp);
2693 +       if (ret < 0) {
2694 +               dev_err(isp->dev, "CSI PHY initialization failed\n");
2695 +               goto error_csiphy;
2696 +       }
2698 +       ret = omap3isp_csi2_init(isp);
2699 +       if (ret < 0) {
2700 +               dev_err(isp->dev, "CSI2 initialization failed\n");
2701 +               goto error_csi2;
2702 +       }
2704 +       ret = omap3isp_ccp2_init(isp);
2705 +       if (ret < 0) {
2706 +               dev_err(isp->dev, "CCP2 initialization failed\n");
2707 +               goto error_ccp2;
2708 +       }
2710 +       ret = omap3isp_ccdc_init(isp);
2711 +       if (ret < 0) {
2712 +               dev_err(isp->dev, "CCDC initialization failed\n");
2713 +               goto error_ccdc;
2714 +       }
2716 +       ret = omap3isp_preview_init(isp);
2717 +       if (ret < 0) {
2718 +               dev_err(isp->dev, "Preview initialization failed\n");
2719 +               goto error_preview;
2720 +       }
2722 +       ret = omap3isp_resizer_init(isp);
2723 +       if (ret < 0) {
2724 +               dev_err(isp->dev, "Resizer initialization failed\n");
2725 +               goto error_resizer;
2726 +       }
2728 +       ret = omap3isp_hist_init(isp);
2729 +       if (ret < 0) {
2730 +               dev_err(isp->dev, "Histogram initialization failed\n");
2731 +               goto error_hist;
2732 +       }
2734 +       ret = omap3isp_h3a_aewb_init(isp);
2735 +       if (ret < 0) {
2736 +               dev_err(isp->dev, "H3A AEWB initialization failed\n");
2737 +               goto error_h3a_aewb;
2738 +       }
2740 +       ret = omap3isp_h3a_af_init(isp);
2741 +       if (ret < 0) {
2742 +               dev_err(isp->dev, "H3A AF initialization failed\n");
2743 +               goto error_h3a_af;
2744 +       }
2746 +       /* Connect the submodules. */
2747 +       ret = media_entity_create_link(
2748 +                       &isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
2749 +                       &isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
2750 +       if (ret < 0)
2751 +               goto error_link;
2753 +       ret = media_entity_create_link(
2754 +                       &isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
2755 +                       &isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
2756 +       if (ret < 0)
2757 +               goto error_link;
2759 +       ret = media_entity_create_link(
2760 +                       &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
2761 +                       &isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
2762 +       if (ret < 0)
2763 +               goto error_link;
2765 +       ret = media_entity_create_link(
2766 +                       &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
2767 +                       &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
2768 +       if (ret < 0)
2769 +               goto error_link;
2771 +       ret = media_entity_create_link(
2772 +                       &isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
2773 +                       &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
2774 +       if (ret < 0)
2775 +               goto error_link;
2777 +       ret = media_entity_create_link(
2778 +                       &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
2779 +                       &isp->isp_aewb.subdev.entity, 0,
2780 +                       MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
2781 +       if (ret < 0)
2782 +               goto error_link;
2784 +       ret = media_entity_create_link(
2785 +                       &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
2786 +                       &isp->isp_af.subdev.entity, 0,
2787 +                       MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
2788 +       if (ret < 0)
2789 +               goto error_link;
2791 +       ret = media_entity_create_link(
2792 +                       &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
2793 +                       &isp->isp_hist.subdev.entity, 0,
2794 +                       MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
2795 +       if (ret < 0)
2796 +               goto error_link;
2798 +       return 0;
2800 +error_link:
2801 +       omap3isp_h3a_af_cleanup(isp);
2802 +error_h3a_af:
2803 +       omap3isp_h3a_aewb_cleanup(isp);
2804 +error_h3a_aewb:
2805 +       omap3isp_hist_cleanup(isp);
2806 +error_hist:
2807 +       omap3isp_resizer_cleanup(isp);
2808 +error_resizer:
2809 +       omap3isp_preview_cleanup(isp);
2810 +error_preview:
2811 +       omap3isp_ccdc_cleanup(isp);
2812 +error_ccdc:
2813 +       omap3isp_ccp2_cleanup(isp);
2814 +error_ccp2:
2815 +       omap3isp_csi2_cleanup(isp);
2816 +error_csi2:
2817 +error_csiphy:
2818 +       return ret;
2819 +}
2821 +/*
2822 + * isp_remove - Remove ISP platform device
2823 + * @pdev: Pointer to ISP platform device
2824 + *
2825 + * Always returns 0.
2826 + */
2827 +static int isp_remove(struct platform_device *pdev)
2828 +{
2829 +       struct isp_device *isp = platform_get_drvdata(pdev);
2830 +       int i;
2832 +       isp_unregister_entities(isp);
2833 +       isp_cleanup_modules(isp);
2835 +       omap3isp_get(isp);
2836 +       iommu_put(isp->iommu);
2837 +       omap3isp_put(isp);
2839 +       free_irq(isp->irq_num, isp);
2840 +       isp_put_clocks(isp);
2842 +       for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) {
2843 +               if (isp->mmio_base[i]) {
2844 +                       iounmap(isp->mmio_base[i]);
2845 +                       isp->mmio_base[i] = NULL;
2846 +               }
2848 +               if (isp->mmio_base_phys[i]) {
2849 +                       release_mem_region(isp->mmio_base_phys[i],
2850 +                                          isp->mmio_size[i]);
2851 +                       isp->mmio_base_phys[i] = 0;
2852 +               }
2853 +       }
2855 +       regulator_put(isp->isp_csiphy1.vdd);
2856 +       regulator_put(isp->isp_csiphy2.vdd);
2857 +       kfree(isp);
2859 +       return 0;
2860 +}
2862 +static int isp_map_mem_resource(struct platform_device *pdev,
2863 +                               struct isp_device *isp,
2864 +                               enum isp_mem_resources res)
2865 +{
2866 +       struct resource *mem;
2868 +       /* request the mem region for the camera registers */
2870 +       mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
2871 +       if (!mem) {
2872 +               dev_err(isp->dev, "no mem resource?\n");
2873 +               return -ENODEV;
2874 +       }
2876 +       if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
2877 +               dev_err(isp->dev,
2878 +                       "cannot reserve camera register I/O region\n");
2879 +               return -ENODEV;
2880 +       }
2881 +       isp->mmio_base_phys[res] = mem->start;
2882 +       isp->mmio_size[res] = resource_size(mem);
2884 +       /* map the region */
2885 +       isp->mmio_base[res] = ioremap_nocache(isp->mmio_base_phys[res],
2886 +                                             isp->mmio_size[res]);
2887 +       if (!isp->mmio_base[res]) {
2888 +               dev_err(isp->dev, "cannot map camera register I/O region\n");
2889 +               return -ENODEV;
2890 +       }
2892 +       return 0;
2893 +}
2895 +/*
2896 + * isp_probe - Probe ISP platform device
2897 + * @pdev: Pointer to ISP platform device
2898 + *
2899 + * Returns 0 if successful,
2900 + *   -ENOMEM if no memory available,
2901 + *   -ENODEV if no platform device resources found
2902 + *     or no space for remapping registers,
2903 + *   -EINVAL if couldn't install ISR,
2904 + *   or clk_get return error value.
2905 + */
2906 +static int isp_probe(struct platform_device *pdev)
2907 +{
2908 +       struct isp_platform_data *pdata = pdev->dev.platform_data;
2909 +       struct isp_device *isp;
2910 +       int ret;
2911 +       int i, m;
2913 +       if (pdata == NULL)
2914 +               return -EINVAL;
2916 +       isp = kzalloc(sizeof(*isp), GFP_KERNEL);
2917 +       if (!isp) {
2918 +               dev_err(&pdev->dev, "could not allocate memory\n");
2919 +               return -ENOMEM;
2920 +       }
2922 +       isp->autoidle = autoidle;
2923 +       isp->platform_cb.set_xclk = isp_set_xclk;
2924 +       isp->platform_cb.set_pixel_clock = isp_set_pixel_clock;
2926 +       mutex_init(&isp->isp_mutex);
2927 +       spin_lock_init(&isp->stat_lock);
2929 +       isp->dev = &pdev->dev;
2930 +       isp->pdata = pdata;
2931 +       isp->ref_count = 0;
2933 +       isp->raw_dmamask = DMA_BIT_MASK(32);
2934 +       isp->dev->dma_mask = &isp->raw_dmamask;
2935 +       isp->dev->coherent_dma_mask = DMA_BIT_MASK(32);
2937 +       platform_set_drvdata(pdev, isp);
2939 +       /* Regulators */
2940 +       isp->isp_csiphy1.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY1");
2941 +       isp->isp_csiphy2.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY2");
2943 +       /* Clocks */
2944 +       ret = isp_map_mem_resource(pdev, isp, OMAP3_ISP_IOMEM_MAIN);
2945 +       if (ret < 0)
2946 +               goto error;
2948 +       ret = isp_get_clocks(isp);
2949 +       if (ret < 0)
2950 +               goto error;
2952 +       if (omap3isp_get(isp) == NULL)
2953 +               goto error;
2955 +       ret = isp_reset(isp);
2956 +       if (ret < 0)
2957 +               goto error_isp;
2959 +       /* Memory resources */
2960 +       isp->revision = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
2961 +       dev_info(isp->dev, "Revision %d.%d found\n",
2962 +                (isp->revision & 0xf0) >> 4, isp->revision & 0x0f);
2964 +       for (m = 0; m < ARRAY_SIZE(isp_res_maps); m++)
2965 +               if (isp->revision == isp_res_maps[m].isp_rev)
2966 +                       break;
2968 +       if (m == ARRAY_SIZE(isp_res_maps)) {
2969 +               dev_err(isp->dev, "No resource map found for ISP rev %d.%d\n",
2970 +                       (isp->revision & 0xf0) >> 4, isp->revision & 0xf);
2971 +               ret = -ENODEV;
2972 +               goto error_isp;
2973 +       }
2975 +       for (i = 1; i < OMAP3_ISP_IOMEM_LAST; i++) {
2976 +               if (isp_res_maps[m].map & 1 << i) {
2977 +                       ret = isp_map_mem_resource(pdev, isp, i);
2978 +                       if (ret)
2979 +                               goto error_isp;
2980 +               }
2981 +       }
2983 +       /* IOMMU */
2984 +       isp->iommu = iommu_get("isp");
2985 +       if (IS_ERR_OR_NULL(isp->iommu)) {
2986 +               isp->iommu = NULL;
2987 +               ret = -ENODEV;
2988 +               goto error_isp;
2989 +       }
2991 +       /* Interrupt */
2992 +       isp->irq_num = platform_get_irq(pdev, 0);
2993 +       if (isp->irq_num <= 0) {
2994 +               dev_err(isp->dev, "No IRQ resource\n");
2995 +               ret = -ENODEV;
2996 +               goto error_isp;
2997 +       }
2999 +       if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) {
3000 +               dev_err(isp->dev, "Unable to request IRQ\n");
3001 +               ret = -EINVAL;
3002 +               goto error_isp;
3003 +       }
3005 +       /* Entities */
3006 +       ret = isp_initialize_modules(isp);
3007 +       if (ret < 0)
3008 +               goto error_irq;
3010 +       ret = isp_register_entities(isp);
3011 +       if (ret < 0)
3012 +               goto error_modules;
3014 +       isp_power_settings(isp, 1);
3015 +       omap3isp_put(isp);
3017 +       return 0;
3019 +error_modules:
3020 +       isp_cleanup_modules(isp);
3021 +error_irq:
3022 +       free_irq(isp->irq_num, isp);
3023 +error_isp:
3024 +       iommu_put(isp->iommu);
3025 +       omap3isp_put(isp);
3026 +error:
3027 +       isp_put_clocks(isp);
3029 +       for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) {
3030 +               if (isp->mmio_base[i]) {
3031 +                       iounmap(isp->mmio_base[i]);
3032 +                       isp->mmio_base[i] = NULL;
3033 +               }
3035 +               if (isp->mmio_base_phys[i]) {
3036 +                       release_mem_region(isp->mmio_base_phys[i],
3037 +                                          isp->mmio_size[i]);
3038 +                       isp->mmio_base_phys[i] = 0;
3039 +               }
3040 +       }
3041 +       regulator_put(isp->isp_csiphy2.vdd);
3042 +       regulator_put(isp->isp_csiphy1.vdd);
3043 +       platform_set_drvdata(pdev, NULL);
3044 +       kfree(isp);
3046 +       return ret;
3047 +}
3049 +static const struct dev_pm_ops omap3isp_pm_ops = {
3050 +       .prepare = isp_pm_prepare,
3051 +       .suspend = isp_pm_suspend,
3052 +       .resume = isp_pm_resume,
3053 +       .complete = isp_pm_complete,
3054 +};
3056 +static struct platform_device_id omap3isp_id_table[] = {
3057 +       { "omap3isp", 0 },
3058 +       { },
3059 +};
3060 +MODULE_DEVICE_TABLE(platform, omap3isp_id_table);
3062 +static struct platform_driver omap3isp_driver = {
3063 +       .probe = isp_probe,
3064 +       .remove = isp_remove,
3065 +       .id_table = omap3isp_id_table,
3066 +       .driver = {
3067 +               .owner = THIS_MODULE,
3068 +               .name = "omap3isp",
3069 +               .pm     = &omap3isp_pm_ops,
3070 +       },
3071 +};
3073 +/*
3074 + * isp_init - ISP module initialization.
3075 + */
3076 +static int __init isp_init(void)
3077 +{
3078 +       return platform_driver_register(&omap3isp_driver);
3079 +}
3081 +/*
3082 + * isp_cleanup - ISP module cleanup.
3083 + */
3084 +static void __exit isp_cleanup(void)
3085 +{
3086 +       platform_driver_unregister(&omap3isp_driver);
3087 +}
3089 +module_init(isp_init);
3090 +module_exit(isp_cleanup);
3092 +MODULE_AUTHOR("Nokia Corporation");
3093 +MODULE_DESCRIPTION("TI OMAP3 ISP driver");
3094 +MODULE_LICENSE("GPL");
3095 diff --git a/drivers/media/video/isp/isp.h b/drivers/media/video/isp/isp.h
3096 new file mode 100644
3097 index 0000000..44590a5
3098 --- /dev/null
3099 +++ b/drivers/media/video/isp/isp.h
3100 @@ -0,0 +1,427 @@
3101 +/*
3102 + * isp.h
3103 + *
3104 + * TI OMAP3 ISP - Core
3105 + *
3106 + * Copyright (C) 2009-2010 Nokia Corporation
3107 + * Copyright (C) 2009 Texas Instruments, Inc.
3108 + *
3109 + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3110 + *          Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3111 + *