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.
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.
123 +
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.
129 +
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
139 obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
141 +obj-$(CONFIG_VIDEO_OMAP3) += isp/
142 +
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
153 +
154 +ifdef CONFIG_VIDEO_OMAP3_DEBUG
155 +EXTRA_CFLAGS += -DDEBUG
156 +endif
157 +
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
163 +
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 + */
195 +
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 + */
803 +
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 + */
927 +
928 +#include <asm/cacheflush.h>
929 +
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>
942 +
943 +#include <media/v4l2-common.h>
944 +#include <media/v4l2-device.h>
945 +
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"
955 +
956 +static unsigned int autoidle;
957 +module_param(autoidle, int, 0444);
958 +MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support");
959 +
960 +static void isp_save_ctx(struct isp_device *isp);
961 +
962 +static void isp_restore_ctx(struct isp_device *isp);
963 +
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 +};
996 +
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 +};
1004 +
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 +}
1020 +
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;
1039 +
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 +}
1043 +
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 +}
1052 +
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;
1071 +
1072 + if (!omap3isp_get(isp))
1073 + return 0;
1074 +
1075 + mclk_hz = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
1076 +
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 + }
1089 +
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 + }
1111 +
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);
1118 +
1119 + isp->xclk_divisor[xclksel] = divisor;
1120 +
1121 + omap3isp_put(isp);
1122 +
1123 + return currentxclk;
1124 +}
1125 +
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);
1142 +
1143 + if (isp->autoidle)
1144 + isp_reg_writel(isp, ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
1145 + ISP_CTRL);
1146 +}
1147 +
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;
1164 +
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;
1170 +
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;
1178 +
1179 + case CCDC_INPUT_CSI2A:
1180 + ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIA;
1181 + break;
1182 +
1183 + case CCDC_INPUT_CCP2B:
1184 + ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIB;
1185 + break;
1186 +
1187 + case CCDC_INPUT_CSI2C:
1188 + ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIC;
1189 + break;
1190 +
1191 + default:
1192 + return;
1193 + }
1194 +
1195 + ispctrl_val &= ~ISPCTRL_SYNC_DETECT_MASK;
1196 + ispctrl_val |= ISPCTRL_SYNC_DETECT_VSRISE;
1197 +
1198 + isp_reg_writel(isp, ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
1199 +}
1200 +
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 +}
1213 +
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 +}
1224 +
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;
1262 +
1263 + dev_dbg(isp->dev, "");
1264 +
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 +}
1271 +
1272 +static void isp_isr_sbl(struct isp_device *isp)
1273 +{
1274 + struct device *dev = isp->dev;
1275 + u32 sbl_pcr;
1276 +
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;
1284 +
1285 + if (sbl_pcr)
1286 + dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr);
1287 +
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 + }
1296 +
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 + }
1303 +
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;
1309 +
1310 + if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF)
1311 + omap3isp_stat_sbl_overflow(&isp->isp_af);
1312 +
1313 + if (sbl_pcr & ISPSBL_PCR_H3A_AEAWB_WBL_OVF)
1314 + omap3isp_stat_sbl_overflow(&isp->isp_aewb);
1315 +}
1316 +
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;
1337 +
1338 + irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
1339 + isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
1340 +
1341 + isp_isr_sbl(isp);
1342 +
1343 + if (irqstatus & IRQ0STATUS_CSIA_IRQ) {
1344 + ret = omap3isp_csi2_isr(&isp->isp_csi2a);
1345 + if (ret)
1346 + isp->isp_ccdc.error = 1;
1347 + }
1348 +
1349 + if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
1350 + ret = omap3isp_ccp2_isr(&isp->isp_ccp2);
1351 + if (ret)
1352 + isp->isp_ccdc.error = 1;
1353 + }
1354 +
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 + }
1364 +
1365 + if (irqstatus & ccdc_events)
1366 + omap3isp_ccdc_isr(&isp->isp_ccdc, irqstatus & ccdc_events);
1367 +
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 + }
1373 +
1374 + if (irqstatus & IRQ0STATUS_RSZ_DONE_IRQ)
1375 + omap3isp_resizer_isr(&isp->isp_res);
1376 +
1377 + if (irqstatus & IRQ0STATUS_H3A_AWB_DONE_IRQ)
1378 + omap3isp_stat_isr(&isp->isp_aewb);
1379 +
1380 + if (irqstatus & IRQ0STATUS_H3A_AF_DONE_IRQ)
1381 + omap3isp_stat_isr(&isp->isp_af);
1382 +
1383 + if (irqstatus & IRQ0STATUS_HIST_DONE_IRQ)
1384 + omap3isp_stat_isr(&isp->isp_hist);
1385 +
1386 + omap3isp_flush(isp);
1387 +
1388 +#if defined(DEBUG) && defined(ISP_ISR_DEBUG)
1389 + isp_isr_dbg(isp, irqstatus);
1390 +#endif
1391 +
1392 + return IRQ_HANDLED;
1393 +}
1394 +
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 + */
1415 +
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;
1426 +
1427 + media_entity_graph_walk_start(&graph, entity);
1428 +
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 + }
1433 +
1434 + return use;
1435 +}
1436 +
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;
1452 +
1453 + subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
1454 + ? media_entity_to_v4l2_subdev(entity) : NULL;
1455 +
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 + }
1461 +
1462 + entity->use_count += change;
1463 + WARN_ON(entity->use_count < 0);
1464 +
1465 + if (entity->use_count == 0 && change < 0 && subdev != NULL)
1466 + v4l2_subdev_call(subdev, core, s_power, 0);
1467 +
1468 + return 0;
1469 +}
1470 +
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;
1486 +
1487 + if (!change)
1488 + return 0;
1489 +
1490 + media_entity_graph_walk_start(&graph, entity);
1491 +
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);
1495 +
1496 + if (!ret)
1497 + return 0;
1498 +
1499 + media_entity_graph_walk_start(&graph, first);
1500 +
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);
1505 +
1506 + return ret;
1507 +}
1508 +
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;
1525 +
1526 + mutex_lock(&entity->parent->graph_mutex);
1527 +
1528 + /* Apply use count to node. */
1529 + entity->use_count += change;
1530 + WARN_ON(entity->use_count < 0);
1531 +
1532 + /* Apply power change to connected non-nodes. */
1533 + ret = isp_pipeline_pm_power(entity, change);
1534 +
1535 + mutex_unlock(&entity->parent->graph_mutex);
1536 +
1537 + return ret;
1538 +}
1539 +
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;
1560 +
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 + }
1567 +
1568 + ret = isp_pipeline_pm_power(source->entity, sink_use);
1569 + if (ret < 0)
1570 + return ret;
1571 +
1572 + ret = isp_pipeline_pm_power(sink->entity, source_use);
1573 + if (ret < 0)
1574 + isp_pipeline_pm_power(source->entity, -sink_use);
1575 +
1576 + return ret;
1577 +}
1578 +
1579 +/* -----------------------------------------------------------------------------
1580 + * Pipeline stream management
1581 + */
1582 +
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;
1603 +
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);
1607 +
1608 + pipe->do_propagation = false;
1609 +
1610 + entity = &pipe->output->video.entity;
1611 + while (1) {
1612 + pad = &entity->pads[0];
1613 + if (!(pad->flags & MEDIA_PAD_FL_INPUT))
1614 + break;
1615 +
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;
1621 +
1622 + entity = pad->entity;
1623 + subdev = media_entity_to_v4l2_subdev(entity);
1624 +
1625 + ret = v4l2_subdev_call(subdev, video, s_stream, mode);
1626 + if (ret < 0 && ret != -ENOIOCTLCMD)
1627 + break;
1628 +
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 + }
1639 +
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);
1647 +
1648 + return ret;
1649 +}
1650 +
1651 +static int isp_pipeline_wait_resizer(struct isp_device *isp)
1652 +{
1653 + return omap3isp_resizer_busy(&isp->isp_res);
1654 +}
1655 +
1656 +static int isp_pipeline_wait_preview(struct isp_device *isp)
1657 +{
1658 + return omap3isp_preview_busy(&isp->isp_prev);
1659 +}
1660 +
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 +}
1668 +
1669 +#define ISP_STOP_TIMEOUT msecs_to_jiffies(1000)
1670 +
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;
1675 +
1676 + while (!time_after(jiffies, timeout)) {
1677 + if (!busy(isp))
1678 + return 0;
1679 + }
1680 +
1681 + return 1;
1682 +}
1683 +
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;
1704 +
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;
1714 +
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;
1720 +
1721 + entity = pad->entity;
1722 + subdev = media_entity_to_v4l2_subdev(entity);
1723 +
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 + }
1732 +
1733 + v4l2_subdev_call(subdev, video, s_stream, 0);
1734 +
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 + }
1744 +
1745 + if (ret) {
1746 + dev_info(isp->dev, "Unable to stop %s\n", subdev->name);
1747 + failure = -ETIMEDOUT;
1748 + }
1749 + }
1750 +
1751 + return failure;
1752 +}
1753 +
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;
1769 +
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;
1775 +
1776 + return ret;
1777 +}
1778 +
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;
1788 +
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 +}
1794 +
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 +}
1805 +
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;
1819 +
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 +}
1828 +
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 +}
1842 +
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 +}
1856 +
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;
1867 +
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);
1876 +
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 + }
1890 +
1891 + return 0;
1892 +}
1893 +
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 +}
1909 +
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;
1917 +
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 + }
1930 +
1931 + return 0;
1932 +}
1933 +
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;
1944 +
1945 + for (; next->reg != ISP_TOK_TERM; next++)
1946 + next->val = isp_reg_readl(isp, next->mmio_range, next->reg);
1947 +}
1948 +
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;
1959 +
1960 + for (; next->reg != ISP_TOK_TERM; next++)
1961 + isp_reg_writel(isp, next->val, next->mmio_range, next->reg);
1962 +}
1963 +
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 +}
1977 +
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 +}
1993 +
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)
2006 +
2007 +void omap3isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res)
2008 +{
2009 + u32 sbl = 0;
2010 +
2011 + isp->sbl_resources |= res;
2012 +
2013 + if (isp->sbl_resources & OMAP3_ISP_SBL_CSI1_READ)
2014 + sbl |= ISPCTRL_SBL_SHARED_RPORTA;
2015 +
2016 + if (isp->sbl_resources & OMAP3_ISP_SBL_CCDC_LSC_READ)
2017 + sbl |= ISPCTRL_SBL_SHARED_RPORTB;
2018 +
2019 + if (isp->sbl_resources & OMAP3_ISP_SBL_CSI2C_WRITE)
2020 + sbl |= ISPCTRL_SBL_SHARED_WPORTC;
2021 +
2022 + if (isp->sbl_resources & OMAP3_ISP_SBL_RESIZER_WRITE)
2023 + sbl |= ISPCTRL_SBL_WR0_RAM_EN;
2024 +
2025 + if (isp->sbl_resources & OMAP3_ISP_SBL_WRITE)
2026 + sbl |= ISPCTRL_SBL_WR1_RAM_EN;
2027 +
2028 + if (isp->sbl_resources & OMAP3_ISP_SBL_READ)
2029 + sbl |= ISPCTRL_SBL_RD_RAM_EN;
2030 +
2031 + isp_reg_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, sbl);
2032 +}
2033 +
2034 +void omap3isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res)
2035 +{
2036 + u32 sbl = 0;
2037 +
2038 + isp->sbl_resources &= ~res;
2039 +
2040 + if (!(isp->sbl_resources & OMAP3_ISP_SBL_CSI1_READ))
2041 + sbl |= ISPCTRL_SBL_SHARED_RPORTA;
2042 +
2043 + if (!(isp->sbl_resources & OMAP3_ISP_SBL_CCDC_LSC_READ))
2044 + sbl |= ISPCTRL_SBL_SHARED_RPORTB;
2045 +
2046 + if (!(isp->sbl_resources & OMAP3_ISP_SBL_CSI2C_WRITE))
2047 + sbl |= ISPCTRL_SBL_SHARED_WPORTC;
2048 +
2049 + if (!(isp->sbl_resources & OMAP3_ISP_SBL_RESIZER_WRITE))
2050 + sbl |= ISPCTRL_SBL_WR0_RAM_EN;
2051 +
2052 + if (!(isp->sbl_resources & OMAP3_ISP_SBL_WRITE))
2053 + sbl |= ISPCTRL_SBL_WR1_RAM_EN;
2054 +
2055 + if (!(isp->sbl_resources & OMAP3_ISP_SBL_READ))
2056 + sbl |= ISPCTRL_SBL_RD_RAM_EN;
2057 +
2058 + isp_reg_clr(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, sbl);
2059 +}
2060 +
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);
2074 +
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;
2079 +
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();
2086 +
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 + }
2114 +
2115 + return 0;
2116 +}
2117 +
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 + }
2134 +
2135 + return 0;
2136 +}
2137 +
2138 +/* --------------------------------------------------------------------------
2139 + * Clock management
2140 + */
2141 +
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))
2147 +
2148 +static void __isp_subclk_update(struct isp_device *isp)
2149 +{
2150 + u32 clk = 0;
2151 +
2152 + if (isp->subclk_resources & OMAP3_ISP_SUBCLK_H3A)
2153 + clk |= ISPCTRL_H3A_CLK_EN;
2154 +
2155 + if (isp->subclk_resources & OMAP3_ISP_SUBCLK_HIST)
2156 + clk |= ISPCTRL_HIST_CLK_EN;
2157 +
2158 + if (isp->subclk_resources & OMAP3_ISP_SUBCLK_RESIZER)
2159 + clk |= ISPCTRL_RSZ_CLK_EN;
2160 +
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;
2166 +
2167 + if (isp->subclk_resources & OMAP3_ISP_SUBCLK_PREVIEW)
2168 + clk |= ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN;
2169 +
2170 + isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
2171 + ISPCTRL_CLKS_MASK, clk);
2172 +}
2173 +
2174 +void omap3isp_subclk_enable(struct isp_device *isp,
2175 + enum isp_subclk_resource res)
2176 +{
2177 + isp->subclk_resources |= res;
2178 +
2179 + __isp_subclk_update(isp);
2180 +}
2181 +
2182 +void omap3isp_subclk_disable(struct isp_device *isp,
2183 + enum isp_subclk_resource res)
2184 +{
2185 + isp->subclk_resources &= ~res;
2186 +
2187 + __isp_subclk_update(isp);
2188 +}
2189 +
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;
2201 +
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;
2215 +
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;
2243 +
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 +}
2251 +
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 +}
2262 +
2263 +static const char *isp_clocks[] = {
2264 + "cam_ick",
2265 + "cam_mclk",
2266 + "dpll4_m5_ck",
2267 + "csi2_96m_fck",
2268 + "l3_ick",
2269 +};
2270 +
2271 +static void isp_put_clocks(struct isp_device *isp)
2272 +{
2273 + unsigned int i;
2274 +
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 +}
2282 +
2283 +static int isp_get_clocks(struct isp_device *isp)
2284 +{
2285 + struct clk *clk;
2286 + unsigned int i;
2287 +
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 + }
2295 +
2296 + isp->clock[i] = clk;
2297 + }
2298 +
2299 + return 0;
2300 +}
2301 +
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;
2315 +
2316 + if (isp == NULL)
2317 + return NULL;
2318 +
2319 + mutex_lock(&isp->isp_mutex);
2320 + if (isp->ref_count > 0)
2321 + goto out;
2322 +
2323 + if (isp_enable_clocks(isp) < 0) {
2324 + __isp = NULL;
2325 + goto out;
2326 + }
2327 +
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;
2333 +
2334 + isp_enable_interrupts(isp);
2335 +
2336 +out:
2337 + if (__isp != NULL)
2338 + isp->ref_count++;
2339 + mutex_unlock(&isp->isp_mutex);
2340 +
2341 + return __isp;
2342 +}
2343 +
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;
2354 +
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 +}
2364 +
2365 +/* --------------------------------------------------------------------------
2366 + * Platform device driver
2367 + */
2368 +
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))
2379 +
2380 +void omap3isp_print_status(struct isp_device *isp)
2381 +{
2382 + dev_dbg(isp->dev, "-------------ISP Register dump--------------\n");
2383 +
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);
2399 +
2400 + SBL_PRINT_REGISTER(isp, PCR);
2401 + SBL_PRINT_REGISTER(isp, SDR_REQ_EXP);
2402 +
2403 + dev_dbg(isp->dev, "--------------------------------------------\n");
2404 +}
2405 +
2406 +#ifdef CONFIG_PM
2407 +
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;
2429 +
2430 + WARN_ON(mutex_is_locked(&isp->isp_mutex));
2431 +
2432 + if (isp->ref_count == 0)
2433 + return 0;
2434 +
2435 + reset = isp_suspend_modules(isp);
2436 + isp_disable_interrupts(isp);
2437 + isp_save_ctx(isp);
2438 + if (reset)
2439 + isp_reset(isp);
2440 +
2441 + return 0;
2442 +}
2443 +
2444 +static int isp_pm_suspend(struct device *dev)
2445 +{
2446 + struct isp_device *isp = dev_get_drvdata(dev);
2447 +
2448 + WARN_ON(mutex_is_locked(&isp->isp_mutex));
2449 +
2450 + if (isp->ref_count)
2451 + isp_disable_clocks(isp);
2452 +
2453 + return 0;
2454 +}
2455 +
2456 +static int isp_pm_resume(struct device *dev)
2457 +{
2458 + struct isp_device *isp = dev_get_drvdata(dev);
2459 +
2460 + if (isp->ref_count == 0)
2461 + return 0;
2462 +
2463 + return isp_enable_clocks(isp);
2464 +}
2465 +
2466 +static void isp_pm_complete(struct device *dev)
2467 +{
2468 + struct isp_device *isp = dev_get_drvdata(dev);
2469 +
2470 + if (isp->ref_count == 0)
2471 + return;
2472 +
2473 + isp_restore_ctx(isp);
2474 + isp_enable_interrupts(isp);
2475 + isp_resume_modules(isp);
2476 +}
2477 +
2478 +#else
2479 +
2480 +#define isp_pm_prepare NULL
2481 +#define isp_pm_suspend NULL
2482 +#define isp_pm_resume NULL
2483 +#define isp_pm_complete NULL
2484 +
2485 +#endif /* CONFIG_PM */
2486 +
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);
2497 +
2498 + v4l2_device_unregister(&isp->v4l2_dev);
2499 + media_device_unregister(&isp->media_dev);
2500 +}
2501 +
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;
2519 +
2520 + if (board_info->board_info == NULL)
2521 + return NULL;
2522 +
2523 + for (first = 1; board_info->board_info; ++board_info, first = 0) {
2524 + struct v4l2_subdev *subdev;
2525 + struct i2c_adapter *adapter;
2526 +
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 + }
2535 +
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 + }
2543 +
2544 + if (first)
2545 + sensor = subdev;
2546 + }
2547 +
2548 + return sensor;
2549 +}
2550 +
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;
2556 +
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 + }
2567 +
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 + }
2575 +
2576 + /* Register internal entities */
2577 + ret = omap3isp_ccp2_register_entities(&isp->isp_ccp2, &isp->v4l2_dev);
2578 + if (ret < 0)
2579 + goto done;
2580 +
2581 + ret = omap3isp_csi2_register_entities(&isp->isp_csi2a, &isp->v4l2_dev);
2582 + if (ret < 0)
2583 + goto done;
2584 +
2585 + ret = omap3isp_ccdc_register_entities(&isp->isp_ccdc, &isp->v4l2_dev);
2586 + if (ret < 0)
2587 + goto done;
2588 +
2589 + ret = omap3isp_preview_register_entities(&isp->isp_prev,
2590 + &isp->v4l2_dev);
2591 + if (ret < 0)
2592 + goto done;
2593 +
2594 + ret = omap3isp_resizer_register_entities(&isp->isp_res, &isp->v4l2_dev);
2595 + if (ret < 0)
2596 + goto done;
2597 +
2598 + ret = omap3isp_stat_register_entities(&isp->isp_aewb, &isp->v4l2_dev);
2599 + if (ret < 0)
2600 + goto done;
2601 +
2602 + ret = omap3isp_stat_register_entities(&isp->isp_af, &isp->v4l2_dev);
2603 + if (ret < 0)
2604 + goto done;
2605 +
2606 + ret = omap3isp_stat_register_entities(&isp->isp_hist, &isp->v4l2_dev);
2607 + if (ret < 0)
2608 + goto done;
2609 +
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;
2616 +
2617 + sensor = isp_register_subdev_group(isp, subdevs->subdevs);
2618 + if (sensor == NULL)
2619 + continue;
2620 +
2621 + sensor->host_priv = subdevs;
2622 +
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;
2634 +
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;
2641 +
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;
2648 +
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;
2655 +
2656 + default:
2657 + printk(KERN_ERR "%s: invalid interface type %u\n",
2658 + __func__, subdevs->interface);
2659 + ret = -EINVAL;
2660 + goto done;
2661 + }
2662 +
2663 + ret = media_entity_create_link(&sensor->entity, 0, input, pad,
2664 + flags);
2665 + if (ret < 0)
2666 + goto done;
2667 + }
2668 +
2669 +done:
2670 + if (ret < 0)
2671 + isp_unregister_entities(isp);
2672 +
2673 + return ret;
2674 +}
2675 +
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 +}
2687 +
2688 +static int isp_initialize_modules(struct isp_device *isp)
2689 +{
2690 + int ret;
2691 +
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 + }
2697 +
2698 + ret = omap3isp_csi2_init(isp);
2699 + if (ret < 0) {
2700 + dev_err(isp->dev, "CSI2 initialization failed\n");
2701 + goto error_csi2;
2702 + }
2703 +
2704 + ret = omap3isp_ccp2_init(isp);
2705 + if (ret < 0) {
2706 + dev_err(isp->dev, "CCP2 initialization failed\n");
2707 + goto error_ccp2;
2708 + }
2709 +
2710 + ret = omap3isp_ccdc_init(isp);
2711 + if (ret < 0) {
2712 + dev_err(isp->dev, "CCDC initialization failed\n");
2713 + goto error_ccdc;
2714 + }
2715 +
2716 + ret = omap3isp_preview_init(isp);
2717 + if (ret < 0) {
2718 + dev_err(isp->dev, "Preview initialization failed\n");
2719 + goto error_preview;
2720 + }
2721 +
2722 + ret = omap3isp_resizer_init(isp);
2723 + if (ret < 0) {
2724 + dev_err(isp->dev, "Resizer initialization failed\n");
2725 + goto error_resizer;
2726 + }
2727 +
2728 + ret = omap3isp_hist_init(isp);
2729 + if (ret < 0) {
2730 + dev_err(isp->dev, "Histogram initialization failed\n");
2731 + goto error_hist;
2732 + }
2733 +
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 + }
2739 +
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 + }
2745 +
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;
2752 +
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;
2758 +
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;
2764 +
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;
2770 +
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;
2776 +
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;
2783 +
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;
2790 +
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;
2797 +
2798 + return 0;
2799 +
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 +}
2820 +
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;
2831 +
2832 + isp_unregister_entities(isp);
2833 + isp_cleanup_modules(isp);
2834 +
2835 + omap3isp_get(isp);
2836 + iommu_put(isp->iommu);
2837 + omap3isp_put(isp);
2838 +
2839 + free_irq(isp->irq_num, isp);
2840 + isp_put_clocks(isp);
2841 +
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 + }
2847 +
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 + }
2854 +
2855 + regulator_put(isp->isp_csiphy1.vdd);
2856 + regulator_put(isp->isp_csiphy2.vdd);
2857 + kfree(isp);
2858 +
2859 + return 0;
2860 +}
2861 +
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;
2867 +
2868 + /* request the mem region for the camera registers */
2869 +
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 + }
2875 +
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);
2883 +
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 + }
2891 +
2892 + return 0;
2893 +}
2894 +
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;
2912 +
2913 + if (pdata == NULL)
2914 + return -EINVAL;
2915 +
2916 + isp = kzalloc(sizeof(*isp), GFP_KERNEL);
2917 + if (!isp) {
2918 + dev_err(&pdev->dev, "could not allocate memory\n");
2919 + return -ENOMEM;
2920 + }
2921 +
2922 + isp->autoidle = autoidle;
2923 + isp->platform_cb.set_xclk = isp_set_xclk;
2924 + isp->platform_cb.set_pixel_clock = isp_set_pixel_clock;
2925 +
2926 + mutex_init(&isp->isp_mutex);
2927 + spin_lock_init(&isp->stat_lock);
2928 +
2929 + isp->dev = &pdev->dev;
2930 + isp->pdata = pdata;
2931 + isp->ref_count = 0;
2932 +
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);
2936 +
2937 + platform_set_drvdata(pdev, isp);
2938 +
2939 + /* Regulators */
2940 + isp->isp_csiphy1.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY1");
2941 + isp->isp_csiphy2.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY2");
2942 +
2943 + /* Clocks */
2944 + ret = isp_map_mem_resource(pdev, isp, OMAP3_ISP_IOMEM_MAIN);
2945 + if (ret < 0)
2946 + goto error;
2947 +
2948 + ret = isp_get_clocks(isp);
2949 + if (ret < 0)
2950 + goto error;
2951 +
2952 + if (omap3isp_get(isp) == NULL)
2953 + goto error;
2954 +
2955 + ret = isp_reset(isp);
2956 + if (ret < 0)
2957 + goto error_isp;
2958 +
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);
2963 +
2964 + for (m = 0; m < ARRAY_SIZE(isp_res_maps); m++)
2965 + if (isp->revision == isp_res_maps[m].isp_rev)
2966 + break;
2967 +
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 + }
2974 +
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 + }
2982 +
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 + }
2990 +
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 + }
2998 +
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 + }
3004 +
3005 + /* Entities */
3006 + ret = isp_initialize_modules(isp);
3007 + if (ret < 0)
3008 + goto error_irq;
3009 +
3010 + ret = isp_register_entities(isp);
3011 + if (ret < 0)
3012 + goto error_modules;
3013 +
3014 + isp_power_settings(isp, 1);
3015 + omap3isp_put(isp);
3016 +
3017 + return 0;
3018 +
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);
3028 +
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 + }
3034 +
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);
3045 +
3046 + return ret;
3047 +}
3048 +
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 +};
3055 +
3056 +static struct platform_device_id omap3isp_id_table[] = {
3057 + { "omap3isp", 0 },
3058 + { },
3059 +};
3060 +MODULE_DEVICE_TABLE(platform, omap3isp_id_table);
3061 +
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 +};
3072 +
3073 +/*
3074 + * isp_init - ISP module initialization.
3075 + */
3076 +static int __init isp_init(void)
3077 +{
3078 + return platform_driver_register(&omap3isp_driver);
3079 +}
3080 +
3081 +/*
3082 + * isp_cleanup - ISP module cleanup.
3083 + */
3084 +static void __exit isp_cleanup(void)
3085 +{
3086 + platform_driver_unregister(&omap3isp_driver);
3087 +}
3088 +
3089 +module_init(isp_init);
3090 +module_exit(isp_cleanup);
3091 +
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 + *