summaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap/media/0043-OMAP3-ISP-driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/media/0043-OMAP3-ISP-driver.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap/media/0043-OMAP3-ISP-driver.patch21513
1 files changed, 21513 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/media/0043-OMAP3-ISP-driver.patch b/extras/recipes-kernel/linux/linux-omap/media/0043-OMAP3-ISP-driver.patch
new file mode 100644
index 00000000..b4e97848
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap/media/0043-OMAP3-ISP-driver.patch
@@ -0,0 +1,21513 @@
1From f12978691d5189949c9296bceb43c5b272c9c03c Mon Sep 17 00:00:00 2001
2From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3Date: Tue, 17 Feb 2009 09:23:45 -0600
4Subject: [PATCH 43/43] OMAP3 ISP driver
5
6Last 10 commits from upstream are
7
8omap3isp: Autoidle enabled for ISP
9omap3isp: enable AUTOIDLE through module parameter
10omap3isp: preview: Fix defect correct config function
11omap3isp: video: Replace BUG with WARN_ON in case of buffer queue error
12omap3isp: Add module device table
13omap3isp: csi2: Print registers on stream on
14v4l: OMAP3 ISP CCDC: Add support for 8bit greyscale sensors
15omap3isp: ccdc: Set default DC subtract value to 0
16omap3isp: Prefix all public symbols with omap3isp_
17omap3isp: Fix dependencies and mark as experimental
18
19Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
20Signed-off-by: Sakari Ailus <sakari.ailus@nokia.com>
21Signed-off-by: David Cohen <david.cohen@nokia.com>
22Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
23Signed-off-by: Vimarsh Zutshi <vimarsh.zutshi@nokia.com>
24Signed-off-by: Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
25Signed-off-by: Sergio Aguirre <saaguirre@ti.com>
26Signed-off-by: Antti Koskipaa <antti.koskipaa@nokia.com>
27Signed-off-by: Ivan T. Ivanov <iivanov@mm-sol.com>
28Signed-off-by: RaniSuneela <r-m@ti.com>
29Signed-off-by: Atanas Filipov <afilipov@mm-sol.com>
30Signed-off-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com>
31Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
32Signed-off-by: Nayden Kanchev <nkanchev@mm-sol.com>
33Signed-off-by: Phil Carmody <ext-phil.2.carmody@nokia.com>
34Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
35Signed-off-by: Dominic Curran <dcurran@ti.com>
36Signed-off-by: Ilkka Myllyperkio <ilkka.myllyperkio@sofica.fi>
37Signed-off-by: Pallavi Kulkarni <p-kulkarni@ti.com>
38Signed-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
108
109diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
110index 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.
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
133diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
134index 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/
142+
143 obj-$(CONFIG_USB_DABUSB) += dabusb.o
144 obj-$(CONFIG_USB_SE401) += se401.o
145 obj-$(CONFIG_USB_ZR364XX) += zr364xx.o
146diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
147new file mode 100644
148index 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
165diff --git a/drivers/media/video/isp/cfa_coef_table.h b/drivers/media/video/isp/cfa_coef_table.h
166new file mode 100644
167index 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
772diff --git a/drivers/media/video/isp/gamma_table.h b/drivers/media/video/isp/gamma_table.h
773new file mode 100644
774index 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,
868diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
869new file mode 100644
870index 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");
3095diff --git a/drivers/media/video/isp/isp.h b/drivers/media/video/isp/isp.h
3096new file mode 100644
3097index 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+ *
3112+ * This program is free software; you can redistribute it and/or modify
3113+ * it under the terms of the GNU General Public License version 2 as
3114+ * published by the Free Software Foundation.
3115+ *
3116+ * This program is distributed in the hope that it will be useful, but
3117+ * WITHOUT ANY WARRANTY; without even the implied warranty of
3118+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3119+ * General Public License for more details.
3120+ *
3121+ * You should have received a copy of the GNU General Public License
3122+ * along with this program; if not, write to the Free Software
3123+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
3124+ * 02110-1301 USA
3125+ */
3126+
3127+#ifndef OMAP3_ISP_CORE_H
3128+#define OMAP3_ISP_CORE_H
3129+
3130+#include <media/v4l2-device.h>
3131+#include <linux/device.h>
3132+#include <linux/io.h>
3133+#include <linux/platform_device.h>
3134+#include <linux/wait.h>
3135+#include <plat/iommu.h>
3136+#include <plat/iovmm.h>
3137+
3138+#include "ispstat.h"
3139+#include "ispccdc.h"
3140+#include "ispreg.h"
3141+#include "ispresizer.h"
3142+#include "isppreview.h"
3143+#include "ispcsiphy.h"
3144+#include "ispcsi2.h"
3145+#include "ispccp2.h"
3146+
3147+#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
3148+
3149+#define ISP_TOK_TERM 0xFFFFFFFF /*
3150+ * terminating token for ISP
3151+ * modules reg list
3152+ */
3153+#define to_isp_device(ptr_module) \
3154+ container_of(ptr_module, struct isp_device, isp_##ptr_module)
3155+#define to_device(ptr_module) \
3156+ (to_isp_device(ptr_module)->dev)
3157+
3158+enum isp_mem_resources {
3159+ OMAP3_ISP_IOMEM_MAIN,
3160+ OMAP3_ISP_IOMEM_CCP2,
3161+ OMAP3_ISP_IOMEM_CCDC,
3162+ OMAP3_ISP_IOMEM_HIST,
3163+ OMAP3_ISP_IOMEM_H3A,
3164+ OMAP3_ISP_IOMEM_PREV,
3165+ OMAP3_ISP_IOMEM_RESZ,
3166+ OMAP3_ISP_IOMEM_SBL,
3167+ OMAP3_ISP_IOMEM_CSI2A_REGS1,
3168+ OMAP3_ISP_IOMEM_CSIPHY2,
3169+ OMAP3_ISP_IOMEM_CSI2A_REGS2,
3170+ OMAP3_ISP_IOMEM_CSI2C_REGS1,
3171+ OMAP3_ISP_IOMEM_CSIPHY1,
3172+ OMAP3_ISP_IOMEM_CSI2C_REGS2,
3173+ OMAP3_ISP_IOMEM_LAST
3174+};
3175+
3176+enum isp_sbl_resource {
3177+ OMAP3_ISP_SBL_CSI1_READ = 0x1,
3178+ OMAP3_ISP_SBL_CSI1_WRITE = 0x2,
3179+ OMAP3_ISP_SBL_CSI2A_WRITE = 0x4,
3180+ OMAP3_ISP_SBL_CSI2C_WRITE = 0x8,
3181+ OMAP3_ISP_SBL_CCDC_LSC_READ = 0x10,
3182+ OMAP3_ISP_SBL_CCDC_WRITE = 0x20,
3183+ OMAP3_ISP_SBL_PREVIEW_READ = 0x40,
3184+ OMAP3_ISP_SBL_PREVIEW_WRITE = 0x80,
3185+ OMAP3_ISP_SBL_RESIZER_READ = 0x100,
3186+ OMAP3_ISP_SBL_RESIZER_WRITE = 0x200,
3187+};
3188+
3189+enum isp_subclk_resource {
3190+ OMAP3_ISP_SUBCLK_CCDC = (1 << 0),
3191+ OMAP3_ISP_SUBCLK_H3A = (1 << 1),
3192+ OMAP3_ISP_SUBCLK_HIST = (1 << 2),
3193+ OMAP3_ISP_SUBCLK_PREVIEW = (1 << 3),
3194+ OMAP3_ISP_SUBCLK_RESIZER = (1 << 4),
3195+};
3196+
3197+enum isp_interface_type {
3198+ ISP_INTERFACE_PARALLEL,
3199+ ISP_INTERFACE_CSI2A_PHY2,
3200+ ISP_INTERFACE_CCP2B_PHY1,
3201+ ISP_INTERFACE_CCP2B_PHY2,
3202+ ISP_INTERFACE_CSI2C_PHY1,
3203+};
3204+
3205+#define ISP_REVISION_1_0 0x10
3206+#define ISP_REVISION_2_0 0x20
3207+#define ISP_REVISION_15_0 0xF0
3208+
3209+/*
3210+ * struct isp_res_mapping - Map ISP io resources to ISP revision.
3211+ * @isp_rev: ISP_REVISION_x_x
3212+ * @map: bitmap for enum isp_mem_resources
3213+ */
3214+struct isp_res_mapping {
3215+ u32 isp_rev;
3216+ u32 map;
3217+};
3218+
3219+/*
3220+ * struct isp_reg - Structure for ISP register values.
3221+ * @reg: 32-bit Register address.
3222+ * @val: 32-bit Register value.
3223+ */
3224+struct isp_reg {
3225+ enum isp_mem_resources mmio_range;
3226+ u32 reg;
3227+ u32 val;
3228+};
3229+
3230+/**
3231+ * struct isp_parallel_platform_data - Parallel interface platform data
3232+ * @width: Parallel bus width in bits (8, 10, 11 or 12)
3233+ * @data_lane_shift: Data lane shifter
3234+ * 0 - CAMEXT[13:0] -> CAM[13:0]
3235+ * 1 - CAMEXT[13:2] -> CAM[11:0]
3236+ * 2 - CAMEXT[13:4] -> CAM[9:0]
3237+ * 3 - CAMEXT[13:6] -> CAM[7:0]
3238+ * @clk_pol: Pixel clock polarity
3239+ * 0 - Non Inverted, 1 - Inverted
3240+ * @bridge: CCDC Bridge input control
3241+ * ISPCTRL_PAR_BRIDGE_DISABLE - Disable
3242+ * ISPCTRL_PAR_BRIDGE_LENDIAN - Little endian
3243+ * ISPCTRL_PAR_BRIDGE_BENDIAN - Big endian
3244+ */
3245+struct isp_parallel_platform_data {
3246+ unsigned int width;
3247+ unsigned int data_lane_shift:2;
3248+ unsigned int clk_pol:1;
3249+ unsigned int bridge:4;
3250+};
3251+
3252+/**
3253+ * struct isp_ccp2_platform_data - CCP2 interface platform data
3254+ * @strobe_clk_pol: Strobe/clock polarity
3255+ * 0 - Non Inverted, 1 - Inverted
3256+ * @crc: Enable the cyclic redundancy check
3257+ * @ccp2_mode: Enable CCP2 compatibility mode
3258+ * 0 - MIPI-CSI1 mode, 1 - CCP2 mode
3259+ * @phy_layer: Physical layer selection
3260+ * ISPCCP2_CTRL_PHY_SEL_CLOCK - Data/clock physical layer
3261+ * ISPCCP2_CTRL_PHY_SEL_STROBE - Data/strobe physical layer
3262+ * @vpclk_div: Video port output clock control
3263+ */
3264+struct isp_ccp2_platform_data {
3265+ unsigned int strobe_clk_pol:1;
3266+ unsigned int crc:1;
3267+ unsigned int ccp2_mode:1;
3268+ unsigned int phy_layer:1;
3269+ unsigned int vpclk_div:2;
3270+};
3271+
3272+/**
3273+ * struct isp_csi2_platform_data - CSI2 interface platform data
3274+ * @crc: Enable the cyclic redundancy check
3275+ * @vpclk_div: Video port output clock control
3276+ */
3277+struct isp_csi2_platform_data {
3278+ unsigned crc:1;
3279+ unsigned vpclk_div:2;
3280+};
3281+
3282+struct isp_subdev_i2c_board_info {
3283+ struct i2c_board_info *board_info;
3284+ int i2c_adapter_id;
3285+};
3286+
3287+struct isp_v4l2_subdevs_group {
3288+ struct isp_subdev_i2c_board_info *subdevs;
3289+ enum isp_interface_type interface;
3290+ union {
3291+ struct isp_parallel_platform_data parallel;
3292+ struct isp_ccp2_platform_data ccp2;
3293+ struct isp_csi2_platform_data csi2;
3294+ } bus; /* gcc < 4.6.0 chokes on anonymous union initializers */
3295+};
3296+
3297+struct isp_platform_data {
3298+ struct isp_v4l2_subdevs_group *subdevs;
3299+};
3300+
3301+struct isp_platform_callback {
3302+ u32 (*set_xclk)(struct isp_device *isp, u32 xclk, u8 xclksel);
3303+ int (*csiphy_config)(struct isp_csiphy *phy,
3304+ struct isp_csiphy_dphy_cfg *dphy,
3305+ struct isp_csiphy_lanes_cfg *lanes);
3306+ void (*set_pixel_clock)(struct isp_device *isp, unsigned int pixelclk);
3307+};
3308+
3309+/*
3310+ * struct isp_device - ISP device structure.
3311+ * @dev: Device pointer specific to the OMAP3 ISP.
3312+ * @revision: Stores current ISP module revision.
3313+ * @irq_num: Currently used IRQ number.
3314+ * @mmio_base: Array with kernel base addresses for ioremapped ISP register
3315+ * regions.
3316+ * @mmio_base_phys: Array with physical L4 bus addresses for ISP register
3317+ * regions.
3318+ * @mmio_size: Array with ISP register regions size in bytes.
3319+ * @raw_dmamask: Raw DMA mask
3320+ * @stat_lock: Spinlock for handling statistics
3321+ * @isp_mutex: Mutex for serializing requests to ISP.
3322+ * @has_context: Context has been saved at least once and can be restored.
3323+ * @ref_count: Reference count for handling multiple ISP requests.
3324+ * @cam_ick: Pointer to camera interface clock structure.
3325+ * @cam_mclk: Pointer to camera functional clock structure.
3326+ * @dpll4_m5_ck: Pointer to DPLL4 M5 clock structure.
3327+ * @csi2_fck: Pointer to camera CSI2 complexIO clock structure.
3328+ * @l3_ick: Pointer to OMAP3 L3 bus interface clock.
3329+ * @irq: Currently attached ISP ISR callbacks information structure.
3330+ * @isp_af: Pointer to current settings for ISP AutoFocus SCM.
3331+ * @isp_hist: Pointer to current settings for ISP Histogram SCM.
3332+ * @isp_h3a: Pointer to current settings for ISP Auto Exposure and
3333+ * White Balance SCM.
3334+ * @isp_res: Pointer to current settings for ISP Resizer.
3335+ * @isp_prev: Pointer to current settings for ISP Preview.
3336+ * @isp_ccdc: Pointer to current settings for ISP CCDC.
3337+ * @iommu: Pointer to requested IOMMU instance for ISP.
3338+ * @platform_cb: ISP driver callback function pointers for platform code
3339+ *
3340+ * This structure is used to store the OMAP ISP Information.
3341+ */
3342+struct isp_device {
3343+ struct v4l2_device v4l2_dev;
3344+ struct media_device media_dev;
3345+ struct device *dev;
3346+ u32 revision;
3347+
3348+ /* platform HW resources */
3349+ struct isp_platform_data *pdata;
3350+ unsigned int irq_num;
3351+
3352+ void __iomem *mmio_base[OMAP3_ISP_IOMEM_LAST];
3353+ unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_LAST];
3354+ resource_size_t mmio_size[OMAP3_ISP_IOMEM_LAST];
3355+
3356+ u64 raw_dmamask;
3357+
3358+ /* ISP Obj */
3359+ spinlock_t stat_lock; /* common lock for statistic drivers */
3360+ struct mutex isp_mutex; /* For handling ref_count field */
3361+ int has_context;
3362+ int ref_count;
3363+ unsigned int autoidle;
3364+ u32 xclk_divisor[2]; /* Two clocks, a and b. */
3365+#define ISP_CLK_CAM_ICK 0
3366+#define ISP_CLK_CAM_MCLK 1
3367+#define ISP_CLK_DPLL4_M5_CK 2
3368+#define ISP_CLK_CSI2_FCK 3
3369+#define ISP_CLK_L3_ICK 4
3370+ struct clk *clock[5];
3371+
3372+ /* ISP modules */
3373+ struct ispstat isp_af;
3374+ struct ispstat isp_aewb;
3375+ struct ispstat isp_hist;
3376+ struct isp_res_device isp_res;
3377+ struct isp_prev_device isp_prev;
3378+ struct isp_ccdc_device isp_ccdc;
3379+ struct isp_csi2_device isp_csi2a;
3380+ struct isp_csi2_device isp_csi2c;
3381+ struct isp_ccp2_device isp_ccp2;
3382+ struct isp_csiphy isp_csiphy1;
3383+ struct isp_csiphy isp_csiphy2;
3384+
3385+ unsigned int sbl_resources;
3386+ unsigned int subclk_resources;
3387+
3388+ struct iommu *iommu;
3389+
3390+ struct isp_platform_callback platform_cb;
3391+};
3392+
3393+#define v4l2_dev_to_isp_device(dev) \
3394+ container_of(dev, struct isp_device, v4l2_dev)
3395+
3396+void omap3isp_hist_dma_done(struct isp_device *isp);
3397+
3398+void omap3isp_flush(struct isp_device *isp);
3399+
3400+int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
3401+ atomic_t *stopping);
3402+
3403+int omap3isp_module_sync_is_stopping(wait_queue_head_t *wait,
3404+ atomic_t *stopping);
3405+
3406+int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
3407+ enum isp_pipeline_stream_state state);
3408+void omap3isp_configure_bridge(struct isp_device *isp,
3409+ enum ccdc_input_entity input,
3410+ const struct isp_parallel_platform_data *pdata);
3411+
3412+#define ISP_XCLK_NONE -1
3413+#define ISP_XCLK_A 0
3414+#define ISP_XCLK_B 1
3415+
3416+struct isp_device *omap3isp_get(struct isp_device *isp);
3417+void omap3isp_put(struct isp_device *isp);
3418+
3419+void omap3isp_print_status(struct isp_device *isp);
3420+
3421+void omap3isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res);
3422+void omap3isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res);
3423+
3424+void omap3isp_subclk_enable(struct isp_device *isp,
3425+ enum isp_subclk_resource res);
3426+void omap3isp_subclk_disable(struct isp_device *isp,
3427+ enum isp_subclk_resource res);
3428+
3429+int omap3isp_pipeline_pm_use(struct media_entity *entity, int use);
3430+
3431+int omap3isp_register_entities(struct platform_device *pdev,
3432+ struct v4l2_device *v4l2_dev);
3433+void omap3isp_unregister_entities(struct platform_device *pdev);
3434+
3435+/*
3436+ * isp_reg_readl - Read value of an OMAP3 ISP register
3437+ * @dev: Device pointer specific to the OMAP3 ISP.
3438+ * @isp_mmio_range: Range to which the register offset refers to.
3439+ * @reg_offset: Register offset to read from.
3440+ *
3441+ * Returns an unsigned 32 bit value with the required register contents.
3442+ */
3443+static inline
3444+u32 isp_reg_readl(struct isp_device *isp, enum isp_mem_resources isp_mmio_range,
3445+ u32 reg_offset)
3446+{
3447+ return __raw_readl(isp->mmio_base[isp_mmio_range] + reg_offset);
3448+}
3449+
3450+/*
3451+ * isp_reg_writel - Write value to an OMAP3 ISP register
3452+ * @dev: Device pointer specific to the OMAP3 ISP.
3453+ * @reg_value: 32 bit value to write to the register.
3454+ * @isp_mmio_range: Range to which the register offset refers to.
3455+ * @reg_offset: Register offset to write into.
3456+ */
3457+static inline
3458+void isp_reg_writel(struct isp_device *isp, u32 reg_value,
3459+ enum isp_mem_resources isp_mmio_range, u32 reg_offset)
3460+{
3461+ __raw_writel(reg_value, isp->mmio_base[isp_mmio_range] + reg_offset);
3462+}
3463+
3464+/*
3465+ * isp_reg_and - Clear individual bits in an OMAP3 ISP register
3466+ * @dev: Device pointer specific to the OMAP3 ISP.
3467+ * @mmio_range: Range to which the register offset refers to.
3468+ * @reg: Register offset to work on.
3469+ * @clr_bits: 32 bit value which would be cleared in the register.
3470+ */
3471+static inline
3472+void isp_reg_clr(struct isp_device *isp, enum isp_mem_resources mmio_range,
3473+ u32 reg, u32 clr_bits)
3474+{
3475+ u32 v = isp_reg_readl(isp, mmio_range, reg);
3476+
3477+ isp_reg_writel(isp, v & ~clr_bits, mmio_range, reg);
3478+}
3479+
3480+/*
3481+ * isp_reg_set - Set individual bits in an OMAP3 ISP register
3482+ * @dev: Device pointer specific to the OMAP3 ISP.
3483+ * @mmio_range: Range to which the register offset refers to.
3484+ * @reg: Register offset to work on.
3485+ * @set_bits: 32 bit value which would be set in the register.
3486+ */
3487+static inline
3488+void isp_reg_set(struct isp_device *isp, enum isp_mem_resources mmio_range,
3489+ u32 reg, u32 set_bits)
3490+{
3491+ u32 v = isp_reg_readl(isp, mmio_range, reg);
3492+
3493+ isp_reg_writel(isp, v | set_bits, mmio_range, reg);
3494+}
3495+
3496+/*
3497+ * isp_reg_clr_set - Clear and set invidial bits in an OMAP3 ISP register
3498+ * @dev: Device pointer specific to the OMAP3 ISP.
3499+ * @mmio_range: Range to which the register offset refers to.
3500+ * @reg: Register offset to work on.
3501+ * @clr_bits: 32 bit value which would be cleared in the register.
3502+ * @set_bits: 32 bit value which would be set in the register.
3503+ *
3504+ * The clear operation is done first, and then the set operation.
3505+ */
3506+static inline
3507+void isp_reg_clr_set(struct isp_device *isp, enum isp_mem_resources mmio_range,
3508+ u32 reg, u32 clr_bits, u32 set_bits)
3509+{
3510+ u32 v = isp_reg_readl(isp, mmio_range, reg);
3511+
3512+ isp_reg_writel(isp, (v & ~clr_bits) | set_bits, mmio_range, reg);
3513+}
3514+
3515+static inline enum v4l2_buf_type
3516+isp_pad_buffer_type(const struct v4l2_subdev *subdev, int pad)
3517+{
3518+ if (pad >= subdev->entity.num_pads)
3519+ return 0;
3520+
3521+ if (subdev->entity.pads[pad].flags & MEDIA_PAD_FL_INPUT)
3522+ return V4L2_BUF_TYPE_VIDEO_OUTPUT;
3523+ else
3524+ return V4L2_BUF_TYPE_VIDEO_CAPTURE;
3525+}
3526+
3527+#endif /* OMAP3_ISP_CORE_H */
3528diff --git a/drivers/media/video/isp/ispccdc.c b/drivers/media/video/isp/ispccdc.c
3529new file mode 100644
3530index 0000000..cb71e4f
3531--- /dev/null
3532+++ b/drivers/media/video/isp/ispccdc.c
3533@@ -0,0 +1,2280 @@
3534+/*
3535+ * ispccdc.c
3536+ *
3537+ * TI OMAP3 ISP - CCDC module
3538+ *
3539+ * Copyright (C) 2009-2010 Nokia Corporation
3540+ * Copyright (C) 2009 Texas Instruments, Inc.
3541+ *
3542+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3543+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3544+ *
3545+ * This program is free software; you can redistribute it and/or modify
3546+ * it under the terms of the GNU General Public License version 2 as
3547+ * published by the Free Software Foundation.
3548+ *
3549+ * This program is distributed in the hope that it will be useful, but
3550+ * WITHOUT ANY WARRANTY; without even the implied warranty of
3551+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3552+ * General Public License for more details.
3553+ *
3554+ * You should have received a copy of the GNU General Public License
3555+ * along with this program; if not, write to the Free Software
3556+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
3557+ * 02110-1301 USA
3558+ */
3559+
3560+#include <linux/module.h>
3561+#include <linux/uaccess.h>
3562+#include <linux/delay.h>
3563+#include <linux/device.h>
3564+#include <linux/dma-mapping.h>
3565+#include <linux/mm.h>
3566+#include <linux/sched.h>
3567+#include <media/v4l2-ctrls.h>
3568+#include <media/v4l2-event.h>
3569+
3570+#include "isp.h"
3571+#include "ispreg.h"
3572+#include "ispccdc.h"
3573+
3574+static struct v4l2_mbus_framefmt *
3575+__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
3576+ unsigned int pad, enum v4l2_subdev_format_whence which);
3577+
3578+static const unsigned int ccdc_fmts[] = {
3579+ V4L2_MBUS_FMT_Y8_1X8,
3580+ V4L2_MBUS_FMT_SGRBG10_1X10,
3581+ V4L2_MBUS_FMT_SRGGB10_1X10,
3582+ V4L2_MBUS_FMT_SBGGR10_1X10,
3583+ V4L2_MBUS_FMT_SGBRG10_1X10,
3584+ V4L2_MBUS_FMT_SGRBG12_1X12,
3585+ V4L2_MBUS_FMT_SRGGB12_1X12,
3586+ V4L2_MBUS_FMT_SBGGR12_1X12,
3587+ V4L2_MBUS_FMT_SGBRG12_1X12,
3588+};
3589+
3590+/*
3591+ * ccdc_print_status - Print current CCDC Module register values.
3592+ * @ccdc: Pointer to ISP CCDC device.
3593+ *
3594+ * Also prints other debug information stored in the CCDC module.
3595+ */
3596+#define CCDC_PRINT_REGISTER(isp, name)\
3597+ dev_dbg(isp->dev, "###CCDC " #name "=0x%08x\n", \
3598+ isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_##name))
3599+
3600+static void ccdc_print_status(struct isp_ccdc_device *ccdc)
3601+{
3602+ struct isp_device *isp = to_isp_device(ccdc);
3603+
3604+ dev_dbg(isp->dev, "-------------CCDC Register dump-------------\n");
3605+
3606+ CCDC_PRINT_REGISTER(isp, PCR);
3607+ CCDC_PRINT_REGISTER(isp, SYN_MODE);
3608+ CCDC_PRINT_REGISTER(isp, HD_VD_WID);
3609+ CCDC_PRINT_REGISTER(isp, PIX_LINES);
3610+ CCDC_PRINT_REGISTER(isp, HORZ_INFO);
3611+ CCDC_PRINT_REGISTER(isp, VERT_START);
3612+ CCDC_PRINT_REGISTER(isp, VERT_LINES);
3613+ CCDC_PRINT_REGISTER(isp, CULLING);
3614+ CCDC_PRINT_REGISTER(isp, HSIZE_OFF);
3615+ CCDC_PRINT_REGISTER(isp, SDOFST);
3616+ CCDC_PRINT_REGISTER(isp, SDR_ADDR);
3617+ CCDC_PRINT_REGISTER(isp, CLAMP);
3618+ CCDC_PRINT_REGISTER(isp, DCSUB);
3619+ CCDC_PRINT_REGISTER(isp, COLPTN);
3620+ CCDC_PRINT_REGISTER(isp, BLKCMP);
3621+ CCDC_PRINT_REGISTER(isp, FPC);
3622+ CCDC_PRINT_REGISTER(isp, FPC_ADDR);
3623+ CCDC_PRINT_REGISTER(isp, VDINT);
3624+ CCDC_PRINT_REGISTER(isp, ALAW);
3625+ CCDC_PRINT_REGISTER(isp, REC656IF);
3626+ CCDC_PRINT_REGISTER(isp, CFG);
3627+ CCDC_PRINT_REGISTER(isp, FMTCFG);
3628+ CCDC_PRINT_REGISTER(isp, FMT_HORZ);
3629+ CCDC_PRINT_REGISTER(isp, FMT_VERT);
3630+ CCDC_PRINT_REGISTER(isp, PRGEVEN0);
3631+ CCDC_PRINT_REGISTER(isp, PRGEVEN1);
3632+ CCDC_PRINT_REGISTER(isp, PRGODD0);
3633+ CCDC_PRINT_REGISTER(isp, PRGODD1);
3634+ CCDC_PRINT_REGISTER(isp, VP_OUT);
3635+ CCDC_PRINT_REGISTER(isp, LSC_CONFIG);
3636+ CCDC_PRINT_REGISTER(isp, LSC_INITIAL);
3637+ CCDC_PRINT_REGISTER(isp, LSC_TABLE_BASE);
3638+ CCDC_PRINT_REGISTER(isp, LSC_TABLE_OFFSET);
3639+
3640+ dev_dbg(isp->dev, "--------------------------------------------\n");
3641+}
3642+
3643+/*
3644+ * omap3isp_ccdc_busy - Get busy state of the CCDC.
3645+ * @ccdc: Pointer to ISP CCDC device.
3646+ */
3647+int omap3isp_ccdc_busy(struct isp_ccdc_device *ccdc)
3648+{
3649+ struct isp_device *isp = to_isp_device(ccdc);
3650+
3651+ return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
3652+ ISPCCDC_PCR_BUSY;
3653+}
3654+
3655+/* -----------------------------------------------------------------------------
3656+ * Lens Shading Compensation
3657+ */
3658+
3659+/*
3660+ * ccdc_lsc_validate_config - Check that LSC configuration is valid.
3661+ * @ccdc: Pointer to ISP CCDC device.
3662+ * @lsc_cfg: the LSC configuration to check.
3663+ *
3664+ * Returns 0 if the LSC configuration is valid, or -EINVAL if invalid.
3665+ */
3666+static int ccdc_lsc_validate_config(struct isp_ccdc_device *ccdc,
3667+ struct omap3isp_ccdc_lsc_config *lsc_cfg)
3668+{
3669+ struct isp_device *isp = to_isp_device(ccdc);
3670+ struct v4l2_mbus_framefmt *format;
3671+ unsigned int paxel_width, paxel_height;
3672+ unsigned int paxel_shift_x, paxel_shift_y;
3673+ unsigned int min_width, min_height, min_size;
3674+ unsigned int input_width, input_height;
3675+
3676+ paxel_shift_x = lsc_cfg->gain_mode_m;
3677+ paxel_shift_y = lsc_cfg->gain_mode_n;
3678+
3679+ if ((paxel_shift_x < 2) || (paxel_shift_x > 6) ||
3680+ (paxel_shift_y < 2) || (paxel_shift_y > 6)) {
3681+ dev_dbg(isp->dev, "CCDC: LSC: Invalid paxel size\n");
3682+ return -EINVAL;
3683+ }
3684+
3685+ if (lsc_cfg->offset & 3) {
3686+ dev_dbg(isp->dev, "CCDC: LSC: Offset must be a multiple of "
3687+ "4\n");
3688+ return -EINVAL;
3689+ }
3690+
3691+ if ((lsc_cfg->initial_x & 1) || (lsc_cfg->initial_y & 1)) {
3692+ dev_dbg(isp->dev, "CCDC: LSC: initial_x and y must be even\n");
3693+ return -EINVAL;
3694+ }
3695+
3696+ format = __ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
3697+ V4L2_SUBDEV_FORMAT_ACTIVE);
3698+ input_width = format->width;
3699+ input_height = format->height;
3700+
3701+ /* Calculate minimum bytesize for validation */
3702+ paxel_width = 1 << paxel_shift_x;
3703+ min_width = ((input_width + lsc_cfg->initial_x + paxel_width - 1)
3704+ >> paxel_shift_x) + 1;
3705+
3706+ paxel_height = 1 << paxel_shift_y;
3707+ min_height = ((input_height + lsc_cfg->initial_y + paxel_height - 1)
3708+ >> paxel_shift_y) + 1;
3709+
3710+ min_size = 4 * min_width * min_height;
3711+ if (min_size > lsc_cfg->size) {
3712+ dev_dbg(isp->dev, "CCDC: LSC: too small table\n");
3713+ return -EINVAL;
3714+ }
3715+ if (lsc_cfg->offset < (min_width * 4)) {
3716+ dev_dbg(isp->dev, "CCDC: LSC: Offset is too small\n");
3717+ return -EINVAL;
3718+ }
3719+ if ((lsc_cfg->size / lsc_cfg->offset) < min_height) {
3720+ dev_dbg(isp->dev, "CCDC: LSC: Wrong size/offset combination\n");
3721+ return -EINVAL;
3722+ }
3723+ return 0;
3724+}
3725+
3726+/*
3727+ * ccdc_lsc_program_table - Program Lens Shading Compensation table address.
3728+ * @ccdc: Pointer to ISP CCDC device.
3729+ */
3730+static void ccdc_lsc_program_table(struct isp_ccdc_device *ccdc, u32 addr)
3731+{
3732+ isp_reg_writel(to_isp_device(ccdc), addr,
3733+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
3734+}
3735+
3736+/*
3737+ * ccdc_lsc_setup_regs - Configures the lens shading compensation module
3738+ * @ccdc: Pointer to ISP CCDC device.
3739+ */
3740+static void ccdc_lsc_setup_regs(struct isp_ccdc_device *ccdc,
3741+ struct omap3isp_ccdc_lsc_config *cfg)
3742+{
3743+ struct isp_device *isp = to_isp_device(ccdc);
3744+ int reg;
3745+
3746+ isp_reg_writel(isp, cfg->offset, OMAP3_ISP_IOMEM_CCDC,
3747+ ISPCCDC_LSC_TABLE_OFFSET);
3748+
3749+ reg = 0;
3750+ reg |= cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT;
3751+ reg |= cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT;
3752+ reg |= cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT;
3753+ isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
3754+
3755+ reg = 0;
3756+ reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
3757+ reg |= cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT;
3758+ reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
3759+ reg |= cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT;
3760+ isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC,
3761+ ISPCCDC_LSC_INITIAL);
3762+}
3763+
3764+static int ccdc_lsc_wait_prefetch(struct isp_ccdc_device *ccdc)
3765+{
3766+ struct isp_device *isp = to_isp_device(ccdc);
3767+ unsigned int wait;
3768+
3769+ isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ,
3770+ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
3771+
3772+ /* timeout 1 ms */
3773+ for (wait = 0; wait < 1000; wait++) {
3774+ if (isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS) &
3775+ IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ) {
3776+ isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ,
3777+ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
3778+ return 0;
3779+ }
3780+
3781+ rmb();
3782+ udelay(1);
3783+ }
3784+
3785+ return -ETIMEDOUT;
3786+}
3787+
3788+/*
3789+ * __ccdc_lsc_enable - Enables/Disables the Lens Shading Compensation module.
3790+ * @ccdc: Pointer to ISP CCDC device.
3791+ * @enable: 0 Disables LSC, 1 Enables LSC.
3792+ */
3793+static int __ccdc_lsc_enable(struct isp_ccdc_device *ccdc, int enable)
3794+{
3795+ struct isp_device *isp = to_isp_device(ccdc);
3796+ const struct v4l2_mbus_framefmt *format =
3797+ __ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
3798+ V4L2_SUBDEV_FORMAT_ACTIVE);
3799+
3800+ if ((format->code != V4L2_MBUS_FMT_SGRBG10_1X10) &&
3801+ (format->code != V4L2_MBUS_FMT_SRGGB10_1X10) &&
3802+ (format->code != V4L2_MBUS_FMT_SBGGR10_1X10) &&
3803+ (format->code != V4L2_MBUS_FMT_SGBRG10_1X10))
3804+ return -EINVAL;
3805+
3806+ if (enable)
3807+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_LSC_READ);
3808+
3809+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG,
3810+ ISPCCDC_LSC_ENABLE, enable ? ISPCCDC_LSC_ENABLE : 0);
3811+
3812+ if (enable) {
3813+ if (ccdc_lsc_wait_prefetch(ccdc) < 0) {
3814+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC,
3815+ ISPCCDC_LSC_CONFIG, ISPCCDC_LSC_ENABLE);
3816+ ccdc->lsc.state = LSC_STATE_STOPPED;
3817+ dev_warn(to_device(ccdc), "LSC prefecth timeout\n");
3818+ return -ETIMEDOUT;
3819+ }
3820+ ccdc->lsc.state = LSC_STATE_RUNNING;
3821+ } else {
3822+ ccdc->lsc.state = LSC_STATE_STOPPING;
3823+ }
3824+
3825+ return 0;
3826+}
3827+
3828+static int ccdc_lsc_busy(struct isp_ccdc_device *ccdc)
3829+{
3830+ struct isp_device *isp = to_isp_device(ccdc);
3831+
3832+ return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG) &
3833+ ISPCCDC_LSC_BUSY;
3834+}
3835+
3836+/* __ccdc_lsc_configure - Apply a new configuration to the LSC engine
3837+ * @ccdc: Pointer to ISP CCDC device
3838+ * @req: New configuration request
3839+ *
3840+ * context: in_interrupt()
3841+ */
3842+static int __ccdc_lsc_configure(struct isp_ccdc_device *ccdc,
3843+ struct ispccdc_lsc_config_req *req)
3844+{
3845+ if (!req->enable)
3846+ return -EINVAL;
3847+
3848+ if (ccdc_lsc_validate_config(ccdc, &req->config) < 0) {
3849+ dev_dbg(to_device(ccdc), "Discard LSC configuration\n");
3850+ return -EINVAL;
3851+ }
3852+
3853+ if (ccdc_lsc_busy(ccdc))
3854+ return -EBUSY;
3855+
3856+ ccdc_lsc_setup_regs(ccdc, &req->config);
3857+ ccdc_lsc_program_table(ccdc, req->table);
3858+ return 0;
3859+}
3860+
3861+/*
3862+ * ccdc_lsc_error_handler - Handle LSC prefetch error scenario.
3863+ * @ccdc: Pointer to ISP CCDC device.
3864+ *
3865+ * Disables LSC, and defers enablement to shadow registers update time.
3866+ */
3867+static void ccdc_lsc_error_handler(struct isp_ccdc_device *ccdc)
3868+{
3869+ struct isp_device *isp = to_isp_device(ccdc);
3870+ /*
3871+ * From OMAP3 TRM: When this event is pending, the module
3872+ * goes into transparent mode (output =input). Normal
3873+ * operation can be resumed at the start of the next frame
3874+ * after:
3875+ * 1) Clearing this event
3876+ * 2) Disabling the LSC module
3877+ * 3) Enabling it
3878+ */
3879+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG,
3880+ ISPCCDC_LSC_ENABLE);
3881+ ccdc->lsc.state = LSC_STATE_STOPPED;
3882+}
3883+
3884+static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc,
3885+ struct ispccdc_lsc_config_req *req)
3886+{
3887+ struct isp_device *isp = to_isp_device(ccdc);
3888+
3889+ if (req == NULL)
3890+ return;
3891+
3892+ if (req->iovm)
3893+ dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
3894+ req->iovm->sgt->nents, DMA_TO_DEVICE);
3895+ if (req->table)
3896+ iommu_vfree(isp->iommu, req->table);
3897+ kfree(req);
3898+}
3899+
3900+static void ccdc_lsc_free_queue(struct isp_ccdc_device *ccdc,
3901+ struct list_head *queue)
3902+{
3903+ struct ispccdc_lsc_config_req *req, *n;
3904+ unsigned long flags;
3905+
3906+ spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
3907+ list_for_each_entry_safe(req, n, queue, list) {
3908+ list_del(&req->list);
3909+ spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
3910+ ccdc_lsc_free_request(ccdc, req);
3911+ spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
3912+ }
3913+ spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
3914+}
3915+
3916+static void ccdc_lsc_free_table_work(struct work_struct *work)
3917+{
3918+ struct isp_ccdc_device *ccdc;
3919+ struct ispccdc_lsc *lsc;
3920+
3921+ lsc = container_of(work, struct ispccdc_lsc, table_work);
3922+ ccdc = container_of(lsc, struct isp_ccdc_device, lsc);
3923+
3924+ ccdc_lsc_free_queue(ccdc, &lsc->free_queue);
3925+}
3926+
3927+/*
3928+ * ccdc_lsc_config - Configure the LSC module from a userspace request
3929+ *
3930+ * Store the request LSC configuration in the LSC engine request pointer. The
3931+ * configuration will be applied to the hardware when the CCDC will be enabled,
3932+ * or at the next LSC interrupt if the CCDC is already running.
3933+ */
3934+static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
3935+ struct omap3isp_ccdc_update_config *config)
3936+{
3937+ struct isp_device *isp = to_isp_device(ccdc);
3938+ struct ispccdc_lsc_config_req *req;
3939+ unsigned long flags;
3940+ void *table;
3941+ u16 update;
3942+ int ret;
3943+
3944+ update = config->update &
3945+ (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC);
3946+ if (!update)
3947+ return 0;
3948+
3949+ if (update != (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC)) {
3950+ dev_dbg(to_device(ccdc), "%s: Both LSC configuration and table "
3951+ "need to be supplied\n", __func__);
3952+ return -EINVAL;
3953+ }
3954+
3955+ req = kzalloc(sizeof(*req), GFP_KERNEL);
3956+ if (req == NULL)
3957+ return -ENOMEM;
3958+
3959+ if (config->flag & OMAP3ISP_CCDC_CONFIG_LSC) {
3960+ if (copy_from_user(&req->config, config->lsc_cfg,
3961+ sizeof(req->config))) {
3962+ ret = -EFAULT;
3963+ goto done;
3964+ }
3965+
3966+ req->enable = 1;
3967+
3968+ req->table = iommu_vmalloc(isp->iommu, 0, req->config.size,
3969+ IOMMU_FLAG);
3970+ if (IS_ERR_VALUE(req->table)) {
3971+ req->table = 0;
3972+ ret = -ENOMEM;
3973+ goto done;
3974+ }
3975+
3976+ req->iovm = find_iovm_area(isp->iommu, req->table);
3977+ if (req->iovm == NULL) {
3978+ ret = -ENOMEM;
3979+ goto done;
3980+ }
3981+
3982+ if (!dma_map_sg(isp->dev, req->iovm->sgt->sgl,
3983+ req->iovm->sgt->nents, DMA_TO_DEVICE)) {
3984+ ret = -ENOMEM;
3985+ req->iovm = NULL;
3986+ goto done;
3987+ }
3988+
3989+ dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl,
3990+ req->iovm->sgt->nents, DMA_TO_DEVICE);
3991+
3992+ table = da_to_va(isp->iommu, req->table);
3993+ if (copy_from_user(table, config->lsc, req->config.size)) {
3994+ ret = -EFAULT;
3995+ goto done;
3996+ }
3997+
3998+ dma_sync_sg_for_device(isp->dev, req->iovm->sgt->sgl,
3999+ req->iovm->sgt->nents, DMA_TO_DEVICE);
4000+ }
4001+
4002+ spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
4003+ if (ccdc->lsc.request) {
4004+ list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue);
4005+ schedule_work(&ccdc->lsc.table_work);
4006+ }
4007+ ccdc->lsc.request = req;
4008+ spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
4009+
4010+ ret = 0;
4011+
4012+done:
4013+ if (ret < 0)
4014+ ccdc_lsc_free_request(ccdc, req);
4015+
4016+ return ret;
4017+}
4018+
4019+static inline int ccdc_lsc_is_configured(struct isp_ccdc_device *ccdc)
4020+{
4021+ unsigned long flags;
4022+
4023+ spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
4024+ if (ccdc->lsc.active) {
4025+ spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
4026+ return 1;
4027+ }
4028+ spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
4029+ return 0;
4030+}
4031+
4032+static int ccdc_lsc_enable(struct isp_ccdc_device *ccdc)
4033+{
4034+ struct ispccdc_lsc *lsc = &ccdc->lsc;
4035+
4036+ if (lsc->state != LSC_STATE_STOPPED)
4037+ return -EINVAL;
4038+
4039+ if (lsc->active) {
4040+ list_add_tail(&lsc->active->list, &lsc->free_queue);
4041+ lsc->active = NULL;
4042+ }
4043+
4044+ if (__ccdc_lsc_configure(ccdc, lsc->request) < 0) {
4045+ omap3isp_sbl_disable(to_isp_device(ccdc),
4046+ OMAP3_ISP_SBL_CCDC_LSC_READ);
4047+ list_add_tail(&lsc->request->list, &lsc->free_queue);
4048+ lsc->request = NULL;
4049+ goto done;
4050+ }
4051+
4052+ lsc->active = lsc->request;
4053+ lsc->request = NULL;
4054+ __ccdc_lsc_enable(ccdc, 1);
4055+
4056+done:
4057+ if (!list_empty(&lsc->free_queue))
4058+ schedule_work(&lsc->table_work);
4059+
4060+ return 0;
4061+}
4062+
4063+/* -----------------------------------------------------------------------------
4064+ * Parameters configuration
4065+ */
4066+
4067+/*
4068+ * ccdc_configure_clamp - Configure optical-black or digital clamping
4069+ * @ccdc: Pointer to ISP CCDC device.
4070+ *
4071+ * The CCDC performs either optical-black or digital clamp. Configure and enable
4072+ * the selected clamp method.
4073+ */
4074+static void ccdc_configure_clamp(struct isp_ccdc_device *ccdc)
4075+{
4076+ struct isp_device *isp = to_isp_device(ccdc);
4077+ u32 clamp;
4078+
4079+ if (ccdc->obclamp) {
4080+ clamp = ccdc->clamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
4081+ clamp |= ccdc->clamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
4082+ clamp |= ccdc->clamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
4083+ clamp |= ccdc->clamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
4084+ isp_reg_writel(isp, clamp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP);
4085+ } else {
4086+ isp_reg_writel(isp, ccdc->clamp.dcsubval,
4087+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB);
4088+ }
4089+
4090+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
4091+ ISPCCDC_CLAMP_CLAMPEN,
4092+ ccdc->obclamp ? ISPCCDC_CLAMP_CLAMPEN : 0);
4093+}
4094+
4095+/*
4096+ * ccdc_configure_fpc - Configure Faulty Pixel Correction
4097+ * @ccdc: Pointer to ISP CCDC device.
4098+ */
4099+static void ccdc_configure_fpc(struct isp_ccdc_device *ccdc)
4100+{
4101+ struct isp_device *isp = to_isp_device(ccdc);
4102+
4103+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, ISPCCDC_FPC_FPCEN);
4104+
4105+ if (!ccdc->fpc_en)
4106+ return;
4107+
4108+ isp_reg_writel(isp, ccdc->fpc.fpcaddr, OMAP3_ISP_IOMEM_CCDC,
4109+ ISPCCDC_FPC_ADDR);
4110+ /* The FPNUM field must be set before enabling FPC. */
4111+ isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
4112+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
4113+ isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT) |
4114+ ISPCCDC_FPC_FPCEN, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
4115+}
4116+
4117+/*
4118+ * ccdc_configure_black_comp - Configure Black Level Compensation.
4119+ * @ccdc: Pointer to ISP CCDC device.
4120+ */
4121+static void ccdc_configure_black_comp(struct isp_ccdc_device *ccdc)
4122+{
4123+ struct isp_device *isp = to_isp_device(ccdc);
4124+ u32 blcomp;
4125+
4126+ blcomp = ccdc->blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
4127+ blcomp |= ccdc->blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
4128+ blcomp |= ccdc->blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
4129+ blcomp |= ccdc->blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
4130+
4131+ isp_reg_writel(isp, blcomp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP);
4132+}
4133+
4134+/*
4135+ * ccdc_configure_lpf - Configure Low-Pass Filter (LPF).
4136+ * @ccdc: Pointer to ISP CCDC device.
4137+ */
4138+static void ccdc_configure_lpf(struct isp_ccdc_device *ccdc)
4139+{
4140+ struct isp_device *isp = to_isp_device(ccdc);
4141+
4142+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
4143+ ISPCCDC_SYN_MODE_LPF,
4144+ ccdc->lpf ? ISPCCDC_SYN_MODE_LPF : 0);
4145+}
4146+
4147+/*
4148+ * ccdc_configure_alaw - Configure A-law compression.
4149+ * @ccdc: Pointer to ISP CCDC device.
4150+ */
4151+static void ccdc_configure_alaw(struct isp_ccdc_device *ccdc)
4152+{
4153+ struct isp_device *isp = to_isp_device(ccdc);
4154+ u32 alaw = 0;
4155+
4156+ switch (ccdc->syncif.datsz) {
4157+ case 8:
4158+ return;
4159+
4160+ case 10:
4161+ alaw = ISPCCDC_ALAW_GWDI_9_0;
4162+ break;
4163+ case 11:
4164+ alaw = ISPCCDC_ALAW_GWDI_10_1;
4165+ break;
4166+ case 12:
4167+ alaw = ISPCCDC_ALAW_GWDI_11_2;
4168+ break;
4169+ case 13:
4170+ alaw = ISPCCDC_ALAW_GWDI_12_3;
4171+ break;
4172+ }
4173+
4174+ if (ccdc->alaw)
4175+ alaw |= ISPCCDC_ALAW_CCDTBL;
4176+
4177+ isp_reg_writel(isp, alaw, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
4178+}
4179+
4180+/*
4181+ * ccdc_config_imgattr - Configure sensor image specific attributes.
4182+ * @ccdc: Pointer to ISP CCDC device.
4183+ * @colptn: Color pattern of the sensor.
4184+ */
4185+static void ccdc_config_imgattr(struct isp_ccdc_device *ccdc, u32 colptn)
4186+{
4187+ struct isp_device *isp = to_isp_device(ccdc);
4188+
4189+ isp_reg_writel(isp, colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
4190+}
4191+
4192+/*
4193+ * ccdc_config - Set CCDC configuration from userspace
4194+ * @ccdc: Pointer to ISP CCDC device.
4195+ * @userspace_add: Structure containing CCDC configuration sent from userspace.
4196+ *
4197+ * Returns 0 if successful, -EINVAL if the pointer to the configuration
4198+ * structure is null, or the copy_from_user function fails to copy user space
4199+ * memory to kernel space memory.
4200+ */
4201+static int ccdc_config(struct isp_ccdc_device *ccdc,
4202+ struct omap3isp_ccdc_update_config *ccdc_struct)
4203+{
4204+ struct isp_device *isp = to_isp_device(ccdc);
4205+ unsigned long flags;
4206+
4207+ spin_lock_irqsave(&ccdc->lock, flags);
4208+ ccdc->shadow_update = 1;
4209+ spin_unlock_irqrestore(&ccdc->lock, flags);
4210+
4211+ if (OMAP3ISP_CCDC_ALAW & ccdc_struct->update) {
4212+ ccdc->alaw = !!(OMAP3ISP_CCDC_ALAW & ccdc_struct->flag);
4213+ ccdc->update |= OMAP3ISP_CCDC_ALAW;
4214+ }
4215+
4216+ if (OMAP3ISP_CCDC_LPF & ccdc_struct->update) {
4217+ ccdc->lpf = !!(OMAP3ISP_CCDC_LPF & ccdc_struct->flag);
4218+ ccdc->update |= OMAP3ISP_CCDC_LPF;
4219+ }
4220+
4221+ if (OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->update) {
4222+ if (copy_from_user(&ccdc->clamp, ccdc_struct->bclamp,
4223+ sizeof(ccdc->clamp))) {
4224+ ccdc->shadow_update = 0;
4225+ return -EFAULT;
4226+ }
4227+
4228+ ccdc->obclamp = !!(OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->flag);
4229+ ccdc->update |= OMAP3ISP_CCDC_BLCLAMP;
4230+ }
4231+
4232+ if (OMAP3ISP_CCDC_BCOMP & ccdc_struct->update) {
4233+ if (copy_from_user(&ccdc->blcomp, ccdc_struct->blcomp,
4234+ sizeof(ccdc->blcomp))) {
4235+ ccdc->shadow_update = 0;
4236+ return -EFAULT;
4237+ }
4238+
4239+ ccdc->update |= OMAP3ISP_CCDC_BCOMP;
4240+ }
4241+
4242+ ccdc->shadow_update = 0;
4243+
4244+ if (OMAP3ISP_CCDC_FPC & ccdc_struct->update) {
4245+ u32 table_old = 0;
4246+ u32 table_new;
4247+ u32 size;
4248+
4249+ if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED)
4250+ return -EBUSY;
4251+
4252+ ccdc->fpc_en = !!(OMAP3ISP_CCDC_FPC & ccdc_struct->flag);
4253+
4254+ if (ccdc->fpc_en) {
4255+ if (copy_from_user(&ccdc->fpc, ccdc_struct->fpc,
4256+ sizeof(ccdc->fpc)))
4257+ return -EFAULT;
4258+
4259+ /*
4260+ * table_new must be 64-bytes aligned, but it's
4261+ * already done by iommu_vmalloc().
4262+ */
4263+ size = ccdc->fpc.fpnum * 4;
4264+ table_new = iommu_vmalloc(isp->iommu, 0, size,
4265+ IOMMU_FLAG);
4266+ if (IS_ERR_VALUE(table_new))
4267+ return -ENOMEM;
4268+
4269+ if (copy_from_user(da_to_va(isp->iommu, table_new),
4270+ (__force void __user *)
4271+ ccdc->fpc.fpcaddr, size)) {
4272+ iommu_vfree(isp->iommu, table_new);
4273+ return -EFAULT;
4274+ }
4275+
4276+ table_old = ccdc->fpc.fpcaddr;
4277+ ccdc->fpc.fpcaddr = table_new;
4278+ }
4279+
4280+ ccdc_configure_fpc(ccdc);
4281+ if (table_old != 0)
4282+ iommu_vfree(isp->iommu, table_old);
4283+ }
4284+
4285+ return ccdc_lsc_config(ccdc, ccdc_struct);
4286+}
4287+
4288+static void ccdc_apply_controls(struct isp_ccdc_device *ccdc)
4289+{
4290+ if (ccdc->update & OMAP3ISP_CCDC_ALAW) {
4291+ ccdc_configure_alaw(ccdc);
4292+ ccdc->update &= ~OMAP3ISP_CCDC_ALAW;
4293+ }
4294+
4295+ if (ccdc->update & OMAP3ISP_CCDC_LPF) {
4296+ ccdc_configure_lpf(ccdc);
4297+ ccdc->update &= ~OMAP3ISP_CCDC_LPF;
4298+ }
4299+
4300+ if (ccdc->update & OMAP3ISP_CCDC_BLCLAMP) {
4301+ ccdc_configure_clamp(ccdc);
4302+ ccdc->update &= ~OMAP3ISP_CCDC_BLCLAMP;
4303+ }
4304+
4305+ if (ccdc->update & OMAP3ISP_CCDC_BCOMP) {
4306+ ccdc_configure_black_comp(ccdc);
4307+ ccdc->update &= ~OMAP3ISP_CCDC_BCOMP;
4308+ }
4309+}
4310+
4311+/*
4312+ * omap3isp_ccdc_restore_context - Restore values of the CCDC module registers
4313+ * @dev: Pointer to ISP device
4314+ */
4315+void omap3isp_ccdc_restore_context(struct isp_device *isp)
4316+{
4317+ struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
4318+
4319+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC);
4320+
4321+ ccdc->update = OMAP3ISP_CCDC_ALAW | OMAP3ISP_CCDC_LPF
4322+ | OMAP3ISP_CCDC_BLCLAMP | OMAP3ISP_CCDC_BCOMP;
4323+ ccdc_apply_controls(ccdc);
4324+ ccdc_configure_fpc(ccdc);
4325+}
4326+
4327+/* -----------------------------------------------------------------------------
4328+ * Format- and pipeline-related configuration helpers
4329+ */
4330+
4331+/*
4332+ * ccdc_config_vp - Configure the Video Port.
4333+ * @ccdc: Pointer to ISP CCDC device.
4334+ */
4335+static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
4336+{
4337+ struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
4338+ struct isp_device *isp = to_isp_device(ccdc);
4339+ unsigned long l3_ick = pipe->l3_ick;
4340+ unsigned int max_div = isp->revision == ISP_REVISION_15_0 ? 64 : 8;
4341+ unsigned int div = 0;
4342+ u32 fmtcfg_vp;
4343+
4344+ fmtcfg_vp = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG)
4345+ & ~(ISPCCDC_FMTCFG_VPIN_MASK | ISPCCDC_FMTCFG_VPIF_FRQ_MASK);
4346+
4347+ switch (ccdc->syncif.datsz) {
4348+ case 8:
4349+ case 10:
4350+ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
4351+ break;
4352+ case 11:
4353+ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
4354+ break;
4355+ case 12:
4356+ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
4357+ break;
4358+ case 13:
4359+ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
4360+ break;
4361+ };
4362+
4363+ if (pipe->input)
4364+ div = DIV_ROUND_UP(l3_ick, pipe->max_rate);
4365+ else if (ccdc->vpcfg.pixelclk)
4366+ div = l3_ick / ccdc->vpcfg.pixelclk;
4367+
4368+ div = clamp(div, 2U, max_div);
4369+ fmtcfg_vp |= (div - 2) << ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT;
4370+
4371+ isp_reg_writel(isp, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
4372+}
4373+
4374+/*
4375+ * ccdc_enable_vp - Enable Video Port.
4376+ * @ccdc: Pointer to ISP CCDC device.
4377+ * @enable: 0 Disables VP, 1 Enables VP
4378+ *
4379+ * This is needed for outputting image to Preview, H3A and HIST ISP submodules.
4380+ */
4381+static void ccdc_enable_vp(struct isp_ccdc_device *ccdc, u8 enable)
4382+{
4383+ struct isp_device *isp = to_isp_device(ccdc);
4384+
4385+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
4386+ ISPCCDC_FMTCFG_VPEN, enable ? ISPCCDC_FMTCFG_VPEN : 0);
4387+}
4388+
4389+/*
4390+ * ccdc_config_outlineoffset - Configure memory saving output line offset
4391+ * @ccdc: Pointer to ISP CCDC device.
4392+ * @offset: Address offset to start a new line. Must be twice the
4393+ * Output width and aligned on 32 byte boundary
4394+ * @oddeven: Specifies the odd/even line pattern to be chosen to store the
4395+ * output.
4396+ * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
4397+ *
4398+ * - Configures the output line offset when stored in memory
4399+ * - Sets the odd/even line pattern to store the output
4400+ * (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
4401+ * - Configures the number of even and odd line fields in case of rearranging
4402+ * the lines.
4403+ */
4404+static void ccdc_config_outlineoffset(struct isp_ccdc_device *ccdc,
4405+ u32 offset, u8 oddeven, u8 numlines)
4406+{
4407+ struct isp_device *isp = to_isp_device(ccdc);
4408+
4409+ isp_reg_writel(isp, offset & 0xffff,
4410+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF);
4411+
4412+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
4413+ ISPCCDC_SDOFST_FINV);
4414+
4415+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
4416+ ISPCCDC_SDOFST_FOFST_4L);
4417+
4418+ switch (oddeven) {
4419+ case EVENEVEN:
4420+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
4421+ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
4422+ break;
4423+ case ODDEVEN:
4424+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
4425+ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
4426+ break;
4427+ case EVENODD:
4428+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
4429+ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
4430+ break;
4431+ case ODDODD:
4432+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
4433+ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
4434+ break;
4435+ default:
4436+ break;
4437+ }
4438+}
4439+
4440+/*
4441+ * ccdc_set_outaddr - Set memory address to save output image
4442+ * @ccdc: Pointer to ISP CCDC device.
4443+ * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
4444+ *
4445+ * Sets the memory address where the output will be saved.
4446+ */
4447+static void ccdc_set_outaddr(struct isp_ccdc_device *ccdc, u32 addr)
4448+{
4449+ struct isp_device *isp = to_isp_device(ccdc);
4450+
4451+ isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR);
4452+}
4453+
4454+/*
4455+ * omap3isp_ccdc_max_rate - Calculate maximum input data rate based on the input
4456+ * @ccdc: Pointer to ISP CCDC device.
4457+ * @max_rate: Maximum calculated data rate.
4458+ *
4459+ * Returns in *max_rate less value between calculated and passed
4460+ */
4461+void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
4462+ unsigned int *max_rate)
4463+{
4464+ struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
4465+ unsigned int rate;
4466+
4467+ if (pipe == NULL)
4468+ return;
4469+
4470+ /*
4471+ * TRM says that for parallel sensors the maximum data rate
4472+ * should be 90% form L3/2 clock, otherwise just L3/2.
4473+ */
4474+ if (ccdc->input == CCDC_INPUT_PARALLEL)
4475+ rate = pipe->l3_ick / 2 * 9 / 10;
4476+ else
4477+ rate = pipe->l3_ick / 2;
4478+
4479+ *max_rate = min(*max_rate, rate);
4480+}
4481+
4482+/*
4483+ * ccdc_config_sync_if - Set CCDC sync interface configuration
4484+ * @ccdc: Pointer to ISP CCDC device.
4485+ * @syncif: Structure containing the sync parameters like field state, CCDC in
4486+ * master/slave mode, raw/yuv data, polarity of data, field, hs, vs
4487+ * signals.
4488+ */
4489+static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
4490+ struct ispccdc_syncif *syncif)
4491+{
4492+ struct isp_device *isp = to_isp_device(ccdc);
4493+ u32 syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC,
4494+ ISPCCDC_SYN_MODE);
4495+
4496+ syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
4497+
4498+ if (syncif->fldstat)
4499+ syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
4500+ else
4501+ syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
4502+
4503+ syn_mode &= ~ISPCCDC_SYN_MODE_DATSIZ_MASK;
4504+ switch (syncif->datsz) {
4505+ case 8:
4506+ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
4507+ break;
4508+ case 10:
4509+ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
4510+ break;
4511+ case 11:
4512+ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
4513+ break;
4514+ case 12:
4515+ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
4516+ break;
4517+ };
4518+
4519+ if (syncif->fldmode)
4520+ syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
4521+ else
4522+ syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
4523+
4524+ if (syncif->datapol)
4525+ syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
4526+ else
4527+ syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
4528+
4529+ if (syncif->fldpol)
4530+ syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
4531+ else
4532+ syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
4533+
4534+ if (syncif->hdpol)
4535+ syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
4536+ else
4537+ syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
4538+
4539+ if (syncif->vdpol)
4540+ syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
4541+ else
4542+ syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
4543+
4544+ if (syncif->ccdc_mastermode) {
4545+ syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
4546+ isp_reg_writel(isp,
4547+ syncif->hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT
4548+ | syncif->vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT,
4549+ OMAP3_ISP_IOMEM_CCDC,
4550+ ISPCCDC_HD_VD_WID);
4551+
4552+ isp_reg_writel(isp,
4553+ syncif->ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
4554+ | syncif->hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
4555+ OMAP3_ISP_IOMEM_CCDC,
4556+ ISPCCDC_PIX_LINES);
4557+ } else
4558+ syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
4559+ ISPCCDC_SYN_MODE_VDHDOUT);
4560+
4561+ isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
4562+
4563+ if (!syncif->bt_r656_en)
4564+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
4565+ ISPCCDC_REC656IF_R656ON);
4566+}
4567+
4568+/* CCDC formats descriptions */
4569+static const u32 ccdc_sgrbg_pattern =
4570+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
4571+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
4572+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
4573+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
4574+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
4575+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
4576+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
4577+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
4578+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
4579+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
4580+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
4581+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
4582+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
4583+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
4584+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
4585+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
4586+
4587+static const u32 ccdc_srggb_pattern =
4588+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
4589+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
4590+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
4591+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
4592+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
4593+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
4594+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
4595+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
4596+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
4597+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
4598+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
4599+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
4600+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
4601+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
4602+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
4603+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
4604+
4605+static const u32 ccdc_sbggr_pattern =
4606+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
4607+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
4608+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
4609+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
4610+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
4611+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
4612+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
4613+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
4614+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
4615+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
4616+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
4617+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
4618+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
4619+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
4620+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
4621+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
4622+
4623+static const u32 ccdc_sgbrg_pattern =
4624+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
4625+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
4626+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
4627+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
4628+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
4629+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
4630+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
4631+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
4632+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
4633+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
4634+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
4635+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
4636+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
4637+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
4638+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
4639+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
4640+
4641+static void ccdc_configure(struct isp_ccdc_device *ccdc)
4642+{
4643+ struct isp_device *isp = to_isp_device(ccdc);
4644+ struct isp_parallel_platform_data *pdata = NULL;
4645+ struct v4l2_subdev *sensor;
4646+ struct v4l2_mbus_framefmt *format;
4647+ struct media_pad *pad;
4648+ unsigned long flags;
4649+ u32 syn_mode;
4650+ u32 ccdc_pattern;
4651+
4652+ if (ccdc->input == CCDC_INPUT_PARALLEL) {
4653+ pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
4654+ sensor = media_entity_to_v4l2_subdev(pad->entity);
4655+ pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
4656+ ->bus.parallel;
4657+ }
4658+
4659+ omap3isp_configure_bridge(isp, ccdc->input, pdata);
4660+
4661+ ccdc->syncif.datsz = pdata ? pdata->width : 10;
4662+ ccdc_config_sync_if(ccdc, &ccdc->syncif);
4663+
4664+ /* CCDC_PAD_SINK */
4665+ format = &ccdc->formats[CCDC_PAD_SINK];
4666+
4667+ syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
4668+
4669+ /* Use the raw, unprocessed data when writing to memory. The H3A and
4670+ * histogram modules are still fed with lens shading corrected data.
4671+ */
4672+ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
4673+
4674+ if (ccdc->output & CCDC_OUTPUT_MEMORY)
4675+ syn_mode |= ISPCCDC_SYN_MODE_WEN;
4676+ else
4677+ syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
4678+
4679+ if (ccdc->output & CCDC_OUTPUT_RESIZER)
4680+ syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
4681+ else
4682+ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
4683+
4684+ /* Use PACK8 mode for 1byte per pixel formats. */
4685+ if (omap3isp_video_format_info(format->code)->bpp <= 8)
4686+ syn_mode |= ISPCCDC_SYN_MODE_PACK8;
4687+ else
4688+ syn_mode &= ~ISPCCDC_SYN_MODE_PACK8;
4689+
4690+ isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
4691+
4692+ /* Mosaic filter */
4693+ switch (format->code) {
4694+ case V4L2_MBUS_FMT_SRGGB10_1X10:
4695+ case V4L2_MBUS_FMT_SRGGB12_1X12:
4696+ ccdc_pattern = ccdc_srggb_pattern;
4697+ break;
4698+ case V4L2_MBUS_FMT_SBGGR10_1X10:
4699+ case V4L2_MBUS_FMT_SBGGR12_1X12:
4700+ ccdc_pattern = ccdc_sbggr_pattern;
4701+ break;
4702+ case V4L2_MBUS_FMT_SGBRG10_1X10:
4703+ case V4L2_MBUS_FMT_SGBRG12_1X12:
4704+ ccdc_pattern = ccdc_sgbrg_pattern;
4705+ break;
4706+ default:
4707+ /* Use GRBG */
4708+ ccdc_pattern = ccdc_sgrbg_pattern;
4709+ break;
4710+ }
4711+ ccdc_config_imgattr(ccdc, ccdc_pattern);
4712+
4713+ /* Generate VD0 on the last line of the image and VD1 on the
4714+ * 2/3 height line.
4715+ */
4716+ isp_reg_writel(isp, ((format->height - 2) << ISPCCDC_VDINT_0_SHIFT) |
4717+ ((format->height * 2 / 3) << ISPCCDC_VDINT_1_SHIFT),
4718+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT);
4719+
4720+ /* CCDC_PAD_SOURCE_OF */
4721+ format = &ccdc->formats[CCDC_PAD_SOURCE_OF];
4722+
4723+ isp_reg_writel(isp, (0 << ISPCCDC_HORZ_INFO_SPH_SHIFT) |
4724+ ((format->width - 1) << ISPCCDC_HORZ_INFO_NPH_SHIFT),
4725+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO);
4726+ isp_reg_writel(isp, 0 << ISPCCDC_VERT_START_SLV0_SHIFT,
4727+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START);
4728+ isp_reg_writel(isp, (format->height - 1)
4729+ << ISPCCDC_VERT_LINES_NLV_SHIFT,
4730+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES);
4731+
4732+ ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, 0, 0);
4733+
4734+ /* CCDC_PAD_SOURCE_VP */
4735+ format = &ccdc->formats[CCDC_PAD_SOURCE_VP];
4736+
4737+ isp_reg_writel(isp, (0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
4738+ (format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
4739+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ);
4740+ isp_reg_writel(isp, (0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
4741+ ((format->height + 1) << ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
4742+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT);
4743+
4744+ isp_reg_writel(isp, (format->width << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
4745+ (format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
4746+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
4747+
4748+ spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
4749+ if (ccdc->lsc.request == NULL)
4750+ goto unlock;
4751+
4752+ WARN_ON(ccdc->lsc.active);
4753+
4754+ /* Get last good LSC configuration. If it is not supported for
4755+ * the current active resolution discard it.
4756+ */
4757+ if (ccdc->lsc.active == NULL &&
4758+ __ccdc_lsc_configure(ccdc, ccdc->lsc.request) == 0) {
4759+ ccdc->lsc.active = ccdc->lsc.request;
4760+ } else {
4761+ list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue);
4762+ schedule_work(&ccdc->lsc.table_work);
4763+ }
4764+
4765+ ccdc->lsc.request = NULL;
4766+
4767+unlock:
4768+ spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
4769+
4770+ ccdc_apply_controls(ccdc);
4771+}
4772+
4773+static void __ccdc_enable(struct isp_ccdc_device *ccdc, int enable)
4774+{
4775+ struct isp_device *isp = to_isp_device(ccdc);
4776+
4777+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR,
4778+ ISPCCDC_PCR_EN, enable ? ISPCCDC_PCR_EN : 0);
4779+}
4780+
4781+static int ccdc_disable(struct isp_ccdc_device *ccdc)
4782+{
4783+ unsigned long flags;
4784+ int ret = 0;
4785+
4786+ spin_lock_irqsave(&ccdc->lock, flags);
4787+ if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS)
4788+ ccdc->stopping = CCDC_STOP_REQUEST;
4789+ spin_unlock_irqrestore(&ccdc->lock, flags);
4790+
4791+ ret = wait_event_timeout(ccdc->wait,
4792+ ccdc->stopping == CCDC_STOP_FINISHED,
4793+ msecs_to_jiffies(2000));
4794+ if (ret == 0) {
4795+ ret = -ETIMEDOUT;
4796+ dev_warn(to_device(ccdc), "CCDC stop timeout!\n");
4797+ }
4798+
4799+ omap3isp_sbl_disable(to_isp_device(ccdc), OMAP3_ISP_SBL_CCDC_LSC_READ);
4800+
4801+ mutex_lock(&ccdc->ioctl_lock);
4802+ ccdc_lsc_free_request(ccdc, ccdc->lsc.request);
4803+ ccdc->lsc.request = ccdc->lsc.active;
4804+ ccdc->lsc.active = NULL;
4805+ cancel_work_sync(&ccdc->lsc.table_work);
4806+ ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
4807+ mutex_unlock(&ccdc->ioctl_lock);
4808+
4809+ ccdc->stopping = CCDC_STOP_NOT_REQUESTED;
4810+
4811+ return ret > 0 ? 0 : ret;
4812+}
4813+
4814+static void ccdc_enable(struct isp_ccdc_device *ccdc)
4815+{
4816+ if (ccdc_lsc_is_configured(ccdc))
4817+ __ccdc_lsc_enable(ccdc, 1);
4818+ __ccdc_enable(ccdc, 1);
4819+}
4820+
4821+/* -----------------------------------------------------------------------------
4822+ * Interrupt handling
4823+ */
4824+
4825+/*
4826+ * ccdc_sbl_busy - Poll idle state of CCDC and related SBL memory write bits
4827+ * @ccdc: Pointer to ISP CCDC device.
4828+ *
4829+ * Returns zero if the CCDC is idle and the image has been written to
4830+ * memory, too.
4831+ */
4832+static int ccdc_sbl_busy(struct isp_ccdc_device *ccdc)
4833+{
4834+ struct isp_device *isp = to_isp_device(ccdc);
4835+
4836+ return omap3isp_ccdc_busy(ccdc)
4837+ | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) &
4838+ ISPSBL_CCDC_WR_0_DATA_READY)
4839+ | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) &
4840+ ISPSBL_CCDC_WR_0_DATA_READY)
4841+ | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) &
4842+ ISPSBL_CCDC_WR_0_DATA_READY)
4843+ | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) &
4844+ ISPSBL_CCDC_WR_0_DATA_READY);
4845+}
4846+
4847+/*
4848+ * ccdc_sbl_wait_idle - Wait until the CCDC and related SBL are idle
4849+ * @ccdc: Pointer to ISP CCDC device.
4850+ * @max_wait: Max retry count in us for wait for idle/busy transition.
4851+ */
4852+static int ccdc_sbl_wait_idle(struct isp_ccdc_device *ccdc,
4853+ unsigned int max_wait)
4854+{
4855+ unsigned int wait = 0;
4856+
4857+ if (max_wait == 0)
4858+ max_wait = 10000; /* 10 ms */
4859+
4860+ for (wait = 0; wait <= max_wait; wait++) {
4861+ if (!ccdc_sbl_busy(ccdc))
4862+ return 0;
4863+
4864+ rmb();
4865+ udelay(1);
4866+ }
4867+
4868+ return -EBUSY;
4869+}
4870+
4871+/* __ccdc_handle_stopping - Handle CCDC and/or LSC stopping sequence
4872+ * @ccdc: Pointer to ISP CCDC device.
4873+ * @event: Pointing which event trigger handler
4874+ *
4875+ * Return 1 when the event and stopping request combination is satisfyied,
4876+ * zero otherwise.
4877+ */
4878+static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
4879+{
4880+ int rval = 0;
4881+
4882+ switch ((ccdc->stopping & 3) | event) {
4883+ case CCDC_STOP_REQUEST | CCDC_EVENT_VD1:
4884+ if (ccdc->lsc.state != LSC_STATE_STOPPED)
4885+ __ccdc_lsc_enable(ccdc, 0);
4886+ __ccdc_enable(ccdc, 0);
4887+ ccdc->stopping = CCDC_STOP_EXECUTED;
4888+ return 1;
4889+
4890+ case CCDC_STOP_EXECUTED | CCDC_EVENT_VD0:
4891+ ccdc->stopping |= CCDC_STOP_CCDC_FINISHED;
4892+ if (ccdc->lsc.state == LSC_STATE_STOPPED)
4893+ ccdc->stopping |= CCDC_STOP_LSC_FINISHED;
4894+ rval = 1;
4895+ break;
4896+
4897+ case CCDC_STOP_EXECUTED | CCDC_EVENT_LSC_DONE:
4898+ ccdc->stopping |= CCDC_STOP_LSC_FINISHED;
4899+ rval = 1;
4900+ break;
4901+
4902+ case CCDC_STOP_EXECUTED | CCDC_EVENT_VD1:
4903+ return 1;
4904+ }
4905+
4906+ if (ccdc->stopping == CCDC_STOP_FINISHED) {
4907+ wake_up(&ccdc->wait);
4908+ rval = 1;
4909+ }
4910+
4911+ return rval;
4912+}
4913+
4914+static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
4915+{
4916+ struct video_device *vdev = &ccdc->subdev.devnode;
4917+ struct v4l2_event event;
4918+
4919+ memset(&event, 0, sizeof(event));
4920+ event.type = V4L2_EVENT_OMAP3ISP_HS_VS;
4921+
4922+ v4l2_event_queue(vdev, &event);
4923+}
4924+
4925+/*
4926+ * ccdc_lsc_isr - Handle LSC events
4927+ * @ccdc: Pointer to ISP CCDC device.
4928+ * @events: LSC events
4929+ */
4930+static void ccdc_lsc_isr(struct isp_ccdc_device *ccdc, u32 events)
4931+{
4932+ unsigned long flags;
4933+
4934+ if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) {
4935+ ccdc_lsc_error_handler(ccdc);
4936+ ccdc->error = 1;
4937+ dev_dbg(to_device(ccdc), "lsc prefetch error\n");
4938+ }
4939+
4940+ if (!(events & IRQ0STATUS_CCDC_LSC_DONE_IRQ))
4941+ return;
4942+
4943+ /* LSC_DONE interrupt occur, there are two cases
4944+ * 1. stopping for reconfiguration
4945+ * 2. stopping because of STREAM OFF command
4946+ */
4947+ spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
4948+
4949+ if (ccdc->lsc.state == LSC_STATE_STOPPING)
4950+ ccdc->lsc.state = LSC_STATE_STOPPED;
4951+
4952+ if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_LSC_DONE))
4953+ goto done;
4954+
4955+ if (ccdc->lsc.state != LSC_STATE_RECONFIG)
4956+ goto done;
4957+
4958+ /* LSC is in STOPPING state, change to the new state */
4959+ ccdc->lsc.state = LSC_STATE_STOPPED;
4960+
4961+ /* This is an exception. Start of frame and LSC_DONE interrupt
4962+ * have been received on the same time. Skip this event and wait
4963+ * for better times.
4964+ */
4965+ if (events & IRQ0STATUS_HS_VS_IRQ)
4966+ goto done;
4967+
4968+ /* The LSC engine is stopped at this point. Enable it if there's a
4969+ * pending request.
4970+ */
4971+ if (ccdc->lsc.request == NULL)
4972+ goto done;
4973+
4974+ ccdc_lsc_enable(ccdc);
4975+
4976+done:
4977+ spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
4978+}
4979+
4980+static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
4981+{
4982+ struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
4983+ struct isp_device *isp = to_isp_device(ccdc);
4984+ struct isp_buffer *buffer;
4985+ int restart = 0;
4986+
4987+ /* The CCDC generates VD0 interrupts even when disabled (the datasheet
4988+ * doesn't explicitly state if that's supposed to happen or not, so it
4989+ * can be considered as a hardware bug or as a feature, but we have to
4990+ * deal with it anyway). Disabling the CCDC when no buffer is available
4991+ * would thus not be enough, we need to handle the situation explicitly.
4992+ */
4993+ if (list_empty(&ccdc->video_out.dmaqueue))
4994+ goto done;
4995+
4996+ /* We're in continuous mode, and memory writes were disabled due to a
4997+ * buffer underrun. Reenable them now that we have a buffer. The buffer
4998+ * address has been set in ccdc_video_queue.
4999+ */
5000+ if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && ccdc->underrun) {
5001+ restart = 1;
5002+ ccdc->underrun = 0;
5003+ goto done;
5004+ }
5005+
5006+ if (ccdc_sbl_wait_idle(ccdc, 1000)) {
5007+ dev_info(isp->dev, "CCDC won't become idle!\n");
5008+ goto done;
5009+ }
5010+
5011+ buffer = omap3isp_video_buffer_next(&ccdc->video_out, ccdc->error);
5012+ if (buffer != NULL) {
5013+ ccdc_set_outaddr(ccdc, buffer->isp_addr);
5014+ restart = 1;
5015+ }
5016+
5017+ pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
5018+
5019+ if (ccdc->state == ISP_PIPELINE_STREAM_SINGLESHOT &&
5020+ isp_pipeline_ready(pipe))
5021+ omap3isp_pipeline_set_stream(pipe,
5022+ ISP_PIPELINE_STREAM_SINGLESHOT);
5023+
5024+done:
5025+ ccdc->error = 0;
5026+ return restart;
5027+}
5028+
5029+/*
5030+ * ccdc_vd0_isr - Handle VD0 event
5031+ * @ccdc: Pointer to ISP CCDC device.
5032+ *
5033+ * Executes LSC deferred enablement before next frame starts.
5034+ */
5035+static void ccdc_vd0_isr(struct isp_ccdc_device *ccdc)
5036+{
5037+ unsigned long flags;
5038+ int restart = 0;
5039+
5040+ if (ccdc->output & CCDC_OUTPUT_MEMORY)
5041+ restart = ccdc_isr_buffer(ccdc);
5042+
5043+ spin_lock_irqsave(&ccdc->lock, flags);
5044+ if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD0)) {
5045+ spin_unlock_irqrestore(&ccdc->lock, flags);
5046+ return;
5047+ }
5048+
5049+ if (!ccdc->shadow_update)
5050+ ccdc_apply_controls(ccdc);
5051+ spin_unlock_irqrestore(&ccdc->lock, flags);
5052+
5053+ if (restart)
5054+ ccdc_enable(ccdc);
5055+}
5056+
5057+/*
5058+ * ccdc_vd1_isr - Handle VD1 event
5059+ * @ccdc: Pointer to ISP CCDC device.
5060+ */
5061+static void ccdc_vd1_isr(struct isp_ccdc_device *ccdc)
5062+{
5063+ unsigned long flags;
5064+
5065+ spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
5066+
5067+ /*
5068+ * Depending on the CCDC pipeline state, CCDC stopping should be
5069+ * handled differently. In SINGLESHOT we emulate an internal CCDC
5070+ * stopping because the CCDC hw works only in continuous mode.
5071+ * When CONTINUOUS pipeline state is used and the CCDC writes it's
5072+ * data to memory the CCDC and LSC are stopped immediately but
5073+ * without change the CCDC stopping state machine. The CCDC
5074+ * stopping state machine should be used only when user request
5075+ * for stopping is received (SINGLESHOT is an exeption).
5076+ */
5077+ switch (ccdc->state) {
5078+ case ISP_PIPELINE_STREAM_SINGLESHOT:
5079+ ccdc->stopping = CCDC_STOP_REQUEST;
5080+ break;
5081+
5082+ case ISP_PIPELINE_STREAM_CONTINUOUS:
5083+ if (ccdc->output & CCDC_OUTPUT_MEMORY) {
5084+ if (ccdc->lsc.state != LSC_STATE_STOPPED)
5085+ __ccdc_lsc_enable(ccdc, 0);
5086+ __ccdc_enable(ccdc, 0);
5087+ }
5088+ break;
5089+
5090+ case ISP_PIPELINE_STREAM_STOPPED:
5091+ break;
5092+ }
5093+
5094+ if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD1))
5095+ goto done;
5096+
5097+ if (ccdc->lsc.request == NULL)
5098+ goto done;
5099+
5100+ /*
5101+ * LSC need to be reconfigured. Stop it here and on next LSC_DONE IRQ
5102+ * do the appropriate changes in registers
5103+ */
5104+ if (ccdc->lsc.state == LSC_STATE_RUNNING) {
5105+ __ccdc_lsc_enable(ccdc, 0);
5106+ ccdc->lsc.state = LSC_STATE_RECONFIG;
5107+ goto done;
5108+ }
5109+
5110+ /* LSC has been in STOPPED state, enable it */
5111+ if (ccdc->lsc.state == LSC_STATE_STOPPED)
5112+ ccdc_lsc_enable(ccdc);
5113+
5114+done:
5115+ spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
5116+}
5117+
5118+/*
5119+ * omap3isp_ccdc_isr - Configure CCDC during interframe time.
5120+ * @ccdc: Pointer to ISP CCDC device.
5121+ * @events: CCDC events
5122+ */
5123+int omap3isp_ccdc_isr(struct isp_ccdc_device *ccdc, u32 events)
5124+{
5125+ if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED)
5126+ return 0;
5127+
5128+ if (events & IRQ0STATUS_CCDC_VD1_IRQ)
5129+ ccdc_vd1_isr(ccdc);
5130+
5131+ ccdc_lsc_isr(ccdc, events);
5132+
5133+ if (events & IRQ0STATUS_CCDC_VD0_IRQ)
5134+ ccdc_vd0_isr(ccdc);
5135+
5136+ if (events & IRQ0STATUS_HS_VS_IRQ)
5137+ ccdc_hs_vs_isr(ccdc);
5138+
5139+ return 0;
5140+}
5141+
5142+/* -----------------------------------------------------------------------------
5143+ * ISP video operations
5144+ */
5145+
5146+static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
5147+{
5148+ struct isp_ccdc_device *ccdc = &video->isp->isp_ccdc;
5149+
5150+ if (!(ccdc->output & CCDC_OUTPUT_MEMORY))
5151+ return -ENODEV;
5152+
5153+ ccdc_set_outaddr(ccdc, buffer->isp_addr);
5154+
5155+ /* We now have a buffer queued on the output, restart the pipeline in
5156+ * on the next CCDC interrupt if running in continuous mode (or when
5157+ * starting the stream).
5158+ */
5159+ ccdc->underrun = 1;
5160+
5161+ return 0;
5162+}
5163+
5164+static const struct isp_video_operations ccdc_video_ops = {
5165+ .queue = ccdc_video_queue,
5166+};
5167+
5168+/* -----------------------------------------------------------------------------
5169+ * V4L2 subdev operations
5170+ */
5171+
5172+/*
5173+ * ccdc_ioctl - CCDC module private ioctl's
5174+ * @sd: ISP CCDC V4L2 subdevice
5175+ * @cmd: ioctl command
5176+ * @arg: ioctl argument
5177+ *
5178+ * Return 0 on success or a negative error code otherwise.
5179+ */
5180+static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
5181+{
5182+ struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
5183+ int ret;
5184+
5185+ switch (cmd) {
5186+ case VIDIOC_OMAP3ISP_CCDC_CFG:
5187+ mutex_lock(&ccdc->ioctl_lock);
5188+ ret = ccdc_config(ccdc, arg);
5189+ mutex_unlock(&ccdc->ioctl_lock);
5190+ break;
5191+
5192+ default:
5193+ return -ENOIOCTLCMD;
5194+ }
5195+
5196+ return ret;
5197+}
5198+
5199+static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
5200+ struct v4l2_event_subscription *sub)
5201+{
5202+ if (sub->type != V4L2_EVENT_OMAP3ISP_HS_VS)
5203+ return -EINVAL;
5204+
5205+ return v4l2_event_subscribe(fh, sub);
5206+}
5207+
5208+static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
5209+ struct v4l2_event_subscription *sub)
5210+{
5211+ return v4l2_event_unsubscribe(fh, sub);
5212+}
5213+
5214+/*
5215+ * ccdc_set_stream - Enable/Disable streaming on the CCDC module
5216+ * @sd: ISP CCDC V4L2 subdevice
5217+ * @enable: Enable/disable stream
5218+ *
5219+ * When writing to memory, the CCDC hardware can't be enabled without a memory
5220+ * buffer to write to. As the s_stream operation is called in response to a
5221+ * STREAMON call without any buffer queued yet, just update the enabled field
5222+ * and return immediately. The CCDC will be enabled in ccdc_isr_buffer().
5223+ *
5224+ * When not writing to memory enable the CCDC immediately.
5225+ */
5226+static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
5227+{
5228+ struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
5229+ struct isp_device *isp = to_isp_device(ccdc);
5230+ int ret = 0;
5231+
5232+ if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) {
5233+ if (enable == ISP_PIPELINE_STREAM_STOPPED)
5234+ return 0;
5235+
5236+ omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_CCDC);
5237+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
5238+ ISPCCDC_CFG_VDLC);
5239+
5240+ ccdc_configure(ccdc);
5241+
5242+ /* TODO: Don't configure the video port if all of its output
5243+ * links are inactive.
5244+ */
5245+ ccdc_config_vp(ccdc);
5246+ ccdc_enable_vp(ccdc, 1);
5247+ ccdc->error = 0;
5248+ ccdc_print_status(ccdc);
5249+ }
5250+
5251+ switch (enable) {
5252+ case ISP_PIPELINE_STREAM_CONTINUOUS:
5253+ if (ccdc->output & CCDC_OUTPUT_MEMORY)
5254+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
5255+
5256+ if (ccdc->underrun || !(ccdc->output & CCDC_OUTPUT_MEMORY))
5257+ ccdc_enable(ccdc);
5258+
5259+ ccdc->underrun = 0;
5260+ break;
5261+
5262+ case ISP_PIPELINE_STREAM_SINGLESHOT:
5263+ if (ccdc->output & CCDC_OUTPUT_MEMORY &&
5264+ ccdc->state != ISP_PIPELINE_STREAM_SINGLESHOT)
5265+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
5266+
5267+ ccdc_enable(ccdc);
5268+ break;
5269+
5270+ case ISP_PIPELINE_STREAM_STOPPED:
5271+ ret = ccdc_disable(ccdc);
5272+ if (ccdc->output & CCDC_OUTPUT_MEMORY)
5273+ omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
5274+ omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_CCDC);
5275+ ccdc->underrun = 0;
5276+ break;
5277+ }
5278+
5279+ ccdc->state = enable;
5280+ return ret;
5281+}
5282+
5283+static struct v4l2_mbus_framefmt *
5284+__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
5285+ unsigned int pad, enum v4l2_subdev_format_whence which)
5286+{
5287+ if (which == V4L2_SUBDEV_FORMAT_TRY)
5288+ return v4l2_subdev_get_try_format(fh, pad);
5289+ else
5290+ return &ccdc->formats[pad];
5291+}
5292+
5293+/*
5294+ * ccdc_try_format - Try video format on a pad
5295+ * @ccdc: ISP CCDC device
5296+ * @fh : V4L2 subdev file handle
5297+ * @pad: Pad number
5298+ * @fmt: Format
5299+ */
5300+static void
5301+ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
5302+ unsigned int pad, struct v4l2_mbus_framefmt *fmt,
5303+ enum v4l2_subdev_format_whence which)
5304+{
5305+ struct v4l2_mbus_framefmt *format;
5306+ const struct isp_format_info *info;
5307+ unsigned int width = fmt->width;
5308+ unsigned int height = fmt->height;
5309+ unsigned int i;
5310+
5311+ switch (pad) {
5312+ case CCDC_PAD_SINK:
5313+ /* TODO: If the CCDC output formatter pad is connected directly
5314+ * to the resizer, only YUV formats can be used.
5315+ */
5316+ for (i = 0; i < ARRAY_SIZE(ccdc_fmts); i++) {
5317+ if (fmt->code == ccdc_fmts[i])
5318+ break;
5319+ }
5320+
5321+ /* If not found, use SGRBG10 as default */
5322+ if (i >= ARRAY_SIZE(ccdc_fmts))
5323+ fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
5324+
5325+ /* Clamp the input size. */
5326+ fmt->width = clamp_t(u32, width, 32, 4096);
5327+ fmt->height = clamp_t(u32, height, 32, 4096);
5328+ break;
5329+
5330+ case CCDC_PAD_SOURCE_OF:
5331+ format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
5332+ memcpy(fmt, format, sizeof(*fmt));
5333+
5334+ /* The data formatter truncates the number of horizontal output
5335+ * pixels to a multiple of 16. To avoid clipping data, allow
5336+ * callers to request an output size bigger than the input size
5337+ * up to the nearest multiple of 16.
5338+ */
5339+ fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15);
5340+ fmt->width &= ~15;
5341+ fmt->height = clamp_t(u32, height, 32, fmt->height);
5342+ break;
5343+
5344+ case CCDC_PAD_SOURCE_VP:
5345+ format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
5346+ memcpy(fmt, format, sizeof(*fmt));
5347+
5348+ /* The video port interface truncates the data to 10 bits. */
5349+ info = omap3isp_video_format_info(fmt->code);
5350+ fmt->code = info->truncated;
5351+
5352+ /* The number of lines that can be clocked out from the video
5353+ * port output must be at least one line less than the number
5354+ * of input lines.
5355+ */
5356+ fmt->width = clamp_t(u32, width, 32, fmt->width);
5357+ fmt->height = clamp_t(u32, height, 32, fmt->height - 1);
5358+ break;
5359+ }
5360+
5361+ /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is
5362+ * stored on 2 bytes.
5363+ */
5364+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
5365+ fmt->field = V4L2_FIELD_NONE;
5366+}
5367+
5368+/*
5369+ * ccdc_enum_mbus_code - Handle pixel format enumeration
5370+ * @sd : pointer to v4l2 subdev structure
5371+ * @fh : V4L2 subdev file handle
5372+ * @code : pointer to v4l2_subdev_mbus_code_enum structure
5373+ * return -EINVAL or zero on success
5374+ */
5375+static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
5376+ struct v4l2_subdev_fh *fh,
5377+ struct v4l2_subdev_mbus_code_enum *code)
5378+{
5379+ struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
5380+ struct v4l2_mbus_framefmt *format;
5381+
5382+ switch (code->pad) {
5383+ case CCDC_PAD_SINK:
5384+ if (code->index >= ARRAY_SIZE(ccdc_fmts))
5385+ return -EINVAL;
5386+
5387+ code->code = ccdc_fmts[code->index];
5388+ break;
5389+
5390+ case CCDC_PAD_SOURCE_OF:
5391+ case CCDC_PAD_SOURCE_VP:
5392+ /* No format conversion inside CCDC */
5393+ if (code->index != 0)
5394+ return -EINVAL;
5395+
5396+ format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK,
5397+ V4L2_SUBDEV_FORMAT_TRY);
5398+
5399+ code->code = format->code;
5400+ break;
5401+
5402+ default:
5403+ return -EINVAL;
5404+ }
5405+
5406+ return 0;
5407+}
5408+
5409+static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
5410+ struct v4l2_subdev_fh *fh,
5411+ struct v4l2_subdev_frame_size_enum *fse)
5412+{
5413+ struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
5414+ struct v4l2_mbus_framefmt format;
5415+
5416+ if (fse->index != 0)
5417+ return -EINVAL;
5418+
5419+ format.code = fse->code;
5420+ format.width = 1;
5421+ format.height = 1;
5422+ ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
5423+ fse->min_width = format.width;
5424+ fse->min_height = format.height;
5425+
5426+ if (format.code != fse->code)
5427+ return -EINVAL;
5428+
5429+ format.code = fse->code;
5430+ format.width = -1;
5431+ format.height = -1;
5432+ ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
5433+ fse->max_width = format.width;
5434+ fse->max_height = format.height;
5435+
5436+ return 0;
5437+}
5438+
5439+/*
5440+ * ccdc_get_format - Retrieve the video format on a pad
5441+ * @sd : ISP CCDC V4L2 subdevice
5442+ * @fh : V4L2 subdev file handle
5443+ * @fmt: Format
5444+ *
5445+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
5446+ * to the format type.
5447+ */
5448+static int ccdc_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
5449+ struct v4l2_subdev_format *fmt)
5450+{
5451+ struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
5452+ struct v4l2_mbus_framefmt *format;
5453+
5454+ format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
5455+ if (format == NULL)
5456+ return -EINVAL;
5457+
5458+ fmt->format = *format;
5459+ return 0;
5460+}
5461+
5462+/*
5463+ * ccdc_set_format - Set the video format on a pad
5464+ * @sd : ISP CCDC V4L2 subdevice
5465+ * @fh : V4L2 subdev file handle
5466+ * @fmt: Format
5467+ *
5468+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
5469+ * to the format type.
5470+ */
5471+static int ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
5472+ struct v4l2_subdev_format *fmt)
5473+{
5474+ struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
5475+ struct v4l2_mbus_framefmt *format;
5476+
5477+ format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
5478+ if (format == NULL)
5479+ return -EINVAL;
5480+
5481+ ccdc_try_format(ccdc, fh, fmt->pad, &fmt->format, fmt->which);
5482+ *format = fmt->format;
5483+
5484+ /* Propagate the format from sink to source */
5485+ if (fmt->pad == CCDC_PAD_SINK) {
5486+ format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_OF,
5487+ fmt->which);
5488+ *format = fmt->format;
5489+ ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_OF, format,
5490+ fmt->which);
5491+
5492+ format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_VP,
5493+ fmt->which);
5494+ *format = fmt->format;
5495+ ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_VP, format,
5496+ fmt->which);
5497+ }
5498+
5499+ return 0;
5500+}
5501+
5502+/*
5503+ * ccdc_init_formats - Initialize formats on all pads
5504+ * @sd: ISP CCDC V4L2 subdevice
5505+ * @fh: V4L2 subdev file handle
5506+ *
5507+ * Initialize all pad formats with default values. If fh is not NULL, try
5508+ * formats are initialized on the file handle. Otherwise active formats are
5509+ * initialized on the device.
5510+ */
5511+static int ccdc_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
5512+{
5513+ struct v4l2_subdev_format format;
5514+
5515+ memset(&format, 0, sizeof(format));
5516+ format.pad = CCDC_PAD_SINK;
5517+ format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
5518+ format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
5519+ format.format.width = 4096;
5520+ format.format.height = 4096;
5521+ ccdc_set_format(sd, fh, &format);
5522+
5523+ return 0;
5524+}
5525+
5526+/* V4L2 subdev core operations */
5527+static const struct v4l2_subdev_core_ops ccdc_v4l2_core_ops = {
5528+ .queryctrl = v4l2_subdev_queryctrl,
5529+ .querymenu = v4l2_subdev_querymenu,
5530+ .g_ctrl = v4l2_subdev_g_ctrl,
5531+ .s_ctrl = v4l2_subdev_s_ctrl,
5532+ .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
5533+ .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
5534+ .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
5535+ .ioctl = ccdc_ioctl,
5536+ .subscribe_event = ccdc_subscribe_event,
5537+ .unsubscribe_event = ccdc_unsubscribe_event,
5538+};
5539+
5540+/* V4L2 subdev file operations */
5541+static const struct v4l2_subdev_file_ops ccdc_v4l2_file_ops = {
5542+ .open = ccdc_init_formats,
5543+};
5544+
5545+/* V4L2 subdev video operations */
5546+static const struct v4l2_subdev_video_ops ccdc_v4l2_video_ops = {
5547+ .s_stream = ccdc_set_stream,
5548+};
5549+
5550+/* V4L2 subdev pad operations */
5551+static const struct v4l2_subdev_pad_ops ccdc_v4l2_pad_ops = {
5552+ .enum_mbus_code = ccdc_enum_mbus_code,
5553+ .enum_frame_size = ccdc_enum_frame_size,
5554+ .get_fmt = ccdc_get_format,
5555+ .set_fmt = ccdc_set_format,
5556+};
5557+
5558+/* V4L2 subdev operations */
5559+static const struct v4l2_subdev_ops ccdc_v4l2_ops = {
5560+ .core = &ccdc_v4l2_core_ops,
5561+ .file = &ccdc_v4l2_file_ops,
5562+ .video = &ccdc_v4l2_video_ops,
5563+ .pad = &ccdc_v4l2_pad_ops,
5564+};
5565+
5566+/* -----------------------------------------------------------------------------
5567+ * Media entity operations
5568+ */
5569+
5570+/*
5571+ * ccdc_link_setup - Setup CCDC connections
5572+ * @entity: CCDC media entity
5573+ * @local: Pad at the local end of the link
5574+ * @remote: Pad at the remote end of the link
5575+ * @flags: Link flags
5576+ *
5577+ * return -EINVAL or zero on success
5578+ */
5579+static int ccdc_link_setup(struct media_entity *entity,
5580+ const struct media_pad *local,
5581+ const struct media_pad *remote, u32 flags)
5582+{
5583+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
5584+ struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
5585+ struct isp_device *isp = to_isp_device(ccdc);
5586+
5587+ switch (local->index | media_entity_type(remote->entity)) {
5588+ case CCDC_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
5589+ /* Read from the sensor (parallel interface), CCP2, CSI2a or
5590+ * CSI2c.
5591+ */
5592+ if (!(flags & MEDIA_LNK_FL_ENABLED)) {
5593+ ccdc->input = CCDC_INPUT_NONE;
5594+ break;
5595+ }
5596+
5597+ if (ccdc->input != CCDC_INPUT_NONE)
5598+ return -EBUSY;
5599+
5600+ if (remote->entity == &isp->isp_ccp2.subdev.entity)
5601+ ccdc->input = CCDC_INPUT_CCP2B;
5602+ else if (remote->entity == &isp->isp_csi2a.subdev.entity)
5603+ ccdc->input = CCDC_INPUT_CSI2A;
5604+ else if (remote->entity == &isp->isp_csi2c.subdev.entity)
5605+ ccdc->input = CCDC_INPUT_CSI2C;
5606+ else
5607+ ccdc->input = CCDC_INPUT_PARALLEL;
5608+
5609+ break;
5610+
5611+ /*
5612+ * The ISP core doesn't support pipelines with multiple video outputs.
5613+ * Revisit this when it will be implemented, and return -EBUSY for now.
5614+ */
5615+
5616+ case CCDC_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV:
5617+ /* Write to preview engine, histogram and H3A. When none of
5618+ * those links are active, the video port can be disabled.
5619+ */
5620+ if (flags & MEDIA_LNK_FL_ENABLED) {
5621+ if (ccdc->output & ~CCDC_OUTPUT_PREVIEW)
5622+ return -EBUSY;
5623+ ccdc->output |= CCDC_OUTPUT_PREVIEW;
5624+ } else {
5625+ ccdc->output &= ~CCDC_OUTPUT_PREVIEW;
5626+ }
5627+ break;
5628+
5629+ case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_DEVNODE:
5630+ /* Write to memory */
5631+ if (flags & MEDIA_LNK_FL_ENABLED) {
5632+ if (ccdc->output & ~CCDC_OUTPUT_MEMORY)
5633+ return -EBUSY;
5634+ ccdc->output |= CCDC_OUTPUT_MEMORY;
5635+ } else {
5636+ ccdc->output &= ~CCDC_OUTPUT_MEMORY;
5637+ }
5638+ break;
5639+
5640+ case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_V4L2_SUBDEV:
5641+ /* Write to resizer */
5642+ if (flags & MEDIA_LNK_FL_ENABLED) {
5643+ if (ccdc->output & ~CCDC_OUTPUT_RESIZER)
5644+ return -EBUSY;
5645+ ccdc->output |= CCDC_OUTPUT_RESIZER;
5646+ } else {
5647+ ccdc->output &= ~CCDC_OUTPUT_RESIZER;
5648+ }
5649+ break;
5650+
5651+ default:
5652+ return -EINVAL;
5653+ }
5654+
5655+ return 0;
5656+}
5657+
5658+/* media operations */
5659+static const struct media_entity_operations ccdc_media_ops = {
5660+ .link_setup = ccdc_link_setup,
5661+};
5662+
5663+/*
5664+ * ccdc_init_entities - Initialize V4L2 subdev and media entity
5665+ * @ccdc: ISP CCDC module
5666+ *
5667+ * Return 0 on success and a negative error code on failure.
5668+ */
5669+static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
5670+{
5671+ struct v4l2_subdev *sd = &ccdc->subdev;
5672+ struct media_pad *pads = ccdc->pads;
5673+ struct media_entity *me = &sd->entity;
5674+ int ret;
5675+
5676+ ccdc->input = CCDC_INPUT_NONE;
5677+
5678+ v4l2_subdev_init(sd, &ccdc_v4l2_ops);
5679+ strlcpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name));
5680+ sd->grp_id = 1 << 16; /* group ID for isp subdevs */
5681+ v4l2_set_subdevdata(sd, ccdc);
5682+ sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
5683+ sd->nevents = OMAP3ISP_CCDC_NEVENTS;
5684+
5685+ v4l2_ctrl_handler_init(&ccdc->ctrls, 1);
5686+ sd->ctrl_handler = &ccdc->ctrls;
5687+
5688+ pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_INPUT;
5689+ pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_OUTPUT;
5690+ pads[CCDC_PAD_SOURCE_OF].flags = MEDIA_PAD_FL_OUTPUT;
5691+
5692+ me->ops = &ccdc_media_ops;
5693+ ret = media_entity_init(me, CCDC_PADS_NUM, pads, 0);
5694+ if (ret < 0)
5695+ return ret;
5696+
5697+ ccdc_init_formats(sd, NULL);
5698+
5699+ ccdc->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
5700+ ccdc->video_out.ops = &ccdc_video_ops;
5701+ ccdc->video_out.isp = to_isp_device(ccdc);
5702+ ccdc->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
5703+ ccdc->video_out.bpl_alignment = 32;
5704+
5705+ ret = omap3isp_video_init(&ccdc->video_out, "CCDC");
5706+ if (ret < 0)
5707+ return ret;
5708+
5709+ /* Connect the CCDC subdev to the video node. */
5710+ ret = media_entity_create_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
5711+ &ccdc->video_out.video.entity, 0, 0);
5712+ if (ret < 0)
5713+ return ret;
5714+
5715+ return 0;
5716+}
5717+
5718+void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
5719+{
5720+ media_entity_cleanup(&ccdc->subdev.entity);
5721+
5722+ v4l2_device_unregister_subdev(&ccdc->subdev);
5723+ v4l2_ctrl_handler_free(&ccdc->ctrls);
5724+ omap3isp_video_unregister(&ccdc->video_out);
5725+}
5726+
5727+int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
5728+ struct v4l2_device *vdev)
5729+{
5730+ int ret;
5731+
5732+ /* Register the subdev and video node. */
5733+ ret = v4l2_device_register_subdev(vdev, &ccdc->subdev);
5734+ if (ret < 0)
5735+ goto error;
5736+
5737+ ret = omap3isp_video_register(&ccdc->video_out, vdev);
5738+ if (ret < 0)
5739+ goto error;
5740+
5741+ return 0;
5742+
5743+error:
5744+ omap3isp_ccdc_unregister_entities(ccdc);
5745+ return ret;
5746+}
5747+
5748+/* -----------------------------------------------------------------------------
5749+ * ISP CCDC initialisation and cleanup
5750+ */
5751+
5752+/*
5753+ * omap3isp_ccdc_init - CCDC module initialization.
5754+ * @dev: Device pointer specific to the OMAP3 ISP.
5755+ *
5756+ * TODO: Get the initialisation values from platform data.
5757+ *
5758+ * Return 0 on success or a negative error code otherwise.
5759+ */
5760+int omap3isp_ccdc_init(struct isp_device *isp)
5761+{
5762+ struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
5763+
5764+ spin_lock_init(&ccdc->lock);
5765+ init_waitqueue_head(&ccdc->wait);
5766+ mutex_init(&ccdc->ioctl_lock);
5767+
5768+ ccdc->stopping = CCDC_STOP_NOT_REQUESTED;
5769+
5770+ INIT_WORK(&ccdc->lsc.table_work, ccdc_lsc_free_table_work);
5771+ ccdc->lsc.state = LSC_STATE_STOPPED;
5772+ INIT_LIST_HEAD(&ccdc->lsc.free_queue);
5773+ spin_lock_init(&ccdc->lsc.req_lock);
5774+
5775+ ccdc->syncif.ccdc_mastermode = 0;
5776+ ccdc->syncif.datapol = 0;
5777+ ccdc->syncif.datsz = 0;
5778+ ccdc->syncif.fldmode = 0;
5779+ ccdc->syncif.fldout = 0;
5780+ ccdc->syncif.fldpol = 0;
5781+ ccdc->syncif.fldstat = 0;
5782+ ccdc->syncif.hdpol = 0;
5783+ ccdc->syncif.vdpol = 0;
5784+
5785+ ccdc->clamp.oblen = 0;
5786+ ccdc->clamp.dcsubval = 0;
5787+
5788+ ccdc->vpcfg.pixelclk = 0;
5789+
5790+ ccdc->update = OMAP3ISP_CCDC_BLCLAMP;
5791+ ccdc_apply_controls(ccdc);
5792+
5793+ return ccdc_init_entities(ccdc);
5794+}
5795+
5796+/*
5797+ * omap3isp_ccdc_cleanup - CCDC module cleanup.
5798+ * @dev: Device pointer specific to the OMAP3 ISP.
5799+ */
5800+void omap3isp_ccdc_cleanup(struct isp_device *isp)
5801+{
5802+ struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
5803+
5804+ /* Free LSC requests. As the CCDC is stopped there's no active request,
5805+ * so only the pending request and the free queue need to be handled.
5806+ */
5807+ ccdc_lsc_free_request(ccdc, ccdc->lsc.request);
5808+ cancel_work_sync(&ccdc->lsc.table_work);
5809+ ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
5810+
5811+ if (ccdc->fpc.fpcaddr != 0)
5812+ iommu_vfree(isp->iommu, ccdc->fpc.fpcaddr);
5813+}
5814diff --git a/drivers/media/video/isp/ispccdc.h b/drivers/media/video/isp/ispccdc.h
5815new file mode 100644
5816index 0000000..5c00e2c
5817--- /dev/null
5818+++ b/drivers/media/video/isp/ispccdc.h
5819@@ -0,0 +1,223 @@
5820+/*
5821+ * ispccdc.h
5822+ *
5823+ * TI OMAP3 ISP - CCDC module
5824+ *
5825+ * Copyright (C) 2009-2010 Nokia Corporation
5826+ * Copyright (C) 2009 Texas Instruments, Inc.
5827+ *
5828+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
5829+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
5830+ *
5831+ * This program is free software; you can redistribute it and/or modify
5832+ * it under the terms of the GNU General Public License version 2 as
5833+ * published by the Free Software Foundation.
5834+ *
5835+ * This program is distributed in the hope that it will be useful, but
5836+ * WITHOUT ANY WARRANTY; without even the implied warranty of
5837+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5838+ * General Public License for more details.
5839+ *
5840+ * You should have received a copy of the GNU General Public License
5841+ * along with this program; if not, write to the Free Software
5842+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
5843+ * 02110-1301 USA
5844+ */
5845+
5846+#ifndef OMAP3_ISP_CCDC_H
5847+#define OMAP3_ISP_CCDC_H
5848+
5849+#include <linux/omap3isp.h>
5850+#include <linux/workqueue.h>
5851+#include <media/v4l2-ctrls.h>
5852+
5853+#include "ispvideo.h"
5854+
5855+enum ccdc_input_entity {
5856+ CCDC_INPUT_NONE,
5857+ CCDC_INPUT_PARALLEL,
5858+ CCDC_INPUT_CSI2A,
5859+ CCDC_INPUT_CCP2B,
5860+ CCDC_INPUT_CSI2C
5861+};
5862+
5863+#define CCDC_OUTPUT_MEMORY (1 << 0)
5864+#define CCDC_OUTPUT_PREVIEW (1 << 1)
5865+#define CCDC_OUTPUT_RESIZER (1 << 2)
5866+
5867+#define OMAP3ISP_CCDC_NEVENTS 16
5868+
5869+/*
5870+ * struct ispccdc_syncif - Structure for Sync Interface between sensor and CCDC
5871+ * @ccdc_mastermode: Master mode. 1 - Master, 0 - Slave.
5872+ * @fldstat: Field state. 0 - Odd Field, 1 - Even Field.
5873+ * @datsz: Data size.
5874+ * @fldmode: 0 - Progressive, 1 - Interlaced.
5875+ * @datapol: 0 - Positive, 1 - Negative.
5876+ * @fldpol: 0 - Positive, 1 - Negative.
5877+ * @hdpol: 0 - Positive, 1 - Negative.
5878+ * @vdpol: 0 - Positive, 1 - Negative.
5879+ * @fldout: 0 - Input, 1 - Output.
5880+ * @hs_width: Width of the Horizontal Sync pulse, used for HS/VS Output.
5881+ * @vs_width: Width of the Vertical Sync pulse, used for HS/VS Output.
5882+ * @ppln: Number of pixels per line, used for HS/VS Output.
5883+ * @hlprf: Number of half lines per frame, used for HS/VS Output.
5884+ * @bt_r656_en: 1 - Enable ITU-R BT656 mode, 0 - Sync mode.
5885+ */
5886+struct ispccdc_syncif {
5887+ u8 ccdc_mastermode;
5888+ u8 fldstat;
5889+ u8 datsz;
5890+ u8 fldmode;
5891+ u8 datapol;
5892+ u8 fldpol;
5893+ u8 hdpol;
5894+ u8 vdpol;
5895+ u8 fldout;
5896+ u8 hs_width;
5897+ u8 vs_width;
5898+ u8 ppln;
5899+ u8 hlprf;
5900+ u8 bt_r656_en;
5901+};
5902+
5903+/*
5904+ * struct ispccdc_vp - Structure for Video Port parameters
5905+ * @pixelclk: Input pixel clock in Hz
5906+ */
5907+struct ispccdc_vp {
5908+ unsigned int pixelclk;
5909+};
5910+
5911+enum ispccdc_lsc_state {
5912+ LSC_STATE_STOPPED = 0,
5913+ LSC_STATE_STOPPING = 1,
5914+ LSC_STATE_RUNNING = 2,
5915+ LSC_STATE_RECONFIG = 3,
5916+};
5917+
5918+struct ispccdc_lsc_config_req {
5919+ struct list_head list;
5920+ struct omap3isp_ccdc_lsc_config config;
5921+ unsigned char enable;
5922+ u32 table;
5923+ struct iovm_struct *iovm;
5924+};
5925+
5926+/*
5927+ * ispccdc_lsc - CCDC LSC parameters
5928+ * @update_config: Set when user changes config
5929+ * @request_enable: Whether LSC is requested to be enabled
5930+ * @config: LSC config set by user
5931+ * @update_table: Set when user provides a new LSC table to table_new
5932+ * @table_new: LSC table set by user, ISP address
5933+ * @table_inuse: LSC table currently in use, ISP address
5934+ */
5935+struct ispccdc_lsc {
5936+ enum ispccdc_lsc_state state;
5937+ struct work_struct table_work;
5938+
5939+ /* LSC queue of configurations */
5940+ spinlock_t req_lock;
5941+ struct ispccdc_lsc_config_req *request; /* requested configuration */
5942+ struct ispccdc_lsc_config_req *active; /* active configuration */
5943+ struct list_head free_queue; /* configurations for freeing */
5944+};
5945+
5946+#define CCDC_STOP_NOT_REQUESTED 0x00
5947+#define CCDC_STOP_REQUEST 0x01
5948+#define CCDC_STOP_EXECUTED (0x02 | CCDC_STOP_REQUEST)
5949+#define CCDC_STOP_CCDC_FINISHED 0x04
5950+#define CCDC_STOP_LSC_FINISHED 0x08
5951+#define CCDC_STOP_FINISHED \
5952+ (CCDC_STOP_EXECUTED | CCDC_STOP_CCDC_FINISHED | CCDC_STOP_LSC_FINISHED)
5953+
5954+#define CCDC_EVENT_VD1 0x10
5955+#define CCDC_EVENT_VD0 0x20
5956+#define CCDC_EVENT_LSC_DONE 0x40
5957+
5958+/* Sink and source CCDC pads */
5959+#define CCDC_PAD_SINK 0
5960+#define CCDC_PAD_SOURCE_OF 1
5961+#define CCDC_PAD_SOURCE_VP 2
5962+#define CCDC_PADS_NUM 3
5963+
5964+/*
5965+ * struct isp_ccdc_device - Structure for the CCDC module to store its own
5966+ * information
5967+ * @subdev: V4L2 subdevice
5968+ * @pads: Sink and source media entity pads
5969+ * @formats: Active video formats
5970+ * @ctrls: V4L2 controls handler
5971+ * @input: Active input
5972+ * @output: Active outputs
5973+ * @video_out: Output video node
5974+ * @error: A hardware error occured during capture
5975+ * @alaw: A-law compression enabled (1) or disabled (0)
5976+ * @lpf: Low pass filter enabled (1) or disabled (0)
5977+ * @obclamp: Optical-black clamp enabled (1) or disabled (0)
5978+ * @fpc_en: Faulty pixels correction enabled (1) or disabled (0)
5979+ * @blcomp: Black level compensation configuration
5980+ * @clamp: Optical-black or digital clamp configuration
5981+ * @fpc: Faulty pixels correction configuration
5982+ * @lsc: Lens shading compensation configuration
5983+ * @update: Bitmask of controls to update during the next interrupt
5984+ * @shadow_update: Controls update in progress by userspace
5985+ * @syncif: Interface synchronization configuration
5986+ * @vpcfg: Video port configuration
5987+ * @underrun: A buffer underrun occured and a new buffer has been queued
5988+ * @state: Streaming state
5989+ * @lock: Serializes shadow_update with interrupt handler
5990+ * @wait: Wait queue used to stop the module
5991+ * @stopping: Stopping state
5992+ * @ioctl_lock: Serializes ioctl calls and LSC requests freeing
5993+ */
5994+struct isp_ccdc_device {
5995+ struct v4l2_subdev subdev;
5996+ struct media_pad pads[CCDC_PADS_NUM];
5997+ struct v4l2_mbus_framefmt formats[CCDC_PADS_NUM];
5998+
5999+ struct v4l2_ctrl_handler ctrls;
6000+
6001+ enum ccdc_input_entity input;
6002+ unsigned int output;
6003+ struct isp_video video_out;
6004+ unsigned int error;
6005+
6006+ unsigned int alaw:1,
6007+ lpf:1,
6008+ obclamp:1,
6009+ fpc_en:1;
6010+ struct omap3isp_ccdc_blcomp blcomp;
6011+ struct omap3isp_ccdc_bclamp clamp;
6012+ struct omap3isp_ccdc_fpc fpc;
6013+ struct ispccdc_lsc lsc;
6014+ unsigned int update;
6015+ unsigned int shadow_update;
6016+
6017+ struct ispccdc_syncif syncif;
6018+ struct ispccdc_vp vpcfg;
6019+
6020+ unsigned int underrun:1;
6021+ enum isp_pipeline_stream_state state;
6022+ spinlock_t lock;
6023+ wait_queue_head_t wait;
6024+ unsigned int stopping;
6025+ struct mutex ioctl_lock;
6026+};
6027+
6028+struct isp_device;
6029+
6030+int omap3isp_ccdc_init(struct isp_device *isp);
6031+void omap3isp_ccdc_cleanup(struct isp_device *isp);
6032+int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
6033+ struct v4l2_device *vdev);
6034+void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc);
6035+
6036+int omap3isp_ccdc_busy(struct isp_ccdc_device *isp_ccdc);
6037+int omap3isp_ccdc_isr(struct isp_ccdc_device *isp_ccdc, u32 events);
6038+void omap3isp_ccdc_restore_context(struct isp_device *isp);
6039+void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
6040+ unsigned int *max_rate);
6041+
6042+#endif /* OMAP3_ISP_CCDC_H */
6043diff --git a/drivers/media/video/isp/ispccp2.c b/drivers/media/video/isp/ispccp2.c
6044new file mode 100644
6045index 0000000..efcf827
6046--- /dev/null
6047+++ b/drivers/media/video/isp/ispccp2.c
6048@@ -0,0 +1,1189 @@
6049+/*
6050+ * ispccp2.c
6051+ *
6052+ * TI OMAP3 ISP - CCP2 module
6053+ *
6054+ * Copyright (C) 2010 Nokia Corporation
6055+ * Copyright (C) 2010 Texas Instruments, Inc.
6056+ *
6057+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
6058+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
6059+ *
6060+ * This program is free software; you can redistribute it and/or modify
6061+ * it under the terms of the GNU General Public License version 2 as
6062+ * published by the Free Software Foundation.
6063+ *
6064+ * This program is distributed in the hope that it will be useful, but
6065+ * WITHOUT ANY WARRANTY; without even the implied warranty of
6066+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6067+ * General Public License for more details.
6068+ *
6069+ * You should have received a copy of the GNU General Public License
6070+ * along with this program; if not, write to the Free Software
6071+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
6072+ * 02110-1301 USA
6073+ */
6074+
6075+#include <linux/delay.h>
6076+#include <linux/device.h>
6077+#include <linux/mm.h>
6078+#include <linux/module.h>
6079+#include <linux/mutex.h>
6080+#include <linux/uaccess.h>
6081+
6082+#include "isp.h"
6083+#include "ispreg.h"
6084+#include "ispccp2.h"
6085+
6086+/* Number of LCX channels */
6087+#define CCP2_LCx_CHANS_NUM 3
6088+/* Max/Min size for CCP2 video port */
6089+#define ISPCCP2_DAT_START_MIN 0
6090+#define ISPCCP2_DAT_START_MAX 4095
6091+#define ISPCCP2_DAT_SIZE_MIN 0
6092+#define ISPCCP2_DAT_SIZE_MAX 4095
6093+#define ISPCCP2_VPCLK_FRACDIV 65536
6094+#define ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP 0x12
6095+#define ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP 0x16
6096+/* Max/Min size for CCP2 memory channel */
6097+#define ISPCCP2_LCM_HSIZE_COUNT_MIN 16
6098+#define ISPCCP2_LCM_HSIZE_COUNT_MAX 8191
6099+#define ISPCCP2_LCM_HSIZE_SKIP_MIN 0
6100+#define ISPCCP2_LCM_HSIZE_SKIP_MAX 8191
6101+#define ISPCCP2_LCM_VSIZE_MIN 1
6102+#define ISPCCP2_LCM_VSIZE_MAX 8191
6103+#define ISPCCP2_LCM_HWORDS_MIN 1
6104+#define ISPCCP2_LCM_HWORDS_MAX 4095
6105+#define ISPCCP2_LCM_CTRL_BURST_SIZE_32X 5
6106+#define ISPCCP2_LCM_CTRL_READ_THROTTLE_FULL 0
6107+#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10 2
6108+#define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8 2
6109+#define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10 3
6110+#define ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10 3
6111+#define ISPCCP2_LCM_CTRL_DST_PORT_VP 0
6112+#define ISPCCP2_LCM_CTRL_DST_PORT_MEM 1
6113+
6114+/* Set only the required bits */
6115+#define BIT_SET(var, shift, mask, val) \
6116+ do { \
6117+ var = ((var) & ~((mask) << (shift))) \
6118+ | ((val) << (shift)); \
6119+ } while (0)
6120+
6121+/*
6122+ * ccp2_print_status - Print current CCP2 module register values.
6123+ */
6124+#define CCP2_PRINT_REGISTER(isp, name)\
6125+ dev_dbg(isp->dev, "###CCP2 " #name "=0x%08x\n", \
6126+ isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_##name))
6127+
6128+static void ccp2_print_status(struct isp_ccp2_device *ccp2)
6129+{
6130+ struct isp_device *isp = to_isp_device(ccp2);
6131+
6132+ dev_dbg(isp->dev, "-------------CCP2 Register dump-------------\n");
6133+
6134+ CCP2_PRINT_REGISTER(isp, SYSCONFIG);
6135+ CCP2_PRINT_REGISTER(isp, SYSSTATUS);
6136+ CCP2_PRINT_REGISTER(isp, LC01_IRQENABLE);
6137+ CCP2_PRINT_REGISTER(isp, LC01_IRQSTATUS);
6138+ CCP2_PRINT_REGISTER(isp, LC23_IRQENABLE);
6139+ CCP2_PRINT_REGISTER(isp, LC23_IRQSTATUS);
6140+ CCP2_PRINT_REGISTER(isp, LCM_IRQENABLE);
6141+ CCP2_PRINT_REGISTER(isp, LCM_IRQSTATUS);
6142+ CCP2_PRINT_REGISTER(isp, CTRL);
6143+ CCP2_PRINT_REGISTER(isp, LCx_CTRL(0));
6144+ CCP2_PRINT_REGISTER(isp, LCx_CODE(0));
6145+ CCP2_PRINT_REGISTER(isp, LCx_STAT_START(0));
6146+ CCP2_PRINT_REGISTER(isp, LCx_STAT_SIZE(0));
6147+ CCP2_PRINT_REGISTER(isp, LCx_SOF_ADDR(0));
6148+ CCP2_PRINT_REGISTER(isp, LCx_EOF_ADDR(0));
6149+ CCP2_PRINT_REGISTER(isp, LCx_DAT_START(0));
6150+ CCP2_PRINT_REGISTER(isp, LCx_DAT_SIZE(0));
6151+ CCP2_PRINT_REGISTER(isp, LCx_DAT_PING_ADDR(0));
6152+ CCP2_PRINT_REGISTER(isp, LCx_DAT_PONG_ADDR(0));
6153+ CCP2_PRINT_REGISTER(isp, LCx_DAT_OFST(0));
6154+ CCP2_PRINT_REGISTER(isp, LCM_CTRL);
6155+ CCP2_PRINT_REGISTER(isp, LCM_VSIZE);
6156+ CCP2_PRINT_REGISTER(isp, LCM_HSIZE);
6157+ CCP2_PRINT_REGISTER(isp, LCM_PREFETCH);
6158+ CCP2_PRINT_REGISTER(isp, LCM_SRC_ADDR);
6159+ CCP2_PRINT_REGISTER(isp, LCM_SRC_OFST);
6160+ CCP2_PRINT_REGISTER(isp, LCM_DST_ADDR);
6161+ CCP2_PRINT_REGISTER(isp, LCM_DST_OFST);
6162+
6163+ dev_dbg(isp->dev, "--------------------------------------------\n");
6164+}
6165+
6166+/*
6167+ * ccp2_reset - Reset the CCP2
6168+ * @ccp2: pointer to ISP CCP2 device
6169+ */
6170+static void ccp2_reset(struct isp_ccp2_device *ccp2)
6171+{
6172+ struct isp_device *isp = to_isp_device(ccp2);
6173+ int i = 0;
6174+
6175+ /* Reset the CSI1/CCP2B and wait for reset to complete */
6176+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG,
6177+ ISPCCP2_SYSCONFIG_SOFT_RESET);
6178+ while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSSTATUS) &
6179+ ISPCCP2_SYSSTATUS_RESET_DONE)) {
6180+ udelay(10);
6181+ if (i++ > 10) { /* try read 10 times */
6182+ dev_warn(isp->dev,
6183+ "omap3_isp: timeout waiting for ccp2 reset\n");
6184+ break;
6185+ }
6186+ }
6187+}
6188+
6189+/*
6190+ * ccp2_pwr_cfg - Configure the power mode settings
6191+ * @ccp2: pointer to ISP CCP2 device
6192+ */
6193+static void ccp2_pwr_cfg(struct isp_ccp2_device *ccp2)
6194+{
6195+ struct isp_device *isp = to_isp_device(ccp2);
6196+
6197+ isp_reg_writel(isp, ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SMART |
6198+ ((isp->revision == ISP_REVISION_15_0 && isp->autoidle) ?
6199+ ISPCCP2_SYSCONFIG_AUTO_IDLE : 0),
6200+ OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG);
6201+}
6202+
6203+/*
6204+ * ccp2_if_enable - Enable CCP2 interface.
6205+ * @ccp2: pointer to ISP CCP2 device
6206+ * @enable: enable/disable flag
6207+ */
6208+static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable)
6209+{
6210+ struct isp_device *isp = to_isp_device(ccp2);
6211+ struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
6212+ int i;
6213+
6214+ /* Enable/Disable all the LCx channels */
6215+ for (i = 0; i < CCP2_LCx_CHANS_NUM; i++)
6216+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i),
6217+ ISPCCP2_LCx_CTRL_CHAN_EN,
6218+ enable ? ISPCCP2_LCx_CTRL_CHAN_EN : 0);
6219+
6220+ /* Enable/Disable ccp2 interface in ccp2 mode */
6221+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
6222+ ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN,
6223+ enable ? (ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN) : 0);
6224+
6225+ /* For frame count propagation */
6226+ if (pipe->do_propagation) {
6227+ /* We may want the Frame Start IRQ from LC0 */
6228+ if (enable)
6229+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2,
6230+ ISPCCP2_LC01_IRQENABLE,
6231+ ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ);
6232+ else
6233+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCP2,
6234+ ISPCCP2_LC01_IRQENABLE,
6235+ ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ);
6236+ }
6237+}
6238+
6239+/*
6240+ * ccp2_mem_enable - Enable CCP2 memory interface.
6241+ * @ccp2: pointer to ISP CCP2 device
6242+ * @enable: enable/disable flag
6243+ */
6244+static void ccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable)
6245+{
6246+ struct isp_device *isp = to_isp_device(ccp2);
6247+
6248+ if (enable)
6249+ ccp2_if_enable(ccp2, 0);
6250+
6251+ /* Enable/Disable ccp2 interface in ccp2 mode */
6252+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
6253+ ISPCCP2_CTRL_MODE, enable ? ISPCCP2_CTRL_MODE : 0);
6254+
6255+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL,
6256+ ISPCCP2_LCM_CTRL_CHAN_EN,
6257+ enable ? ISPCCP2_LCM_CTRL_CHAN_EN : 0);
6258+}
6259+
6260+/*
6261+ * ccp2_phyif_config - Initialize CCP2 phy interface config
6262+ * @ccp2: Pointer to ISP CCP2 device
6263+ * @config: CCP2 platform data
6264+ *
6265+ * Configure the CCP2 physical interface module from platform data.
6266+ *
6267+ * Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success.
6268+ */
6269+static int ccp2_phyif_config(struct isp_ccp2_device *ccp2,
6270+ const struct isp_ccp2_platform_data *pdata)
6271+{
6272+ struct isp_device *isp = to_isp_device(ccp2);
6273+ u32 val;
6274+
6275+ /* CCP2B mode */
6276+ val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL) |
6277+ ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE;
6278+ /* Data/strobe physical layer */
6279+ BIT_SET(val, ISPCCP2_CTRL_PHY_SEL_SHIFT, ISPCCP2_CTRL_PHY_SEL_MASK,
6280+ pdata->phy_layer);
6281+ BIT_SET(val, ISPCCP2_CTRL_INV_SHIFT, ISPCCP2_CTRL_INV_MASK,
6282+ pdata->strobe_clk_pol);
6283+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
6284+
6285+ val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
6286+ if (!(val & ISPCCP2_CTRL_MODE)) {
6287+ if (pdata->ccp2_mode)
6288+ dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");
6289+ if (pdata->phy_layer == ISPCCP2_CTRL_PHY_SEL_STROBE)
6290+ /* Strobe mode requires CCP2 */
6291+ return -EIO;
6292+ }
6293+
6294+ return 0;
6295+}
6296+
6297+/*
6298+ * ccp2_vp_config - Initialize CCP2 video port interface.
6299+ * @ccp2: Pointer to ISP CCP2 device
6300+ * @vpclk_div: Video port divisor
6301+ *
6302+ * Configure the CCP2 video port with the given clock divisor. The valid divisor
6303+ * values depend on the ISP revision:
6304+ *
6305+ * - revision 1.0 and 2.0 1 to 4
6306+ * - revision 15.0 1 to 65536
6307+ *
6308+ * The exact divisor value used might differ from the requested value, as ISP
6309+ * revision 15.0 represent the divisor by 65536 divided by an integer.
6310+ */
6311+static void ccp2_vp_config(struct isp_ccp2_device *ccp2,
6312+ unsigned int vpclk_div)
6313+{
6314+ struct isp_device *isp = to_isp_device(ccp2);
6315+ u32 val;
6316+
6317+ /* ISPCCP2_CTRL Video port */
6318+ val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
6319+ val |= ISPCCP2_CTRL_VP_ONLY_EN; /* Disable the memory write port */
6320+
6321+ if (isp->revision == ISP_REVISION_15_0) {
6322+ vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 65536);
6323+ vpclk_div = min(ISPCCP2_VPCLK_FRACDIV / vpclk_div, 65535U);
6324+ BIT_SET(val, ISPCCP2_CTRL_VPCLK_DIV_SHIFT,
6325+ ISPCCP2_CTRL_VPCLK_DIV_MASK, vpclk_div);
6326+ } else {
6327+ vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 4);
6328+ BIT_SET(val, ISPCCP2_CTRL_VP_OUT_CTRL_SHIFT,
6329+ ISPCCP2_CTRL_VP_OUT_CTRL_MASK, vpclk_div - 1);
6330+ }
6331+
6332+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
6333+}
6334+
6335+/*
6336+ * ccp2_lcx_config - Initialize CCP2 logical channel interface.
6337+ * @ccp2: Pointer to ISP CCP2 device
6338+ * @config: Pointer to ISP LCx config structure.
6339+ *
6340+ * This will analyze the parameters passed by the interface config
6341+ * and configure CSI1/CCP2 logical channel
6342+ *
6343+ */
6344+static void ccp2_lcx_config(struct isp_ccp2_device *ccp2,
6345+ struct isp_interface_lcx_config *config)
6346+{
6347+ struct isp_device *isp = to_isp_device(ccp2);
6348+ u32 val, format;
6349+
6350+ switch (config->format) {
6351+ case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
6352+ format = ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP;
6353+ break;
6354+ case V4L2_MBUS_FMT_SGRBG10_1X10:
6355+ default:
6356+ format = ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP; /* RAW10+VP */
6357+ break;
6358+ }
6359+ /* ISPCCP2_LCx_CTRL logical channel #0 */
6360+ val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0))
6361+ | (ISPCCP2_LCx_CTRL_REGION_EN); /* Region */
6362+
6363+ if (isp->revision == ISP_REVISION_15_0) {
6364+ /* CRC */
6365+ BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT_15_0,
6366+ ISPCCP2_LCx_CTRL_CRC_MASK,
6367+ config->crc);
6368+ /* Format = RAW10+VP or RAW8+DPCM10+VP*/
6369+ BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT_15_0,
6370+ ISPCCP2_LCx_CTRL_FORMAT_MASK_15_0, format);
6371+ } else {
6372+ BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT,
6373+ ISPCCP2_LCx_CTRL_CRC_MASK,
6374+ config->crc);
6375+
6376+ BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT,
6377+ ISPCCP2_LCx_CTRL_FORMAT_MASK, format);
6378+ }
6379+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0));
6380+
6381+ /* ISPCCP2_DAT_START for logical channel #0 */
6382+ isp_reg_writel(isp, config->data_start << ISPCCP2_LCx_DAT_SHIFT,
6383+ OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_START(0));
6384+
6385+ /* ISPCCP2_DAT_SIZE for logical channel #0 */
6386+ isp_reg_writel(isp, config->data_size << ISPCCP2_LCx_DAT_SHIFT,
6387+ OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_SIZE(0));
6388+
6389+ /* Enable error IRQs for logical channel #0 */
6390+ val = ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
6391+ ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
6392+ ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |
6393+ ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |
6394+ ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ |
6395+ ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |
6396+ ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;
6397+
6398+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQSTATUS);
6399+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, val);
6400+}
6401+
6402+/*
6403+ * ccp2_if_configure - Configure ccp2 with data from sensor
6404+ * @ccp2: Pointer to ISP CCP2 device
6405+ *
6406+ * Return 0 on success or a negative error code
6407+ */
6408+static int ccp2_if_configure(struct isp_ccp2_device *ccp2)
6409+{
6410+ const struct isp_v4l2_subdevs_group *pdata;
6411+ struct v4l2_mbus_framefmt *format;
6412+ struct media_pad *pad;
6413+ struct v4l2_subdev *sensor;
6414+ u32 lines = 0;
6415+ int ret;
6416+
6417+ ccp2_pwr_cfg(ccp2);
6418+
6419+ pad = media_entity_remote_source(&ccp2->pads[CCP2_PAD_SINK]);
6420+ sensor = media_entity_to_v4l2_subdev(pad->entity);
6421+ pdata = sensor->host_priv;
6422+
6423+ ret = ccp2_phyif_config(ccp2, &pdata->bus.ccp2);
6424+ if (ret < 0)
6425+ return ret;
6426+
6427+ ccp2_vp_config(ccp2, pdata->bus.ccp2.vpclk_div + 1);
6428+
6429+ v4l2_subdev_call(sensor, sensor, g_skip_top_lines, &lines);
6430+
6431+ format = &ccp2->formats[CCP2_PAD_SINK];
6432+
6433+ ccp2->if_cfg.data_start = lines;
6434+ ccp2->if_cfg.crc = pdata->bus.ccp2.crc;
6435+ ccp2->if_cfg.format = format->code;
6436+ ccp2->if_cfg.data_size = format->height;
6437+
6438+ ccp2_lcx_config(ccp2, &ccp2->if_cfg);
6439+
6440+ return 0;
6441+}
6442+
6443+static int ccp2_adjust_bandwidth(struct isp_ccp2_device *ccp2)
6444+{
6445+ struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
6446+ struct isp_device *isp = to_isp_device(ccp2);
6447+ const struct v4l2_mbus_framefmt *ofmt = &ccp2->formats[CCP2_PAD_SOURCE];
6448+ unsigned long l3_ick = pipe->l3_ick;
6449+ struct v4l2_fract *timeperframe;
6450+ unsigned int vpclk_div = 2;
6451+ unsigned int value;
6452+ u64 bound;
6453+ u64 area;
6454+
6455+ /* Compute the minimum clock divisor, based on the pipeline maximum
6456+ * data rate. This is an absolute lower bound if we don't want SBL
6457+ * overflows, so round the value up.
6458+ */
6459+ vpclk_div = max_t(unsigned int, DIV_ROUND_UP(l3_ick, pipe->max_rate),
6460+ vpclk_div);
6461+
6462+ /* Compute the maximum clock divisor, based on the requested frame rate.
6463+ * This is a soft lower bound to achieve a frame rate equal or higher
6464+ * than the requested value, so round the value down.
6465+ */
6466+ timeperframe = &pipe->max_timeperframe;
6467+
6468+ if (timeperframe->numerator) {
6469+ area = ofmt->width * ofmt->height;
6470+ bound = div_u64(area * timeperframe->denominator,
6471+ timeperframe->numerator);
6472+ value = min_t(u64, bound, l3_ick);
6473+ vpclk_div = max_t(unsigned int, l3_ick / value, vpclk_div);
6474+ }
6475+
6476+ dev_dbg(isp->dev, "%s: minimum clock divisor = %u\n", __func__,
6477+ vpclk_div);
6478+
6479+ return vpclk_div;
6480+}
6481+
6482+/*
6483+ * ccp2_mem_configure - Initialize CCP2 memory input/output interface
6484+ * @ccp2: Pointer to ISP CCP2 device
6485+ * @config: Pointer to ISP mem interface config structure
6486+ *
6487+ * This will analyze the parameters passed by the interface config
6488+ * structure, and configure the respective registers for proper
6489+ * CSI1/CCP2 memory input.
6490+ */
6491+static void ccp2_mem_configure(struct isp_ccp2_device *ccp2,
6492+ struct isp_interface_mem_config *config)
6493+{
6494+ struct isp_device *isp = to_isp_device(ccp2);
6495+ u32 sink_pixcode = ccp2->formats[CCP2_PAD_SINK].code;
6496+ u32 source_pixcode = ccp2->formats[CCP2_PAD_SOURCE].code;
6497+ unsigned int dpcm_decompress = 0;
6498+ u32 val, hwords;
6499+
6500+ if (sink_pixcode != source_pixcode &&
6501+ sink_pixcode == V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
6502+ dpcm_decompress = 1;
6503+
6504+ ccp2_pwr_cfg(ccp2);
6505+
6506+ /* Hsize, Skip */
6507+ isp_reg_writel(isp, ISPCCP2_LCM_HSIZE_SKIP_MIN |
6508+ (config->hsize_count << ISPCCP2_LCM_HSIZE_SHIFT),
6509+ OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_HSIZE);
6510+
6511+ /* Vsize, no. of lines */
6512+ isp_reg_writel(isp, config->vsize_count << ISPCCP2_LCM_VSIZE_SHIFT,
6513+ OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_VSIZE);
6514+
6515+ if (ccp2->video_in.bpl_padding == 0)
6516+ config->src_ofst = 0;
6517+ else
6518+ config->src_ofst = ccp2->video_in.bpl_value;
6519+
6520+ isp_reg_writel(isp, config->src_ofst, OMAP3_ISP_IOMEM_CCP2,
6521+ ISPCCP2_LCM_SRC_OFST);
6522+
6523+ /* Source and Destination formats */
6524+ val = ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10 <<
6525+ ISPCCP2_LCM_CTRL_DST_FORMAT_SHIFT;
6526+
6527+ if (dpcm_decompress) {
6528+ /* source format is RAW8 */
6529+ val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8 <<
6530+ ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;
6531+
6532+ /* RAW8 + DPCM10 - simple predictor */
6533+ val |= ISPCCP2_LCM_CTRL_SRC_DPCM_PRED;
6534+
6535+ /* enable source DPCM decompression */
6536+ val |= ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10 <<
6537+ ISPCCP2_LCM_CTRL_SRC_DECOMPR_SHIFT;
6538+ } else {
6539+ /* source format is RAW10 */
6540+ val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10 <<
6541+ ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;
6542+ }
6543+
6544+ /* Burst size to 32x64 */
6545+ val |= ISPCCP2_LCM_CTRL_BURST_SIZE_32X <<
6546+ ISPCCP2_LCM_CTRL_BURST_SIZE_SHIFT;
6547+
6548+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL);
6549+
6550+ /* Prefetch setup */
6551+ if (dpcm_decompress)
6552+ hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +
6553+ config->hsize_count) >> 3;
6554+ else
6555+ hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +
6556+ config->hsize_count) >> 2;
6557+
6558+ isp_reg_writel(isp, hwords << ISPCCP2_LCM_PREFETCH_SHIFT,
6559+ OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_PREFETCH);
6560+
6561+ /* Video port */
6562+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
6563+ ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE);
6564+ ccp2_vp_config(ccp2, ccp2_adjust_bandwidth(ccp2));
6565+
6566+ /* Clear LCM interrupts */
6567+ isp_reg_writel(isp, ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ |
6568+ ISPCCP2_LCM_IRQSTATUS_EOF_IRQ,
6569+ OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQSTATUS);
6570+
6571+ /* Enable LCM interupts */
6572+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQENABLE,
6573+ ISPCCP2_LCM_IRQSTATUS_EOF_IRQ |
6574+ ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ);
6575+}
6576+
6577+/*
6578+ * ccp2_set_inaddr - Sets memory address of input frame.
6579+ * @ccp2: Pointer to ISP CCP2 device
6580+ * @addr: 32bit memory address aligned on 32byte boundary.
6581+ *
6582+ * Configures the memory address from which the input frame is to be read.
6583+ */
6584+static void ccp2_set_inaddr(struct isp_ccp2_device *ccp2, u32 addr)
6585+{
6586+ struct isp_device *isp = to_isp_device(ccp2);
6587+
6588+ isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_SRC_ADDR);
6589+}
6590+
6591+/* -----------------------------------------------------------------------------
6592+ * Interrupt handling
6593+ */
6594+
6595+static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
6596+{
6597+ struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
6598+ struct isp_buffer *buffer;
6599+
6600+ buffer = omap3isp_video_buffer_next(&ccp2->video_in, ccp2->error);
6601+ if (buffer != NULL)
6602+ ccp2_set_inaddr(ccp2, buffer->isp_addr);
6603+
6604+ pipe->state |= ISP_PIPELINE_IDLE_INPUT;
6605+
6606+ if (ccp2->state == ISP_PIPELINE_STREAM_SINGLESHOT) {
6607+ if (isp_pipeline_ready(pipe))
6608+ omap3isp_pipeline_set_stream(pipe,
6609+ ISP_PIPELINE_STREAM_SINGLESHOT);
6610+ }
6611+
6612+ ccp2->error = 0;
6613+}
6614+
6615+/*
6616+ * omap3isp_ccp2_isr - Handle ISP CCP2 interrupts
6617+ * @ccp2: Pointer to ISP CCP2 device
6618+ *
6619+ * This will handle the CCP2 interrupts
6620+ *
6621+ * Returns -EIO in case of error, or 0 on success.
6622+ */
6623+int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
6624+{
6625+ struct isp_device *isp = to_isp_device(ccp2);
6626+ int ret = 0;
6627+ static const u32 ISPCCP2_LC01_ERROR =
6628+ ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
6629+ ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
6630+ ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |
6631+ ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |
6632+ ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |
6633+ ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;
6634+ u32 lcx_irqstatus, lcm_irqstatus;
6635+
6636+ /* First clear the interrupts */
6637+ lcx_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,
6638+ ISPCCP2_LC01_IRQSTATUS);
6639+ isp_reg_writel(isp, lcx_irqstatus, OMAP3_ISP_IOMEM_CCP2,
6640+ ISPCCP2_LC01_IRQSTATUS);
6641+
6642+ lcm_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,
6643+ ISPCCP2_LCM_IRQSTATUS);
6644+ isp_reg_writel(isp, lcm_irqstatus, OMAP3_ISP_IOMEM_CCP2,
6645+ ISPCCP2_LCM_IRQSTATUS);
6646+ /* Errors */
6647+ if (lcx_irqstatus & ISPCCP2_LC01_ERROR) {
6648+ ccp2->error = 1;
6649+ dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus);
6650+ return -EIO;
6651+ }
6652+
6653+ if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) {
6654+ ccp2->error = 1;
6655+ dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus);
6656+ ret = -EIO;
6657+ }
6658+
6659+ if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping))
6660+ return 0;
6661+
6662+ /* Frame number propagation */
6663+ if (lcx_irqstatus & ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ) {
6664+ struct isp_pipeline *pipe =
6665+ to_isp_pipeline(&ccp2->subdev.entity);
6666+ if (pipe->do_propagation)
6667+ atomic_inc(&pipe->frame_number);
6668+ }
6669+
6670+ /* Handle queued buffers on frame end interrupts */
6671+ if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ)
6672+ ccp2_isr_buffer(ccp2);
6673+
6674+ return ret;
6675+}
6676+
6677+/* -----------------------------------------------------------------------------
6678+ * V4L2 subdev operations
6679+ */
6680+
6681+static const unsigned int ccp2_fmts[] = {
6682+ V4L2_MBUS_FMT_SGRBG10_1X10,
6683+ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
6684+};
6685+
6686+/*
6687+ * __ccp2_get_format - helper function for getting ccp2 format
6688+ * @ccp2 : Pointer to ISP CCP2 device
6689+ * @fh : V4L2 subdev file handle
6690+ * @pad : pad number
6691+ * @which : wanted subdev format
6692+ * return format structure or NULL on error
6693+ */
6694+static struct v4l2_mbus_framefmt *
6695+__ccp2_get_format(struct isp_ccp2_device *ccp2, struct v4l2_subdev_fh *fh,
6696+ unsigned int pad, enum v4l2_subdev_format_whence which)
6697+{
6698+ if (which == V4L2_SUBDEV_FORMAT_TRY)
6699+ return v4l2_subdev_get_try_format(fh, pad);
6700+ else
6701+ return &ccp2->formats[pad];
6702+}
6703+
6704+/*
6705+ * ccp2_try_format - Handle try format by pad subdev method
6706+ * @ccp2 : Pointer to ISP CCP2 device
6707+ * @fh : V4L2 subdev file handle
6708+ * @pad : pad num
6709+ * @fmt : pointer to v4l2 mbus format structure
6710+ * @which : wanted subdev format
6711+ */
6712+static void ccp2_try_format(struct isp_ccp2_device *ccp2,
6713+ struct v4l2_subdev_fh *fh, unsigned int pad,
6714+ struct v4l2_mbus_framefmt *fmt,
6715+ enum v4l2_subdev_format_whence which)
6716+{
6717+ struct v4l2_mbus_framefmt *format;
6718+
6719+ switch (pad) {
6720+ case CCP2_PAD_SINK:
6721+ if (fmt->code != V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
6722+ fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
6723+
6724+ if (ccp2->input == CCP2_INPUT_SENSOR) {
6725+ fmt->width = clamp_t(u32, fmt->width,
6726+ ISPCCP2_DAT_START_MIN,
6727+ ISPCCP2_DAT_START_MAX);
6728+ fmt->height = clamp_t(u32, fmt->height,
6729+ ISPCCP2_DAT_SIZE_MIN,
6730+ ISPCCP2_DAT_SIZE_MAX);
6731+ } else if (ccp2->input == CCP2_INPUT_MEMORY) {
6732+ fmt->width = clamp_t(u32, fmt->width,
6733+ ISPCCP2_LCM_HSIZE_COUNT_MIN,
6734+ ISPCCP2_LCM_HSIZE_COUNT_MAX);
6735+ fmt->height = clamp_t(u32, fmt->height,
6736+ ISPCCP2_LCM_VSIZE_MIN,
6737+ ISPCCP2_LCM_VSIZE_MAX);
6738+ }
6739+ break;
6740+
6741+ case CCP2_PAD_SOURCE:
6742+ /* Source format - copy sink format and change pixel code
6743+ * to SGRBG10_1X10 as we don't support CCP2 write to memory.
6744+ * When CCP2 write to memory feature will be added this
6745+ * should be changed properly.
6746+ */
6747+ format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK, which);
6748+ memcpy(fmt, format, sizeof(*fmt));
6749+ fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
6750+ break;
6751+ }
6752+
6753+ fmt->field = V4L2_FIELD_NONE;
6754+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
6755+}
6756+
6757+/*
6758+ * ccp2_enum_mbus_code - Handle pixel format enumeration
6759+ * @sd : pointer to v4l2 subdev structure
6760+ * @fh : V4L2 subdev file handle
6761+ * @code : pointer to v4l2_subdev_mbus_code_enum structure
6762+ * return -EINVAL or zero on success
6763+ */
6764+static int ccp2_enum_mbus_code(struct v4l2_subdev *sd,
6765+ struct v4l2_subdev_fh *fh,
6766+ struct v4l2_subdev_mbus_code_enum *code)
6767+{
6768+ struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
6769+ struct v4l2_mbus_framefmt *format;
6770+
6771+ if (code->pad == CCP2_PAD_SINK) {
6772+ if (code->index >= ARRAY_SIZE(ccp2_fmts))
6773+ return -EINVAL;
6774+
6775+ code->code = ccp2_fmts[code->index];
6776+ } else {
6777+ if (code->index != 0)
6778+ return -EINVAL;
6779+
6780+ format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK,
6781+ V4L2_SUBDEV_FORMAT_TRY);
6782+ code->code = format->code;
6783+ }
6784+
6785+ return 0;
6786+}
6787+
6788+static int ccp2_enum_frame_size(struct v4l2_subdev *sd,
6789+ struct v4l2_subdev_fh *fh,
6790+ struct v4l2_subdev_frame_size_enum *fse)
6791+{
6792+ struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
6793+ struct v4l2_mbus_framefmt format;
6794+
6795+ if (fse->index != 0)
6796+ return -EINVAL;
6797+
6798+ format.code = fse->code;
6799+ format.width = 1;
6800+ format.height = 1;
6801+ ccp2_try_format(ccp2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
6802+ fse->min_width = format.width;
6803+ fse->min_height = format.height;
6804+
6805+ if (format.code != fse->code)
6806+ return -EINVAL;
6807+
6808+ format.code = fse->code;
6809+ format.width = -1;
6810+ format.height = -1;
6811+ ccp2_try_format(ccp2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
6812+ fse->max_width = format.width;
6813+ fse->max_height = format.height;
6814+
6815+ return 0;
6816+}
6817+
6818+/*
6819+ * ccp2_get_format - Handle get format by pads subdev method
6820+ * @sd : pointer to v4l2 subdev structure
6821+ * @fh : V4L2 subdev file handle
6822+ * @fmt : pointer to v4l2 subdev format structure
6823+ * return -EINVAL or zero on sucess
6824+ */
6825+static int ccp2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
6826+ struct v4l2_subdev_format *fmt)
6827+{
6828+ struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
6829+ struct v4l2_mbus_framefmt *format;
6830+
6831+ format = __ccp2_get_format(ccp2, fh, fmt->pad, fmt->which);
6832+ if (format == NULL)
6833+ return -EINVAL;
6834+
6835+ fmt->format = *format;
6836+ return 0;
6837+}
6838+
6839+/*
6840+ * ccp2_set_format - Handle set format by pads subdev method
6841+ * @sd : pointer to v4l2 subdev structure
6842+ * @fh : V4L2 subdev file handle
6843+ * @fmt : pointer to v4l2 subdev format structure
6844+ * returns zero
6845+ */
6846+static int ccp2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
6847+ struct v4l2_subdev_format *fmt)
6848+{
6849+ struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
6850+ struct v4l2_mbus_framefmt *format;
6851+
6852+ format = __ccp2_get_format(ccp2, fh, fmt->pad, fmt->which);
6853+ if (format == NULL)
6854+ return -EINVAL;
6855+
6856+ ccp2_try_format(ccp2, fh, fmt->pad, &fmt->format, fmt->which);
6857+ *format = fmt->format;
6858+
6859+ /* Propagate the format from sink to source */
6860+ if (fmt->pad == CCP2_PAD_SINK) {
6861+ format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SOURCE,
6862+ fmt->which);
6863+ *format = fmt->format;
6864+ ccp2_try_format(ccp2, fh, CCP2_PAD_SOURCE, format, fmt->which);
6865+ }
6866+
6867+ return 0;
6868+}
6869+
6870+/*
6871+ * ccp2_init_formats - Initialize formats on all pads
6872+ * @sd: ISP CCP2 V4L2 subdevice
6873+ * @fh: V4L2 subdev file handle
6874+ *
6875+ * Initialize all pad formats with default values. If fh is not NULL, try
6876+ * formats are initialized on the file handle. Otherwise active formats are
6877+ * initialized on the device.
6878+ */
6879+static int ccp2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
6880+{
6881+ struct v4l2_subdev_format format;
6882+
6883+ memset(&format, 0, sizeof(format));
6884+ format.pad = CCP2_PAD_SINK;
6885+ format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
6886+ format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
6887+ format.format.width = 4096;
6888+ format.format.height = 4096;
6889+ ccp2_set_format(sd, fh, &format);
6890+
6891+ return 0;
6892+}
6893+
6894+/*
6895+ * ccp2_s_stream - Enable/Disable streaming on ccp2 subdev
6896+ * @sd : pointer to v4l2 subdev structure
6897+ * @enable: 1 == Enable, 0 == Disable
6898+ * return zero
6899+ */
6900+static int ccp2_s_stream(struct v4l2_subdev *sd, int enable)
6901+{
6902+ struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
6903+ struct isp_device *isp = to_isp_device(ccp2);
6904+ struct device *dev = to_device(ccp2);
6905+ int ret;
6906+
6907+ if (ccp2->state == ISP_PIPELINE_STREAM_STOPPED) {
6908+ if (enable == ISP_PIPELINE_STREAM_STOPPED)
6909+ return 0;
6910+ atomic_set(&ccp2->stopping, 0);
6911+ ccp2->error = 0;
6912+ }
6913+
6914+ switch (enable) {
6915+ case ISP_PIPELINE_STREAM_CONTINUOUS:
6916+ if (ccp2->phy) {
6917+ ret = omap3isp_csiphy_acquire(ccp2->phy);
6918+ if (ret < 0)
6919+ return ret;
6920+ }
6921+
6922+ ccp2_if_configure(ccp2);
6923+ ccp2_print_status(ccp2);
6924+
6925+ /* Enable CSI1/CCP2 interface */
6926+ ccp2_if_enable(ccp2, 1);
6927+ break;
6928+
6929+ case ISP_PIPELINE_STREAM_SINGLESHOT:
6930+ if (ccp2->state != ISP_PIPELINE_STREAM_SINGLESHOT) {
6931+ struct v4l2_mbus_framefmt *format;
6932+
6933+ format = &ccp2->formats[CCP2_PAD_SINK];
6934+
6935+ ccp2->mem_cfg.hsize_count = format->width;
6936+ ccp2->mem_cfg.vsize_count = format->height;
6937+ ccp2->mem_cfg.src_ofst = 0;
6938+
6939+ ccp2_mem_configure(ccp2, &ccp2->mem_cfg);
6940+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI1_READ);
6941+ ccp2_print_status(ccp2);
6942+ }
6943+ ccp2_mem_enable(ccp2, 1);
6944+ break;
6945+
6946+ case ISP_PIPELINE_STREAM_STOPPED:
6947+ if (omap3isp_module_sync_idle(&sd->entity, &ccp2->wait,
6948+ &ccp2->stopping))
6949+ dev_dbg(dev, "%s: module stop timeout.\n", sd->name);
6950+ if (ccp2->input == CCP2_INPUT_MEMORY) {
6951+ ccp2_mem_enable(ccp2, 0);
6952+ omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI1_READ);
6953+ } else if (ccp2->input == CCP2_INPUT_SENSOR) {
6954+ /* Disable CSI1/CCP2 interface */
6955+ ccp2_if_enable(ccp2, 0);
6956+ if (ccp2->phy)
6957+ omap3isp_csiphy_release(ccp2->phy);
6958+ }
6959+ break;
6960+ }
6961+
6962+ ccp2->state = enable;
6963+ return 0;
6964+}
6965+
6966+/* subdev core operations */
6967+static const struct v4l2_subdev_core_ops ccp2_sd_core_ops = {
6968+ .queryctrl = v4l2_subdev_queryctrl,
6969+ .querymenu = v4l2_subdev_querymenu,
6970+ .g_ctrl = v4l2_subdev_g_ctrl,
6971+ .s_ctrl = v4l2_subdev_s_ctrl,
6972+ .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
6973+ .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
6974+ .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
6975+};
6976+
6977+/* subdev file operations */
6978+static const struct v4l2_subdev_file_ops ccp2_sd_file_ops = {
6979+ .open = ccp2_init_formats,
6980+};
6981+
6982+/* subdev video operations */
6983+static const struct v4l2_subdev_video_ops ccp2_sd_video_ops = {
6984+ .s_stream = ccp2_s_stream,
6985+};
6986+
6987+/* subdev pad operations */
6988+static const struct v4l2_subdev_pad_ops ccp2_sd_pad_ops = {
6989+ .enum_mbus_code = ccp2_enum_mbus_code,
6990+ .enum_frame_size = ccp2_enum_frame_size,
6991+ .get_fmt = ccp2_get_format,
6992+ .set_fmt = ccp2_set_format,
6993+};
6994+
6995+/* subdev operations */
6996+static const struct v4l2_subdev_ops ccp2_sd_ops = {
6997+ .core = &ccp2_sd_core_ops,
6998+ .file = &ccp2_sd_file_ops,
6999+ .video = &ccp2_sd_video_ops,
7000+ .pad = &ccp2_sd_pad_ops,
7001+};
7002+
7003+/* --------------------------------------------------------------------------
7004+ * ISP ccp2 video device node
7005+ */
7006+
7007+/*
7008+ * ccp2_video_queue - Queue video buffer.
7009+ * @video : Pointer to isp video structure
7010+ * @buffer: Pointer to isp_buffer structure
7011+ * return -EIO or zero on success
7012+ */
7013+static int ccp2_video_queue(struct isp_video *video, struct isp_buffer *buffer)
7014+{
7015+ struct isp_ccp2_device *ccp2 = &video->isp->isp_ccp2;
7016+
7017+ ccp2_set_inaddr(ccp2, buffer->isp_addr);
7018+ return 0;
7019+}
7020+
7021+static const struct isp_video_operations ccp2_video_ops = {
7022+ .queue = ccp2_video_queue,
7023+};
7024+
7025+/* -----------------------------------------------------------------------------
7026+ * Media entity operations
7027+ */
7028+
7029+/*
7030+ * ccp2_link_setup - Setup ccp2 connections.
7031+ * @entity : Pointer to media entity structure
7032+ * @local : Pointer to local pad array
7033+ * @remote : Pointer to remote pad array
7034+ * @flags : Link flags
7035+ * return -EINVAL on error or zero on success
7036+ */
7037+static int ccp2_link_setup(struct media_entity *entity,
7038+ const struct media_pad *local,
7039+ const struct media_pad *remote, u32 flags)
7040+{
7041+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
7042+ struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
7043+
7044+ switch (local->index | media_entity_type(remote->entity)) {
7045+ case CCP2_PAD_SINK | MEDIA_ENT_T_DEVNODE:
7046+ /* read from memory */
7047+ if (flags & MEDIA_LNK_FL_ENABLED) {
7048+ if (ccp2->input == CCP2_INPUT_SENSOR)
7049+ return -EBUSY;
7050+ ccp2->input = CCP2_INPUT_MEMORY;
7051+ } else {
7052+ if (ccp2->input == CCP2_INPUT_MEMORY)
7053+ ccp2->input = CCP2_INPUT_NONE;
7054+ }
7055+ break;
7056+
7057+ case CCP2_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
7058+ /* read from sensor/phy */
7059+ if (flags & MEDIA_LNK_FL_ENABLED) {
7060+ if (ccp2->input == CCP2_INPUT_MEMORY)
7061+ return -EBUSY;
7062+ ccp2->input = CCP2_INPUT_SENSOR;
7063+ } else {
7064+ if (ccp2->input == CCP2_INPUT_SENSOR)
7065+ ccp2->input = CCP2_INPUT_NONE;
7066+ } break;
7067+
7068+ case CCP2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
7069+ /* write to video port/ccdc */
7070+ if (flags & MEDIA_LNK_FL_ENABLED)
7071+ ccp2->output = CCP2_OUTPUT_CCDC;
7072+ else
7073+ ccp2->output = CCP2_OUTPUT_NONE;
7074+ break;
7075+
7076+ default:
7077+ return -EINVAL;
7078+ }
7079+
7080+ return 0;
7081+}
7082+
7083+/* media operations */
7084+static const struct media_entity_operations ccp2_media_ops = {
7085+ .link_setup = ccp2_link_setup,
7086+};
7087+
7088+/*
7089+ * ccp2_init_entities - Initialize ccp2 subdev and media entity.
7090+ * @ccp2: Pointer to ISP CCP2 device
7091+ * return negative error code or zero on success
7092+ */
7093+static int ccp2_init_entities(struct isp_ccp2_device *ccp2)
7094+{
7095+ struct v4l2_subdev *sd = &ccp2->subdev;
7096+ struct media_pad *pads = ccp2->pads;
7097+ struct media_entity *me = &sd->entity;
7098+ int ret;
7099+
7100+ ccp2->input = CCP2_INPUT_NONE;
7101+ ccp2->output = CCP2_OUTPUT_NONE;
7102+
7103+ v4l2_subdev_init(sd, &ccp2_sd_ops);
7104+ strlcpy(sd->name, "OMAP3 ISP CCP2", sizeof(sd->name));
7105+ sd->grp_id = 1 << 16; /* group ID for isp subdevs */
7106+ v4l2_set_subdevdata(sd, ccp2);
7107+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
7108+
7109+ v4l2_ctrl_handler_init(&ccp2->ctrls, 1);
7110+ sd->ctrl_handler = &ccp2->ctrls;
7111+
7112+ pads[CCP2_PAD_SINK].flags = MEDIA_PAD_FL_INPUT;
7113+ pads[CCP2_PAD_SOURCE].flags = MEDIA_PAD_FL_OUTPUT;
7114+
7115+ me->ops = &ccp2_media_ops;
7116+ ret = media_entity_init(me, CCP2_PADS_NUM, pads, 0);
7117+ if (ret < 0)
7118+ return ret;
7119+
7120+ ccp2_init_formats(sd, NULL);
7121+
7122+ /*
7123+ * The CCP2 has weird line alignment requirements, possibly caused by
7124+ * DPCM8 decompression. Line length for data read from memory must be a
7125+ * multiple of 128 bits (16 bytes) in continuous mode (when no padding
7126+ * is present at end of lines). Additionally, if padding is used, the
7127+ * padded line length must be a multiple of 32 bytes. To simplify the
7128+ * implementation we use a fixed 32 bytes alignment regardless of the
7129+ * input format and width. If strict 128 bits alignment support is
7130+ * required ispvideo will need to be made aware of this special dual
7131+ * alignement requirements.
7132+ */
7133+ ccp2->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
7134+ ccp2->video_in.bpl_alignment = 32;
7135+ ccp2->video_in.bpl_max = 0xffffffe0;
7136+ ccp2->video_in.isp = to_isp_device(ccp2);
7137+ ccp2->video_in.ops = &ccp2_video_ops;
7138+ ccp2->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
7139+
7140+ ret = omap3isp_video_init(&ccp2->video_in, "CCP2");
7141+ if (ret < 0)
7142+ return ret;
7143+
7144+ /* Connect the video node to the ccp2 subdev. */
7145+ ret = media_entity_create_link(&ccp2->video_in.video.entity, 0,
7146+ &ccp2->subdev.entity, CCP2_PAD_SINK, 0);
7147+ if (ret < 0)
7148+ return ret;
7149+
7150+ return 0;
7151+}
7152+
7153+/*
7154+ * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev
7155+ * @ccp2: Pointer to ISP CCP2 device
7156+ */
7157+void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)
7158+{
7159+ media_entity_cleanup(&ccp2->subdev.entity);
7160+
7161+ v4l2_device_unregister_subdev(&ccp2->subdev);
7162+ v4l2_ctrl_handler_free(&ccp2->ctrls);
7163+ omap3isp_video_unregister(&ccp2->video_in);
7164+}
7165+
7166+/*
7167+ * omap3isp_ccp2_register_entities - Register the subdev media entity
7168+ * @ccp2: Pointer to ISP CCP2 device
7169+ * @vdev: Pointer to v4l device
7170+ * return negative error code or zero on success
7171+ */
7172+
7173+int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
7174+ struct v4l2_device *vdev)
7175+{
7176+ int ret;
7177+
7178+ /* Register the subdev and video nodes. */
7179+ ret = v4l2_device_register_subdev(vdev, &ccp2->subdev);
7180+ if (ret < 0)
7181+ goto error;
7182+
7183+ ret = omap3isp_video_register(&ccp2->video_in, vdev);
7184+ if (ret < 0)
7185+ goto error;
7186+
7187+ return 0;
7188+
7189+error:
7190+ omap3isp_ccp2_unregister_entities(ccp2);
7191+ return ret;
7192+}
7193+
7194+/* -----------------------------------------------------------------------------
7195+ * ISP ccp2 initialisation and cleanup
7196+ */
7197+
7198+/*
7199+ * omap3isp_ccp2_cleanup - CCP2 un-initialization
7200+ * @isp : Pointer to ISP device
7201+ */
7202+void omap3isp_ccp2_cleanup(struct isp_device *isp)
7203+{
7204+}
7205+
7206+/*
7207+ * omap3isp_ccp2_init - CCP2 initialization.
7208+ * @isp : Pointer to ISP device
7209+ * return negative error code or zero on success
7210+ */
7211+int omap3isp_ccp2_init(struct isp_device *isp)
7212+{
7213+ struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
7214+ int ret;
7215+
7216+ init_waitqueue_head(&ccp2->wait);
7217+
7218+ /* On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with
7219+ * the CSI2c or CSI2a receivers. The PHY then needs to be explicitly
7220+ * configured.
7221+ *
7222+ * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c).
7223+ */
7224+ if (isp->revision == ISP_REVISION_15_0)
7225+ ccp2->phy = &isp->isp_csiphy1;
7226+
7227+ ret = ccp2_init_entities(ccp2);
7228+ if (ret < 0)
7229+ goto out;
7230+
7231+ ccp2_reset(ccp2);
7232+out:
7233+ if (ret)
7234+ omap3isp_ccp2_cleanup(isp);
7235+
7236+ return ret;
7237+}
7238diff --git a/drivers/media/video/isp/ispccp2.h b/drivers/media/video/isp/ispccp2.h
7239new file mode 100644
7240index 0000000..1c1504e
7241--- /dev/null
7242+++ b/drivers/media/video/isp/ispccp2.h
7243@@ -0,0 +1,101 @@
7244+/*
7245+ * ispccp2.h
7246+ *
7247+ * TI OMAP3 ISP - CCP2 module
7248+ *
7249+ * Copyright (C) 2010 Nokia Corporation
7250+ * Copyright (C) 2010 Texas Instruments, Inc.
7251+ *
7252+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7253+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7254+ *
7255+ * This program is free software; you can redistribute it and/or modify
7256+ * it under the terms of the GNU General Public License version 2 as
7257+ * published by the Free Software Foundation.
7258+ *
7259+ * This program is distributed in the hope that it will be useful, but
7260+ * WITHOUT ANY WARRANTY; without even the implied warranty of
7261+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7262+ * General Public License for more details.
7263+ *
7264+ * You should have received a copy of the GNU General Public License
7265+ * along with this program; if not, write to the Free Software
7266+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
7267+ * 02110-1301 USA
7268+ */
7269+
7270+#ifndef OMAP3_ISP_CCP2_H
7271+#define OMAP3_ISP_CCP2_H
7272+
7273+#include <linux/videodev2.h>
7274+#include <media/v4l2-ctrls.h>
7275+
7276+struct isp_device;
7277+struct isp_csiphy;
7278+
7279+/* Sink and source ccp2 pads */
7280+#define CCP2_PAD_SINK 0
7281+#define CCP2_PAD_SOURCE 1
7282+#define CCP2_PADS_NUM 2
7283+
7284+/* CCP2 input media entity */
7285+enum ccp2_input_entity {
7286+ CCP2_INPUT_NONE,
7287+ CCP2_INPUT_SENSOR,
7288+ CCP2_INPUT_MEMORY,
7289+};
7290+
7291+/* CCP2 output media entity */
7292+enum ccp2_output_entity {
7293+ CCP2_OUTPUT_NONE,
7294+ CCP2_OUTPUT_CCDC,
7295+ CCP2_OUTPUT_MEMORY,
7296+};
7297+
7298+
7299+/* Logical channel configuration */
7300+struct isp_interface_lcx_config {
7301+ int crc;
7302+ u32 data_start;
7303+ u32 data_size;
7304+ u32 format;
7305+};
7306+
7307+/* Memory channel configuration */
7308+struct isp_interface_mem_config {
7309+ u32 dst_port;
7310+ u32 vsize_count;
7311+ u32 hsize_count;
7312+ u32 src_ofst;
7313+ u32 dst_ofst;
7314+};
7315+
7316+/* CCP2 device */
7317+struct isp_ccp2_device {
7318+ struct v4l2_subdev subdev;
7319+ struct v4l2_mbus_framefmt formats[CCP2_PADS_NUM];
7320+ struct media_pad pads[CCP2_PADS_NUM];
7321+
7322+ struct v4l2_ctrl_handler ctrls;
7323+
7324+ enum ccp2_input_entity input;
7325+ enum ccp2_output_entity output;
7326+ struct isp_interface_lcx_config if_cfg;
7327+ struct isp_interface_mem_config mem_cfg;
7328+ struct isp_video video_in;
7329+ struct isp_csiphy *phy;
7330+ unsigned int error;
7331+ enum isp_pipeline_stream_state state;
7332+ wait_queue_head_t wait;
7333+ atomic_t stopping;
7334+};
7335+
7336+/* Function declarations */
7337+int omap3isp_ccp2_init(struct isp_device *isp);
7338+void omap3isp_ccp2_cleanup(struct isp_device *isp);
7339+int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
7340+ struct v4l2_device *vdev);
7341+void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2);
7342+int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
7343+
7344+#endif /* OMAP3_ISP_CCP2_H */
7345diff --git a/drivers/media/video/isp/ispcsi2.c b/drivers/media/video/isp/ispcsi2.c
7346new file mode 100644
7347index 0000000..30ced95
7348--- /dev/null
7349+++ b/drivers/media/video/isp/ispcsi2.c
7350@@ -0,0 +1,1332 @@
7351+/*
7352+ * ispcsi2.c
7353+ *
7354+ * TI OMAP3 ISP - CSI2 module
7355+ *
7356+ * Copyright (C) 2010 Nokia Corporation
7357+ * Copyright (C) 2009 Texas Instruments, Inc.
7358+ *
7359+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7360+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7361+ *
7362+ * This program is free software; you can redistribute it and/or modify
7363+ * it under the terms of the GNU General Public License version 2 as
7364+ * published by the Free Software Foundation.
7365+ *
7366+ * This program is distributed in the hope that it will be useful, but
7367+ * WITHOUT ANY WARRANTY; without even the implied warranty of
7368+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7369+ * General Public License for more details.
7370+ *
7371+ * You should have received a copy of the GNU General Public License
7372+ * along with this program; if not, write to the Free Software
7373+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
7374+ * 02110-1301 USA
7375+ */
7376+#include <linux/delay.h>
7377+#include <media/v4l2-common.h>
7378+#include <linux/v4l2-mediabus.h>
7379+#include <linux/mm.h>
7380+
7381+#include "isp.h"
7382+#include "ispreg.h"
7383+#include "ispcsi2.h"
7384+
7385+/*
7386+ * csi2_if_enable - Enable CSI2 Receiver interface.
7387+ * @enable: enable flag
7388+ *
7389+ */
7390+static void csi2_if_enable(struct isp_device *isp,
7391+ struct isp_csi2_device *csi2, u8 enable)
7392+{
7393+ struct isp_csi2_ctrl_cfg *currctrl = &csi2->ctrl;
7394+
7395+ isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_CTRL, ISPCSI2_CTRL_IF_EN,
7396+ enable ? ISPCSI2_CTRL_IF_EN : 0);
7397+
7398+ currctrl->if_enable = enable;
7399+}
7400+
7401+/*
7402+ * csi2_recv_config - CSI2 receiver module configuration.
7403+ * @currctrl: isp_csi2_ctrl_cfg structure
7404+ *
7405+ */
7406+static void csi2_recv_config(struct isp_device *isp,
7407+ struct isp_csi2_device *csi2,
7408+ struct isp_csi2_ctrl_cfg *currctrl)
7409+{
7410+ u32 reg;
7411+
7412+ reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTRL);
7413+
7414+ if (currctrl->frame_mode)
7415+ reg |= ISPCSI2_CTRL_FRAME;
7416+ else
7417+ reg &= ~ISPCSI2_CTRL_FRAME;
7418+
7419+ if (currctrl->vp_clk_enable)
7420+ reg |= ISPCSI2_CTRL_VP_CLK_EN;
7421+ else
7422+ reg &= ~ISPCSI2_CTRL_VP_CLK_EN;
7423+
7424+ if (currctrl->vp_only_enable)
7425+ reg |= ISPCSI2_CTRL_VP_ONLY_EN;
7426+ else
7427+ reg &= ~ISPCSI2_CTRL_VP_ONLY_EN;
7428+
7429+ reg &= ~ISPCSI2_CTRL_VP_OUT_CTRL_MASK;
7430+ reg |= currctrl->vp_out_ctrl << ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT;
7431+
7432+ if (currctrl->ecc_enable)
7433+ reg |= ISPCSI2_CTRL_ECC_EN;
7434+ else
7435+ reg &= ~ISPCSI2_CTRL_ECC_EN;
7436+
7437+ isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTRL);
7438+}
7439+
7440+static const unsigned int csi2_input_fmts[] = {
7441+ V4L2_MBUS_FMT_SGRBG10_1X10,
7442+ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
7443+ V4L2_MBUS_FMT_SRGGB10_1X10,
7444+ V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
7445+ V4L2_MBUS_FMT_SBGGR10_1X10,
7446+ V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
7447+ V4L2_MBUS_FMT_SGBRG10_1X10,
7448+ V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
7449+};
7450+
7451+/* To set the format on the CSI2 requires a mapping function that takes
7452+ * the following inputs:
7453+ * - 2 different formats (at this time)
7454+ * - 2 destinations (mem, vp+mem) (vp only handled separately)
7455+ * - 2 decompression options (on, off)
7456+ * - 2 isp revisions (certain format must be handled differently on OMAP3630)
7457+ * Output should be CSI2 frame format code
7458+ * Array indices as follows: [format][dest][decompr][is_3630]
7459+ * Not all combinations are valid. 0 means invalid.
7460+ */
7461+static const u16 __csi2_fmt_map[2][2][2][2] = {
7462+ /* RAW10 formats */
7463+ {
7464+ /* Output to memory */
7465+ {
7466+ /* No DPCM decompression */
7467+ { CSI2_PIX_FMT_RAW10_EXP16, CSI2_PIX_FMT_RAW10_EXP16 },
7468+ /* DPCM decompression */
7469+ { 0, 0 },
7470+ },
7471+ /* Output to both */
7472+ {
7473+ /* No DPCM decompression */
7474+ { CSI2_PIX_FMT_RAW10_EXP16_VP,
7475+ CSI2_PIX_FMT_RAW10_EXP16_VP },
7476+ /* DPCM decompression */
7477+ { 0, 0 },
7478+ },
7479+ },
7480+ /* RAW10 DPCM8 formats */
7481+ {
7482+ /* Output to memory */
7483+ {
7484+ /* No DPCM decompression */
7485+ { CSI2_PIX_FMT_RAW8, CSI2_USERDEF_8BIT_DATA1 },
7486+ /* DPCM decompression */
7487+ { CSI2_PIX_FMT_RAW8_DPCM10_EXP16,
7488+ CSI2_USERDEF_8BIT_DATA1_DPCM10 },
7489+ },
7490+ /* Output to both */
7491+ {
7492+ /* No DPCM decompression */
7493+ { CSI2_PIX_FMT_RAW8_VP,
7494+ CSI2_PIX_FMT_RAW8_VP },
7495+ /* DPCM decompression */
7496+ { CSI2_PIX_FMT_RAW8_DPCM10_VP,
7497+ CSI2_USERDEF_8BIT_DATA1_DPCM10_VP },
7498+ },
7499+ },
7500+};
7501+
7502+/*
7503+ * csi2_ctx_map_format - Map CSI2 sink media bus format to CSI2 format ID
7504+ * @csi2: ISP CSI2 device
7505+ *
7506+ * Returns CSI2 physical format id
7507+ */
7508+static u16 csi2_ctx_map_format(struct isp_csi2_device *csi2)
7509+{
7510+ const struct v4l2_mbus_framefmt *fmt = &csi2->formats[CSI2_PAD_SINK];
7511+ int fmtidx, destidx, is_3630;
7512+
7513+ switch (fmt->code) {
7514+ case V4L2_MBUS_FMT_SGRBG10_1X10:
7515+ case V4L2_MBUS_FMT_SRGGB10_1X10:
7516+ case V4L2_MBUS_FMT_SBGGR10_1X10:
7517+ case V4L2_MBUS_FMT_SGBRG10_1X10:
7518+ fmtidx = 0;
7519+ break;
7520+ case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
7521+ case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
7522+ case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
7523+ case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
7524+ fmtidx = 1;
7525+ break;
7526+ default:
7527+ WARN(1, KERN_ERR "CSI2: pixel format %08x unsupported!\n",
7528+ fmt->code);
7529+ return 0;
7530+ }
7531+
7532+ if (!(csi2->output & CSI2_OUTPUT_CCDC) &&
7533+ !(csi2->output & CSI2_OUTPUT_MEMORY)) {
7534+ /* Neither output enabled is a valid combination */
7535+ return CSI2_PIX_FMT_OTHERS;
7536+ }
7537+
7538+ /* If we need to skip frames at the beginning of the stream disable the
7539+ * video port to avoid sending the skipped frames to the CCDC.
7540+ */
7541+ destidx = csi2->frame_skip ? 0 : !!(csi2->output & CSI2_OUTPUT_CCDC);
7542+ is_3630 = csi2->isp->revision == ISP_REVISION_15_0;
7543+
7544+ return __csi2_fmt_map[fmtidx][destidx][csi2->dpcm_decompress][is_3630];
7545+}
7546+
7547+/*
7548+ * csi2_set_outaddr - Set memory address to save output image
7549+ * @csi2: Pointer to ISP CSI2a device.
7550+ * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
7551+ *
7552+ * Sets the memory address where the output will be saved.
7553+ *
7554+ * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
7555+ * boundary.
7556+ */
7557+static void csi2_set_outaddr(struct isp_csi2_device *csi2, u32 addr)
7558+{
7559+ struct isp_device *isp = csi2->isp;
7560+ struct isp_csi2_ctx_cfg *ctx = &csi2->contexts[0];
7561+
7562+ ctx->ping_addr = ctx->pong_addr = addr;
7563+ isp_reg_writel(isp, ctx->ping_addr,
7564+ csi2->regs1, ISPCSI2_CTX_DAT_PING_ADDR(ctx->ctxnum));
7565+ isp_reg_writel(isp, ctx->pong_addr,
7566+ csi2->regs1, ISPCSI2_CTX_DAT_PONG_ADDR(ctx->ctxnum));
7567+}
7568+
7569+/*
7570+ * is_usr_def_mapping - Checks whether USER_DEF_MAPPING should
7571+ * be enabled by CSI2.
7572+ * @format_id: mapped format id
7573+ *
7574+ */
7575+static inline int is_usr_def_mapping(u32 format_id)
7576+{
7577+ return (format_id & 0x40) ? 1 : 0;
7578+}
7579+
7580+/*
7581+ * csi2_ctx_enable - Enable specified CSI2 context
7582+ * @ctxnum: Context number, valid between 0 and 7 values.
7583+ * @enable: enable
7584+ *
7585+ */
7586+static void csi2_ctx_enable(struct isp_device *isp,
7587+ struct isp_csi2_device *csi2, u8 ctxnum, u8 enable)
7588+{
7589+ struct isp_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum];
7590+ unsigned int skip = 0;
7591+ u32 reg;
7592+
7593+ reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL1(ctxnum));
7594+
7595+ if (enable) {
7596+ if (csi2->frame_skip)
7597+ skip = csi2->frame_skip;
7598+ else if (csi2->output & CSI2_OUTPUT_MEMORY)
7599+ skip = 1;
7600+
7601+ reg &= ~ISPCSI2_CTX_CTRL1_COUNT_MASK;
7602+ reg |= ISPCSI2_CTX_CTRL1_COUNT_UNLOCK
7603+ | (skip << ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
7604+ | ISPCSI2_CTX_CTRL1_CTX_EN;
7605+ } else {
7606+ reg &= ~ISPCSI2_CTX_CTRL1_CTX_EN;
7607+ }
7608+
7609+ isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL1(ctxnum));
7610+ ctx->enabled = enable;
7611+}
7612+
7613+/*
7614+ * csi2_ctx_config - CSI2 context configuration.
7615+ * @ctx: context configuration
7616+ *
7617+ */
7618+static void csi2_ctx_config(struct isp_device *isp,
7619+ struct isp_csi2_device *csi2,
7620+ struct isp_csi2_ctx_cfg *ctx)
7621+{
7622+ u32 reg;
7623+
7624+ /* Set up CSI2_CTx_CTRL1 */
7625+ reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL1(ctx->ctxnum));
7626+
7627+ if (ctx->eof_enabled)
7628+ reg |= ISPCSI2_CTX_CTRL1_EOF_EN;
7629+ else
7630+ reg &= ~ISPCSI2_CTX_CTRL1_EOF_EN;
7631+
7632+ if (ctx->eol_enabled)
7633+ reg |= ISPCSI2_CTX_CTRL1_EOL_EN;
7634+ else
7635+ reg &= ~ISPCSI2_CTX_CTRL1_EOL_EN;
7636+
7637+ if (ctx->checksum_enabled)
7638+ reg |= ISPCSI2_CTX_CTRL1_CS_EN;
7639+ else
7640+ reg &= ~ISPCSI2_CTX_CTRL1_CS_EN;
7641+
7642+ isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL1(ctx->ctxnum));
7643+
7644+ /* Set up CSI2_CTx_CTRL2 */
7645+ reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL2(ctx->ctxnum));
7646+
7647+ reg &= ~(ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK);
7648+ reg |= ctx->virtual_id << ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
7649+
7650+ reg &= ~(ISPCSI2_CTX_CTRL2_FORMAT_MASK);
7651+ reg |= ctx->format_id << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT;
7652+
7653+ if (ctx->dpcm_decompress) {
7654+ if (ctx->dpcm_predictor)
7655+ reg |= ISPCSI2_CTX_CTRL2_DPCM_PRED;
7656+ else
7657+ reg &= ~ISPCSI2_CTX_CTRL2_DPCM_PRED;
7658+ }
7659+
7660+ if (is_usr_def_mapping(ctx->format_id)) {
7661+ reg &= ~ISPCSI2_CTX_CTRL2_USER_DEF_MAP_MASK;
7662+ reg |= 2 << ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT;
7663+ }
7664+
7665+ isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL2(ctx->ctxnum));
7666+
7667+ /* Set up CSI2_CTx_CTRL3 */
7668+ reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL3(ctx->ctxnum));
7669+ reg &= ~(ISPCSI2_CTX_CTRL3_ALPHA_MASK);
7670+ reg |= (ctx->alpha << ISPCSI2_CTX_CTRL3_ALPHA_SHIFT);
7671+
7672+ isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL3(ctx->ctxnum));
7673+
7674+ /* Set up CSI2_CTx_DAT_OFST */
7675+ reg = isp_reg_readl(isp, csi2->regs1,
7676+ ISPCSI2_CTX_DAT_OFST(ctx->ctxnum));
7677+ reg &= ~ISPCSI2_CTX_DAT_OFST_OFST_MASK;
7678+ reg |= ctx->data_offset << ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
7679+ isp_reg_writel(isp, reg, csi2->regs1,
7680+ ISPCSI2_CTX_DAT_OFST(ctx->ctxnum));
7681+
7682+ isp_reg_writel(isp, ctx->ping_addr,
7683+ csi2->regs1, ISPCSI2_CTX_DAT_PING_ADDR(ctx->ctxnum));
7684+
7685+ isp_reg_writel(isp, ctx->pong_addr,
7686+ csi2->regs1, ISPCSI2_CTX_DAT_PONG_ADDR(ctx->ctxnum));
7687+}
7688+
7689+/*
7690+ * csi2_timing_config - CSI2 timing configuration.
7691+ * @timing: csi2_timing_cfg structure
7692+ */
7693+static void csi2_timing_config(struct isp_device *isp,
7694+ struct isp_csi2_device *csi2,
7695+ struct isp_csi2_timing_cfg *timing)
7696+{
7697+ u32 reg;
7698+
7699+ reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_TIMING);
7700+
7701+ if (timing->force_rx_mode)
7702+ reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO(timing->ionum);
7703+ else
7704+ reg &= ~ISPCSI2_TIMING_FORCE_RX_MODE_IO(timing->ionum);
7705+
7706+ if (timing->stop_state_16x)
7707+ reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO(timing->ionum);
7708+ else
7709+ reg &= ~ISPCSI2_TIMING_STOP_STATE_X16_IO(timing->ionum);
7710+
7711+ if (timing->stop_state_4x)
7712+ reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO(timing->ionum);
7713+ else
7714+ reg &= ~ISPCSI2_TIMING_STOP_STATE_X4_IO(timing->ionum);
7715+
7716+ reg &= ~ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(timing->ionum);
7717+ reg |= timing->stop_state_counter <<
7718+ ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(timing->ionum);
7719+
7720+ isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_TIMING);
7721+}
7722+
7723+/*
7724+ * csi2_irq_ctx_set - Enables CSI2 Context IRQs.
7725+ * @enable: Enable/disable CSI2 Context interrupts
7726+ */
7727+static void csi2_irq_ctx_set(struct isp_device *isp,
7728+ struct isp_csi2_device *csi2, int enable)
7729+{
7730+ u32 reg = ISPCSI2_CTX_IRQSTATUS_FE_IRQ;
7731+ int i;
7732+
7733+ if (csi2->use_fs_irq)
7734+ reg |= ISPCSI2_CTX_IRQSTATUS_FS_IRQ;
7735+
7736+ for (i = 0; i < 8; i++) {
7737+ isp_reg_writel(isp, reg, csi2->regs1,
7738+ ISPCSI2_CTX_IRQSTATUS(i));
7739+ if (enable)
7740+ isp_reg_set(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
7741+ reg);
7742+ else
7743+ isp_reg_clr(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
7744+ reg);
7745+ }
7746+}
7747+
7748+/*
7749+ * csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
7750+ * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
7751+ */
7752+static void csi2_irq_complexio1_set(struct isp_device *isp,
7753+ struct isp_csi2_device *csi2, int enable)
7754+{
7755+ u32 reg;
7756+ reg = ISPCSI2_PHY_IRQENABLE_STATEALLULPMEXIT |
7757+ ISPCSI2_PHY_IRQENABLE_STATEALLULPMENTER |
7758+ ISPCSI2_PHY_IRQENABLE_STATEULPM5 |
7759+ ISPCSI2_PHY_IRQENABLE_ERRCONTROL5 |
7760+ ISPCSI2_PHY_IRQENABLE_ERRESC5 |
7761+ ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS5 |
7762+ ISPCSI2_PHY_IRQENABLE_ERRSOTHS5 |
7763+ ISPCSI2_PHY_IRQENABLE_STATEULPM4 |
7764+ ISPCSI2_PHY_IRQENABLE_ERRCONTROL4 |
7765+ ISPCSI2_PHY_IRQENABLE_ERRESC4 |
7766+ ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS4 |
7767+ ISPCSI2_PHY_IRQENABLE_ERRSOTHS4 |
7768+ ISPCSI2_PHY_IRQENABLE_STATEULPM3 |
7769+ ISPCSI2_PHY_IRQENABLE_ERRCONTROL3 |
7770+ ISPCSI2_PHY_IRQENABLE_ERRESC3 |
7771+ ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS3 |
7772+ ISPCSI2_PHY_IRQENABLE_ERRSOTHS3 |
7773+ ISPCSI2_PHY_IRQENABLE_STATEULPM2 |
7774+ ISPCSI2_PHY_IRQENABLE_ERRCONTROL2 |
7775+ ISPCSI2_PHY_IRQENABLE_ERRESC2 |
7776+ ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS2 |
7777+ ISPCSI2_PHY_IRQENABLE_ERRSOTHS2 |
7778+ ISPCSI2_PHY_IRQENABLE_STATEULPM1 |
7779+ ISPCSI2_PHY_IRQENABLE_ERRCONTROL1 |
7780+ ISPCSI2_PHY_IRQENABLE_ERRESC1 |
7781+ ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS1 |
7782+ ISPCSI2_PHY_IRQENABLE_ERRSOTHS1;
7783+ isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
7784+ if (enable)
7785+ reg |= isp_reg_readl(isp, csi2->regs1, ISPCSI2_PHY_IRQENABLE);
7786+ else
7787+ reg = 0;
7788+ isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_PHY_IRQENABLE);
7789+}
7790+
7791+/*
7792+ * csi2_irq_status_set - Enables CSI2 Status IRQs.
7793+ * @enable: Enable/disable CSI2 Status interrupts
7794+ */
7795+static void csi2_irq_status_set(struct isp_device *isp,
7796+ struct isp_csi2_device *csi2, int enable)
7797+{
7798+ u32 reg;
7799+ reg = ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
7800+ ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
7801+ ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ |
7802+ ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
7803+ ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
7804+ ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ |
7805+ ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ |
7806+ ISPCSI2_IRQSTATUS_CONTEXT(0);
7807+ isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_IRQSTATUS);
7808+ if (enable)
7809+ reg |= isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQENABLE);
7810+ else
7811+ reg = 0;
7812+
7813+ isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_IRQENABLE);
7814+}
7815+
7816+/*
7817+ * omap3isp_csi2_reset - Resets the CSI2 module.
7818+ *
7819+ * Must be called with the phy lock held.
7820+ *
7821+ * Returns 0 if successful, or -EBUSY if power command didn't respond.
7822+ */
7823+int omap3isp_csi2_reset(struct isp_csi2_device *csi2)
7824+{
7825+ struct isp_device *isp = csi2->isp;
7826+ u8 soft_reset_retries = 0;
7827+ u32 reg;
7828+ int i;
7829+
7830+ if (!csi2->available)
7831+ return -ENODEV;
7832+
7833+ if (csi2->phy->phy_in_use)
7834+ return -EBUSY;
7835+
7836+ isp_reg_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
7837+ ISPCSI2_SYSCONFIG_SOFT_RESET);
7838+
7839+ do {
7840+ reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_SYSSTATUS) &
7841+ ISPCSI2_SYSSTATUS_RESET_DONE;
7842+ if (reg == ISPCSI2_SYSSTATUS_RESET_DONE)
7843+ break;
7844+ soft_reset_retries++;
7845+ if (soft_reset_retries < 5)
7846+ udelay(100);
7847+ } while (soft_reset_retries < 5);
7848+
7849+ if (soft_reset_retries == 5) {
7850+ printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
7851+ return -EBUSY;
7852+ }
7853+
7854+ if (isp->revision == ISP_REVISION_15_0)
7855+ isp_reg_set(isp, csi2->regs1, ISPCSI2_PHY_CFG,
7856+ ISPCSI2_PHY_CFG_RESET_CTRL);
7857+
7858+ i = 100;
7859+ do {
7860+ reg = isp_reg_readl(isp, csi2->phy->phy_regs, ISPCSIPHY_REG1)
7861+ & ISPCSIPHY_REG1_RESET_DONE_CTRLCLK;
7862+ if (reg == ISPCSIPHY_REG1_RESET_DONE_CTRLCLK)
7863+ break;
7864+ udelay(100);
7865+ } while (--i > 0);
7866+
7867+ if (i == 0) {
7868+ printk(KERN_ERR
7869+ "CSI2: Reset for CSI2_96M_FCLK domain Failed!\n");
7870+ return -EBUSY;
7871+ }
7872+
7873+ if (isp->autoidle)
7874+ isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
7875+ ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
7876+ ISPCSI2_SYSCONFIG_AUTO_IDLE,
7877+ ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART |
7878+ ((isp->revision == ISP_REVISION_15_0) ?
7879+ ISPCSI2_SYSCONFIG_AUTO_IDLE : 0));
7880+ else
7881+ isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
7882+ ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
7883+ ISPCSI2_SYSCONFIG_AUTO_IDLE,
7884+ ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO);
7885+
7886+ return 0;
7887+}
7888+
7889+static int csi2_configure(struct isp_csi2_device *csi2)
7890+{
7891+ const struct isp_v4l2_subdevs_group *pdata;
7892+ struct isp_device *isp = csi2->isp;
7893+ struct isp_csi2_timing_cfg *timing = &csi2->timing[0];
7894+ struct v4l2_subdev *sensor;
7895+ struct media_pad *pad;
7896+
7897+ /*
7898+ * CSI2 fields that can be updated while the context has
7899+ * been enabled or the interface has been enabled are not
7900+ * updated dynamically currently. So we do not allow to
7901+ * reconfigure if either has been enabled
7902+ */
7903+ if (csi2->contexts[0].enabled || csi2->ctrl.if_enable)
7904+ return -EBUSY;
7905+
7906+ pad = media_entity_remote_source(&csi2->pads[CSI2_PAD_SINK]);
7907+ sensor = media_entity_to_v4l2_subdev(pad->entity);
7908+ pdata = sensor->host_priv;
7909+
7910+ csi2->frame_skip = 0;
7911+ v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);
7912+
7913+ csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div;
7914+ csi2->ctrl.frame_mode = ISP_CSI2_FRAME_IMMEDIATE;
7915+ csi2->ctrl.ecc_enable = pdata->bus.csi2.crc;
7916+
7917+ timing->ionum = 1;
7918+ timing->force_rx_mode = 1;
7919+ timing->stop_state_16x = 1;
7920+ timing->stop_state_4x = 1;
7921+ timing->stop_state_counter = 0x1FF;
7922+
7923+ /*
7924+ * The CSI2 receiver can't do any format conversion except DPCM
7925+ * decompression, so every set_format call configures both pads
7926+ * and enables DPCM decompression as a special case:
7927+ */
7928+ if (csi2->formats[CSI2_PAD_SINK].code !=
7929+ csi2->formats[CSI2_PAD_SOURCE].code)
7930+ csi2->dpcm_decompress = true;
7931+ else
7932+ csi2->dpcm_decompress = false;
7933+
7934+ csi2->contexts[0].format_id = csi2_ctx_map_format(csi2);
7935+
7936+ if (csi2->video_out.bpl_padding == 0)
7937+ csi2->contexts[0].data_offset = 0;
7938+ else
7939+ csi2->contexts[0].data_offset = csi2->video_out.bpl_value;
7940+
7941+ /*
7942+ * Enable end of frame and end of line signals generation for
7943+ * context 0. These signals are generated from CSI2 receiver to
7944+ * qualify the last pixel of a frame and the last pixel of a line.
7945+ * Without enabling the signals CSI2 receiver writes data to memory
7946+ * beyond buffer size and/or data line offset is not handled correctly.
7947+ */
7948+ csi2->contexts[0].eof_enabled = 1;
7949+ csi2->contexts[0].eol_enabled = 1;
7950+
7951+ csi2_irq_complexio1_set(isp, csi2, 1);
7952+ csi2_irq_ctx_set(isp, csi2, 1);
7953+ csi2_irq_status_set(isp, csi2, 1);
7954+
7955+ /* Set configuration (timings, format and links) */
7956+ csi2_timing_config(isp, csi2, timing);
7957+ csi2_recv_config(isp, csi2, &csi2->ctrl);
7958+ csi2_ctx_config(isp, csi2, &csi2->contexts[0]);
7959+
7960+ return 0;
7961+}
7962+
7963+/*
7964+ * csi2_print_status - Prints CSI2 debug information.
7965+ */
7966+#define CSI2_PRINT_REGISTER(isp, regs, name)\
7967+ dev_dbg(isp->dev, "###CSI2 " #name "=0x%08x\n", \
7968+ isp_reg_readl(isp, regs, ISPCSI2_##name))
7969+
7970+static void csi2_print_status(struct isp_csi2_device *csi2)
7971+{
7972+ struct isp_device *isp = csi2->isp;
7973+
7974+ if (!csi2->available)
7975+ return;
7976+
7977+ dev_dbg(isp->dev, "-------------CSI2 Register dump-------------\n");
7978+
7979+ CSI2_PRINT_REGISTER(isp, csi2->regs1, SYSCONFIG);
7980+ CSI2_PRINT_REGISTER(isp, csi2->regs1, SYSSTATUS);
7981+ CSI2_PRINT_REGISTER(isp, csi2->regs1, IRQENABLE);
7982+ CSI2_PRINT_REGISTER(isp, csi2->regs1, IRQSTATUS);
7983+ CSI2_PRINT_REGISTER(isp, csi2->regs1, CTRL);
7984+ CSI2_PRINT_REGISTER(isp, csi2->regs1, DBG_H);
7985+ CSI2_PRINT_REGISTER(isp, csi2->regs1, GNQ);
7986+ CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_CFG);
7987+ CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_IRQSTATUS);
7988+ CSI2_PRINT_REGISTER(isp, csi2->regs1, SHORT_PACKET);
7989+ CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_IRQENABLE);
7990+ CSI2_PRINT_REGISTER(isp, csi2->regs1, DBG_P);
7991+ CSI2_PRINT_REGISTER(isp, csi2->regs1, TIMING);
7992+ CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL1(0));
7993+ CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL2(0));
7994+ CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_OFST(0));
7995+ CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_PING_ADDR(0));
7996+ CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_PONG_ADDR(0));
7997+ CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_IRQENABLE(0));
7998+ CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_IRQSTATUS(0));
7999+ CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL3(0));
8000+
8001+ dev_dbg(isp->dev, "--------------------------------------------\n");
8002+}
8003+
8004+/* -----------------------------------------------------------------------------
8005+ * Interrupt handling
8006+ */
8007+
8008+/*
8009+ * csi2_isr_buffer - Does buffer handling at end-of-frame
8010+ * when writing to memory.
8011+ */
8012+static void csi2_isr_buffer(struct isp_csi2_device *csi2)
8013+{
8014+ struct isp_device *isp = csi2->isp;
8015+ struct isp_buffer *buffer;
8016+
8017+ csi2_ctx_enable(isp, csi2, 0, 0);
8018+
8019+ buffer = omap3isp_video_buffer_next(&csi2->video_out, 0);
8020+
8021+ /*
8022+ * Let video queue operation restart engine if there is an underrun
8023+ * condition.
8024+ */
8025+ if (buffer == NULL)
8026+ return;
8027+
8028+ csi2_set_outaddr(csi2, buffer->isp_addr);
8029+ csi2_ctx_enable(isp, csi2, 0, 1);
8030+}
8031+
8032+static void csi2_isr_ctx(struct isp_csi2_device *csi2,
8033+ struct isp_csi2_ctx_cfg *ctx)
8034+{
8035+ struct isp_device *isp = csi2->isp;
8036+ unsigned int n = ctx->ctxnum;
8037+ u32 status;
8038+
8039+ status = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));
8040+ isp_reg_writel(isp, status, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));
8041+
8042+ /* Propagate frame number */
8043+ if (status & ISPCSI2_CTX_IRQSTATUS_FS_IRQ) {
8044+ struct isp_pipeline *pipe =
8045+ to_isp_pipeline(&csi2->subdev.entity);
8046+ if (pipe->do_propagation)
8047+ atomic_inc(&pipe->frame_number);
8048+ }
8049+
8050+ if (!(status & ISPCSI2_CTX_IRQSTATUS_FE_IRQ))
8051+ return;
8052+
8053+ /* Skip interrupts until we reach the frame skip count. The CSI2 will be
8054+ * automatically disabled, as the frame skip count has been programmed
8055+ * in the CSI2_CTx_CTRL1::COUNT field, so reenable it.
8056+ *
8057+ * It would have been nice to rely on the FRAME_NUMBER interrupt instead
8058+ * but it turned out that the interrupt is only generated when the CSI2
8059+ * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased
8060+ * correctly and reaches 0 when data is forwarded to the video port only
8061+ * but no interrupt arrives). Maybe a CSI2 hardware bug.
8062+ */
8063+ if (csi2->frame_skip) {
8064+ csi2->frame_skip--;
8065+ if (csi2->frame_skip == 0) {
8066+ ctx->format_id = csi2_ctx_map_format(csi2);
8067+ csi2_ctx_config(isp, csi2, ctx);
8068+ csi2_ctx_enable(isp, csi2, n, 1);
8069+ }
8070+ return;
8071+ }
8072+
8073+ if (csi2->output & CSI2_OUTPUT_MEMORY)
8074+ csi2_isr_buffer(csi2);
8075+}
8076+
8077+/*
8078+ * omap3isp_csi2_isr - CSI2 interrupt handling.
8079+ *
8080+ * Return -EIO on Transmission error
8081+ */
8082+int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
8083+{
8084+ u32 csi2_irqstatus, cpxio1_irqstatus;
8085+ struct isp_device *isp = csi2->isp;
8086+ int retval = 0;
8087+
8088+ if (!csi2->available)
8089+ return -ENODEV;
8090+
8091+ csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS);
8092+ isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS);
8093+
8094+ /* Failure Cases */
8095+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ) {
8096+ cpxio1_irqstatus = isp_reg_readl(isp, csi2->regs1,
8097+ ISPCSI2_PHY_IRQSTATUS);
8098+ isp_reg_writel(isp, cpxio1_irqstatus,
8099+ csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
8100+ dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ "
8101+ "%x\n", cpxio1_irqstatus);
8102+ retval = -EIO;
8103+ }
8104+
8105+ if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
8106+ ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
8107+ ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
8108+ ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
8109+ ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)) {
8110+ dev_dbg(isp->dev, "CSI2 Err:"
8111+ " OCP:%d,"
8112+ " Short_pack:%d,"
8113+ " ECC:%d,"
8114+ " CPXIO2:%d,"
8115+ " FIFO_OVF:%d,"
8116+ "\n",
8117+ (csi2_irqstatus &
8118+ ISPCSI2_IRQSTATUS_OCP_ERR_IRQ) ? 1 : 0,
8119+ (csi2_irqstatus &
8120+ ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ) ? 1 : 0,
8121+ (csi2_irqstatus &
8122+ ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ) ? 1 : 0,
8123+ (csi2_irqstatus &
8124+ ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0,
8125+ (csi2_irqstatus &
8126+ ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0);
8127+ retval = -EIO;
8128+ }
8129+
8130+ if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
8131+ return 0;
8132+
8133+ /* Successful cases */
8134+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0))
8135+ csi2_isr_ctx(csi2, &csi2->contexts[0]);
8136+
8137+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
8138+ dev_dbg(isp->dev, "CSI2: ECC correction done\n");
8139+
8140+ return retval;
8141+}
8142+
8143+/* -----------------------------------------------------------------------------
8144+ * ISP video operations
8145+ */
8146+
8147+/*
8148+ * csi2_queue - Queues the first buffer when using memory output
8149+ * @video: The video node
8150+ * @buffer: buffer to queue
8151+ */
8152+static int csi2_queue(struct isp_video *video, struct isp_buffer *buffer)
8153+{
8154+ struct isp_device *isp = video->isp;
8155+ struct isp_csi2_device *csi2 = &isp->isp_csi2a;
8156+
8157+ csi2_set_outaddr(csi2, buffer->isp_addr);
8158+
8159+ /*
8160+ * If streaming was enabled before there was a buffer queued
8161+ * or underrun happened in the ISR, the hardware was not enabled
8162+ * and DMA queue flag ISP_VIDEO_DMAQUEUE_UNDERRUN is still set.
8163+ * Enable it now.
8164+ */
8165+ if (csi2->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
8166+ /* Enable / disable context 0 and IRQs */
8167+ csi2_if_enable(isp, csi2, 1);
8168+ csi2_ctx_enable(isp, csi2, 0, 1);
8169+ isp_video_dmaqueue_flags_clr(&csi2->video_out);
8170+ }
8171+
8172+ return 0;
8173+}
8174+
8175+static const struct isp_video_operations csi2_ispvideo_ops = {
8176+ .queue = csi2_queue,
8177+};
8178+
8179+/* -----------------------------------------------------------------------------
8180+ * V4L2 subdev operations
8181+ */
8182+
8183+static struct v4l2_mbus_framefmt *
8184+__csi2_get_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
8185+ unsigned int pad, enum v4l2_subdev_format_whence which)
8186+{
8187+ if (which == V4L2_SUBDEV_FORMAT_TRY)
8188+ return v4l2_subdev_get_try_format(fh, pad);
8189+ else
8190+ return &csi2->formats[pad];
8191+}
8192+
8193+static void
8194+csi2_try_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
8195+ unsigned int pad, struct v4l2_mbus_framefmt *fmt,
8196+ enum v4l2_subdev_format_whence which)
8197+{
8198+ enum v4l2_mbus_pixelcode pixelcode;
8199+ struct v4l2_mbus_framefmt *format;
8200+ const struct isp_format_info *info;
8201+ unsigned int i;
8202+
8203+ switch (pad) {
8204+ case CSI2_PAD_SINK:
8205+ /* Clamp the width and height to valid range (1-8191). */
8206+ for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) {
8207+ if (fmt->code == csi2_input_fmts[i])
8208+ break;
8209+ }
8210+
8211+ /* If not found, use SGRBG10 as default */
8212+ if (i >= ARRAY_SIZE(csi2_input_fmts))
8213+ fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
8214+
8215+ fmt->width = clamp_t(u32, fmt->width, 1, 8191);
8216+ fmt->height = clamp_t(u32, fmt->height, 1, 8191);
8217+ break;
8218+
8219+ case CSI2_PAD_SOURCE:
8220+ /* Source format same as sink format, except for DPCM
8221+ * compression.
8222+ */
8223+ pixelcode = fmt->code;
8224+ format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which);
8225+ memcpy(fmt, format, sizeof(*fmt));
8226+
8227+ /*
8228+ * Only Allow DPCM decompression, and check that the
8229+ * pattern is preserved
8230+ */
8231+ info = omap3isp_video_format_info(fmt->code);
8232+ if (info->uncompressed == pixelcode)
8233+ fmt->code = pixelcode;
8234+ break;
8235+ }
8236+
8237+ /* RGB, non-interlaced */
8238+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
8239+ fmt->field = V4L2_FIELD_NONE;
8240+}
8241+
8242+/*
8243+ * csi2_enum_mbus_code - Handle pixel format enumeration
8244+ * @sd : pointer to v4l2 subdev structure
8245+ * @fh : V4L2 subdev file handle
8246+ * @code : pointer to v4l2_subdev_mbus_code_enum structure
8247+ * return -EINVAL or zero on success
8248+ */
8249+static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
8250+ struct v4l2_subdev_fh *fh,
8251+ struct v4l2_subdev_mbus_code_enum *code)
8252+{
8253+ struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
8254+ struct v4l2_mbus_framefmt *format;
8255+ const struct isp_format_info *info;
8256+
8257+ if (code->pad == CSI2_PAD_SINK) {
8258+ if (code->index >= ARRAY_SIZE(csi2_input_fmts))
8259+ return -EINVAL;
8260+
8261+ code->code = csi2_input_fmts[code->index];
8262+ } else {
8263+ format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK,
8264+ V4L2_SUBDEV_FORMAT_TRY);
8265+ switch (code->index) {
8266+ case 0:
8267+ /* Passthrough sink pad code */
8268+ code->code = format->code;
8269+ break;
8270+ case 1:
8271+ /* Uncompressed code */
8272+ info = omap3isp_video_format_info(format->code);
8273+ if (info->uncompressed == format->code)
8274+ return -EINVAL;
8275+
8276+ code->code = info->uncompressed;
8277+ break;
8278+ default:
8279+ return -EINVAL;
8280+ }
8281+ }
8282+
8283+ return 0;
8284+}
8285+
8286+static int csi2_enum_frame_size(struct v4l2_subdev *sd,
8287+ struct v4l2_subdev_fh *fh,
8288+ struct v4l2_subdev_frame_size_enum *fse)
8289+{
8290+ struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
8291+ struct v4l2_mbus_framefmt format;
8292+
8293+ if (fse->index != 0)
8294+ return -EINVAL;
8295+
8296+ format.code = fse->code;
8297+ format.width = 1;
8298+ format.height = 1;
8299+ csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
8300+ fse->min_width = format.width;
8301+ fse->min_height = format.height;
8302+
8303+ if (format.code != fse->code)
8304+ return -EINVAL;
8305+
8306+ format.code = fse->code;
8307+ format.width = -1;
8308+ format.height = -1;
8309+ csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
8310+ fse->max_width = format.width;
8311+ fse->max_height = format.height;
8312+
8313+ return 0;
8314+}
8315+
8316+/*
8317+ * csi2_get_format - Handle get format by pads subdev method
8318+ * @sd : pointer to v4l2 subdev structure
8319+ * @fh : V4L2 subdev file handle
8320+ * @fmt: pointer to v4l2 subdev format structure
8321+ * return -EINVAL or zero on sucess
8322+ */
8323+static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
8324+ struct v4l2_subdev_format *fmt)
8325+{
8326+ struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
8327+ struct v4l2_mbus_framefmt *format;
8328+
8329+ format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
8330+ if (format == NULL)
8331+ return -EINVAL;
8332+
8333+ fmt->format = *format;
8334+ return 0;
8335+}
8336+
8337+/*
8338+ * csi2_set_format - Handle set format by pads subdev method
8339+ * @sd : pointer to v4l2 subdev structure
8340+ * @fh : V4L2 subdev file handle
8341+ * @fmt: pointer to v4l2 subdev format structure
8342+ * return -EINVAL or zero on success
8343+ */
8344+static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
8345+ struct v4l2_subdev_format *fmt)
8346+{
8347+ struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
8348+ struct v4l2_mbus_framefmt *format;
8349+
8350+ format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
8351+ if (format == NULL)
8352+ return -EINVAL;
8353+
8354+ csi2_try_format(csi2, fh, fmt->pad, &fmt->format, fmt->which);
8355+ *format = fmt->format;
8356+
8357+ /* Propagate the format from sink to source */
8358+ if (fmt->pad == CSI2_PAD_SINK) {
8359+ format = __csi2_get_format(csi2, fh, CSI2_PAD_SOURCE,
8360+ fmt->which);
8361+ *format = fmt->format;
8362+ csi2_try_format(csi2, fh, CSI2_PAD_SOURCE, format, fmt->which);
8363+ }
8364+
8365+ return 0;
8366+}
8367+
8368+/*
8369+ * csi2_init_formats - Initialize formats on all pads
8370+ * @sd: ISP CSI2 V4L2 subdevice
8371+ * @fh: V4L2 subdev file handle
8372+ *
8373+ * Initialize all pad formats with default values. If fh is not NULL, try
8374+ * formats are initialized on the file handle. Otherwise active formats are
8375+ * initialized on the device.
8376+ */
8377+static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
8378+{
8379+ struct v4l2_subdev_format format;
8380+
8381+ memset(&format, 0, sizeof(format));
8382+ format.pad = CSI2_PAD_SINK;
8383+ format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
8384+ format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
8385+ format.format.width = 4096;
8386+ format.format.height = 4096;
8387+ csi2_set_format(sd, fh, &format);
8388+
8389+ return 0;
8390+}
8391+
8392+/*
8393+ * csi2_set_stream - Enable/Disable streaming on the CSI2 module
8394+ * @sd: ISP CSI2 V4L2 subdevice
8395+ * @enable: ISP pipeline stream state
8396+ *
8397+ * Return 0 on success or a negative error code otherwise.
8398+ */
8399+static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
8400+{
8401+ struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
8402+ struct isp_device *isp = csi2->isp;
8403+ struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
8404+ struct isp_video *video_out = &csi2->video_out;
8405+
8406+ switch (enable) {
8407+ case ISP_PIPELINE_STREAM_CONTINUOUS:
8408+ if (omap3isp_csiphy_acquire(csi2->phy) < 0)
8409+ return -ENODEV;
8410+ csi2->use_fs_irq = pipe->do_propagation;
8411+ if (csi2->output & CSI2_OUTPUT_MEMORY)
8412+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI2A_WRITE);
8413+ csi2_configure(csi2);
8414+ csi2_print_status(csi2);
8415+
8416+ /*
8417+ * When outputting to memory with no buffer available, let the
8418+ * buffer queue handler start the hardware. A DMA queue flag
8419+ * ISP_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
8420+ * a buffer available.
8421+ */
8422+ if (csi2->output & CSI2_OUTPUT_MEMORY &&
8423+ !(video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED))
8424+ break;
8425+ /* Enable context 0 and IRQs */
8426+ atomic_set(&csi2->stopping, 0);
8427+ csi2_ctx_enable(isp, csi2, 0, 1);
8428+ csi2_if_enable(isp, csi2, 1);
8429+ isp_video_dmaqueue_flags_clr(video_out);
8430+ break;
8431+
8432+ case ISP_PIPELINE_STREAM_STOPPED:
8433+ if (csi2->state == ISP_PIPELINE_STREAM_STOPPED)
8434+ return 0;
8435+ if (omap3isp_module_sync_idle(&sd->entity, &csi2->wait,
8436+ &csi2->stopping))
8437+ dev_dbg(isp->dev, "%s: module stop timeout.\n",
8438+ sd->name);
8439+ csi2_ctx_enable(isp, csi2, 0, 0);
8440+ csi2_if_enable(isp, csi2, 0);
8441+ csi2_irq_ctx_set(isp, csi2, 0);
8442+ omap3isp_csiphy_release(csi2->phy);
8443+ isp_video_dmaqueue_flags_clr(video_out);
8444+ omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI2A_WRITE);
8445+ break;
8446+ }
8447+
8448+ csi2->state = enable;
8449+ return 0;
8450+}
8451+
8452+/* subdev core operations */
8453+static const struct v4l2_subdev_core_ops csi2_core_ops = {
8454+ .queryctrl = v4l2_subdev_queryctrl,
8455+ .querymenu = v4l2_subdev_querymenu,
8456+ .g_ctrl = v4l2_subdev_g_ctrl,
8457+ .s_ctrl = v4l2_subdev_s_ctrl,
8458+ .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
8459+ .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
8460+ .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
8461+};
8462+
8463+/* subdev file operations */
8464+static const struct v4l2_subdev_file_ops csi2_file_ops = {
8465+ .open = csi2_init_formats,
8466+};
8467+
8468+/* subdev video operations */
8469+static const struct v4l2_subdev_video_ops csi2_video_ops = {
8470+ .s_stream = csi2_set_stream,
8471+};
8472+
8473+/* subdev pad operations */
8474+static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
8475+ .enum_mbus_code = csi2_enum_mbus_code,
8476+ .enum_frame_size = csi2_enum_frame_size,
8477+ .get_fmt = csi2_get_format,
8478+ .set_fmt = csi2_set_format,
8479+};
8480+
8481+/* subdev operations */
8482+static const struct v4l2_subdev_ops csi2_ops = {
8483+ .core = &csi2_core_ops,
8484+ .file = &csi2_file_ops,
8485+ .video = &csi2_video_ops,
8486+ .pad = &csi2_pad_ops,
8487+};
8488+
8489+/* -----------------------------------------------------------------------------
8490+ * Media entity operations
8491+ */
8492+
8493+/*
8494+ * csi2_link_setup - Setup CSI2 connections.
8495+ * @entity : Pointer to media entity structure
8496+ * @local : Pointer to local pad array
8497+ * @remote : Pointer to remote pad array
8498+ * @flags : Link flags
8499+ * return -EINVAL or zero on success
8500+ */
8501+static int csi2_link_setup(struct media_entity *entity,
8502+ const struct media_pad *local,
8503+ const struct media_pad *remote, u32 flags)
8504+{
8505+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
8506+ struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
8507+ struct isp_csi2_ctrl_cfg *ctrl = &csi2->ctrl;
8508+
8509+ /*
8510+ * The ISP core doesn't support pipelines with multiple video outputs.
8511+ * Revisit this when it will be implemented, and return -EBUSY for now.
8512+ */
8513+
8514+ switch (local->index | media_entity_type(remote->entity)) {
8515+ case CSI2_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
8516+ if (flags & MEDIA_LNK_FL_ENABLED) {
8517+ if (csi2->output & ~CSI2_OUTPUT_MEMORY)
8518+ return -EBUSY;
8519+ csi2->output |= CSI2_OUTPUT_MEMORY;
8520+ } else {
8521+ csi2->output &= ~CSI2_OUTPUT_MEMORY;
8522+ }
8523+ break;
8524+
8525+ case CSI2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
8526+ if (flags & MEDIA_LNK_FL_ENABLED) {
8527+ if (csi2->output & ~CSI2_OUTPUT_CCDC)
8528+ return -EBUSY;
8529+ csi2->output |= CSI2_OUTPUT_CCDC;
8530+ } else {
8531+ csi2->output &= ~CSI2_OUTPUT_CCDC;
8532+ }
8533+ break;
8534+
8535+ default:
8536+ /* Link from camera to CSI2 is fixed... */
8537+ return -EINVAL;
8538+ }
8539+
8540+ ctrl->vp_only_enable =
8541+ (csi2->output & CSI2_OUTPUT_MEMORY) ? false : true;
8542+ ctrl->vp_clk_enable = !!(csi2->output & CSI2_OUTPUT_CCDC);
8543+
8544+ return 0;
8545+}
8546+
8547+/* media operations */
8548+static const struct media_entity_operations csi2_media_ops = {
8549+ .link_setup = csi2_link_setup,
8550+};
8551+
8552+/*
8553+ * csi2_init_entities - Initialize subdev and media entity.
8554+ * @csi2: Pointer to csi2 structure.
8555+ * return -ENOMEM or zero on success
8556+ */
8557+static int csi2_init_entities(struct isp_csi2_device *csi2)
8558+{
8559+ struct v4l2_subdev *sd = &csi2->subdev;
8560+ struct media_pad *pads = csi2->pads;
8561+ struct media_entity *me = &sd->entity;
8562+ int ret;
8563+
8564+ v4l2_subdev_init(sd, &csi2_ops);
8565+ strlcpy(sd->name, "OMAP3 ISP CSI2a", sizeof(sd->name));
8566+
8567+ sd->grp_id = 1 << 16; /* group ID for isp subdevs */
8568+ v4l2_set_subdevdata(sd, csi2);
8569+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
8570+
8571+ v4l2_ctrl_handler_init(&csi2->ctrls, 1);
8572+ sd->ctrl_handler = &csi2->ctrls;
8573+
8574+ pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_OUTPUT;
8575+ pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_INPUT;
8576+
8577+ me->ops = &csi2_media_ops;
8578+ ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0);
8579+ if (ret < 0)
8580+ return ret;
8581+
8582+ csi2_init_formats(sd, NULL);
8583+
8584+ /* Video device node */
8585+ csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
8586+ csi2->video_out.ops = &csi2_ispvideo_ops;
8587+ csi2->video_out.bpl_alignment = 32;
8588+ csi2->video_out.bpl_zero_padding = 1;
8589+ csi2->video_out.bpl_max = 0x1ffe0;
8590+ csi2->video_out.isp = csi2->isp;
8591+ csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
8592+
8593+ ret = omap3isp_video_init(&csi2->video_out, "CSI2a");
8594+ if (ret < 0)
8595+ return ret;
8596+
8597+ /* Connect the CSI2 subdev to the video node. */
8598+ ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
8599+ &csi2->video_out.video.entity, 0, 0);
8600+ if (ret < 0)
8601+ return ret;
8602+
8603+ return 0;
8604+}
8605+
8606+void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2)
8607+{
8608+ media_entity_cleanup(&csi2->subdev.entity);
8609+
8610+ v4l2_device_unregister_subdev(&csi2->subdev);
8611+ v4l2_ctrl_handler_free(&csi2->ctrls);
8612+ omap3isp_video_unregister(&csi2->video_out);
8613+}
8614+
8615+int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
8616+ struct v4l2_device *vdev)
8617+{
8618+ int ret;
8619+
8620+ /* Register the subdev and video nodes. */
8621+ ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
8622+ if (ret < 0)
8623+ goto error;
8624+
8625+ ret = omap3isp_video_register(&csi2->video_out, vdev);
8626+ if (ret < 0)
8627+ goto error;
8628+
8629+ return 0;
8630+
8631+error:
8632+ omap3isp_csi2_unregister_entities(csi2);
8633+ return ret;
8634+}
8635+
8636+/* -----------------------------------------------------------------------------
8637+ * ISP CSI2 initialisation and cleanup
8638+ */
8639+
8640+/*
8641+ * omap3isp_csi2_cleanup - Routine for module driver cleanup
8642+ */
8643+void omap3isp_csi2_cleanup(struct isp_device *isp)
8644+{
8645+}
8646+
8647+/*
8648+ * omap3isp_csi2_init - Routine for module driver init
8649+ */
8650+int omap3isp_csi2_init(struct isp_device *isp)
8651+{
8652+ struct isp_csi2_device *csi2a = &isp->isp_csi2a;
8653+ struct isp_csi2_device *csi2c = &isp->isp_csi2c;
8654+ int ret;
8655+
8656+ csi2a->isp = isp;
8657+ csi2a->available = 1;
8658+ csi2a->regs1 = OMAP3_ISP_IOMEM_CSI2A_REGS1;
8659+ csi2a->regs2 = OMAP3_ISP_IOMEM_CSI2A_REGS2;
8660+ csi2a->phy = &isp->isp_csiphy2;
8661+ csi2a->state = ISP_PIPELINE_STREAM_STOPPED;
8662+ init_waitqueue_head(&csi2a->wait);
8663+
8664+ ret = csi2_init_entities(csi2a);
8665+ if (ret < 0)
8666+ goto fail;
8667+
8668+ if (isp->revision == ISP_REVISION_15_0) {
8669+ csi2c->isp = isp;
8670+ csi2c->available = 1;
8671+ csi2c->regs1 = OMAP3_ISP_IOMEM_CSI2C_REGS1;
8672+ csi2c->regs2 = OMAP3_ISP_IOMEM_CSI2C_REGS2;
8673+ csi2c->phy = &isp->isp_csiphy1;
8674+ csi2c->state = ISP_PIPELINE_STREAM_STOPPED;
8675+ init_waitqueue_head(&csi2c->wait);
8676+ }
8677+
8678+ return 0;
8679+fail:
8680+ omap3isp_csi2_cleanup(isp);
8681+ return ret;
8682+}
8683diff --git a/drivers/media/video/isp/ispcsi2.h b/drivers/media/video/isp/ispcsi2.h
8684new file mode 100644
8685index 0000000..b367326
8686--- /dev/null
8687+++ b/drivers/media/video/isp/ispcsi2.h
8688@@ -0,0 +1,169 @@
8689+/*
8690+ * ispcsi2.h
8691+ *
8692+ * TI OMAP3 ISP - CSI2 module
8693+ *
8694+ * Copyright (C) 2010 Nokia Corporation
8695+ * Copyright (C) 2009 Texas Instruments, Inc.
8696+ *
8697+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
8698+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8699+ *
8700+ * This program is free software; you can redistribute it and/or modify
8701+ * it under the terms of the GNU General Public License version 2 as
8702+ * published by the Free Software Foundation.
8703+ *
8704+ * This program is distributed in the hope that it will be useful, but
8705+ * WITHOUT ANY WARRANTY; without even the implied warranty of
8706+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8707+ * General Public License for more details.
8708+ *
8709+ * You should have received a copy of the GNU General Public License
8710+ * along with this program; if not, write to the Free Software
8711+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
8712+ * 02110-1301 USA
8713+ */
8714+
8715+#ifndef OMAP3_ISP_CSI2_H
8716+#define OMAP3_ISP_CSI2_H
8717+
8718+#include <linux/types.h>
8719+#include <linux/videodev2.h>
8720+#include <media/v4l2-ctrls.h>
8721+
8722+struct isp_csiphy;
8723+
8724+/* This is not an exhaustive list */
8725+enum isp_csi2_pix_formats {
8726+ CSI2_PIX_FMT_OTHERS = 0,
8727+ CSI2_PIX_FMT_YUV422_8BIT = 0x1e,
8728+ CSI2_PIX_FMT_YUV422_8BIT_VP = 0x9e,
8729+ CSI2_PIX_FMT_RAW10_EXP16 = 0xab,
8730+ CSI2_PIX_FMT_RAW10_EXP16_VP = 0x12f,
8731+ CSI2_PIX_FMT_RAW8 = 0x2a,
8732+ CSI2_PIX_FMT_RAW8_DPCM10_EXP16 = 0x2aa,
8733+ CSI2_PIX_FMT_RAW8_DPCM10_VP = 0x32a,
8734+ CSI2_PIX_FMT_RAW8_VP = 0x12a,
8735+ CSI2_USERDEF_8BIT_DATA1_DPCM10_VP = 0x340,
8736+ CSI2_USERDEF_8BIT_DATA1_DPCM10 = 0x2c0,
8737+ CSI2_USERDEF_8BIT_DATA1 = 0x40,
8738+};
8739+
8740+enum isp_csi2_irqevents {
8741+ OCP_ERR_IRQ = 0x4000,
8742+ SHORT_PACKET_IRQ = 0x2000,
8743+ ECC_CORRECTION_IRQ = 0x1000,
8744+ ECC_NO_CORRECTION_IRQ = 0x800,
8745+ COMPLEXIO2_ERR_IRQ = 0x400,
8746+ COMPLEXIO1_ERR_IRQ = 0x200,
8747+ FIFO_OVF_IRQ = 0x100,
8748+ CONTEXT7 = 0x80,
8749+ CONTEXT6 = 0x40,
8750+ CONTEXT5 = 0x20,
8751+ CONTEXT4 = 0x10,
8752+ CONTEXT3 = 0x8,
8753+ CONTEXT2 = 0x4,
8754+ CONTEXT1 = 0x2,
8755+ CONTEXT0 = 0x1,
8756+};
8757+
8758+enum isp_csi2_ctx_irqevents {
8759+ CTX_ECC_CORRECTION = 0x100,
8760+ CTX_LINE_NUMBER = 0x80,
8761+ CTX_FRAME_NUMBER = 0x40,
8762+ CTX_CS = 0x20,
8763+ CTX_LE = 0x8,
8764+ CTX_LS = 0x4,
8765+ CTX_FE = 0x2,
8766+ CTX_FS = 0x1,
8767+};
8768+
8769+enum isp_csi2_frame_mode {
8770+ ISP_CSI2_FRAME_IMMEDIATE,
8771+ ISP_CSI2_FRAME_AFTERFEC,
8772+};
8773+
8774+#define ISP_CSI2_MAX_CTX_NUM 7
8775+
8776+struct isp_csi2_ctx_cfg {
8777+ u8 ctxnum; /* context number 0 - 7 */
8778+ u8 dpcm_decompress;
8779+
8780+ /* Fields in CSI2_CTx_CTRL2 - locked by CSI2_CTx_CTRL1.CTX_EN */
8781+ u8 virtual_id;
8782+ u16 format_id; /* as in CSI2_CTx_CTRL2[9:0] */
8783+ u8 dpcm_predictor; /* 1: simple, 0: advanced */
8784+
8785+ /* Fields in CSI2_CTx_CTRL1/3 - Shadowed */
8786+ u16 alpha;
8787+ u16 data_offset;
8788+ u32 ping_addr;
8789+ u32 pong_addr;
8790+ u8 eof_enabled;
8791+ u8 eol_enabled;
8792+ u8 checksum_enabled;
8793+ u8 enabled;
8794+};
8795+
8796+struct isp_csi2_timing_cfg {
8797+ u8 ionum; /* IO1 or IO2 as in CSI2_TIMING */
8798+ unsigned force_rx_mode:1;
8799+ unsigned stop_state_16x:1;
8800+ unsigned stop_state_4x:1;
8801+ u16 stop_state_counter;
8802+};
8803+
8804+struct isp_csi2_ctrl_cfg {
8805+ bool vp_clk_enable;
8806+ bool vp_only_enable;
8807+ u8 vp_out_ctrl;
8808+ enum isp_csi2_frame_mode frame_mode;
8809+ bool ecc_enable;
8810+ bool if_enable;
8811+};
8812+
8813+#define CSI2_PAD_SINK 0
8814+#define CSI2_PAD_SOURCE 1
8815+#define CSI2_PADS_NUM 2
8816+
8817+#define CSI2_OUTPUT_CCDC (1 << 0)
8818+#define CSI2_OUTPUT_MEMORY (1 << 1)
8819+
8820+struct isp_csi2_device {
8821+ struct v4l2_subdev subdev;
8822+ struct media_pad pads[CSI2_PADS_NUM];
8823+ struct v4l2_mbus_framefmt formats[CSI2_PADS_NUM];
8824+
8825+ struct v4l2_ctrl_handler ctrls;
8826+
8827+ struct isp_video video_out;
8828+ struct isp_device *isp;
8829+
8830+ u8 available; /* Is the IP present on the silicon? */
8831+
8832+ /* mem resources - enums as defined in enum isp_mem_resources */
8833+ u8 regs1;
8834+ u8 regs2;
8835+
8836+ u32 output; /* output to CCDC, memory or both? */
8837+ bool dpcm_decompress;
8838+ unsigned int frame_skip;
8839+ bool use_fs_irq;
8840+
8841+ struct isp_csiphy *phy;
8842+ struct isp_csi2_ctx_cfg contexts[ISP_CSI2_MAX_CTX_NUM + 1];
8843+ struct isp_csi2_timing_cfg timing[2];
8844+ struct isp_csi2_ctrl_cfg ctrl;
8845+ enum isp_pipeline_stream_state state;
8846+ wait_queue_head_t wait;
8847+ atomic_t stopping;
8848+};
8849+
8850+int omap3isp_csi2_isr(struct isp_csi2_device *csi2);
8851+int omap3isp_csi2_reset(struct isp_csi2_device *csi2);
8852+int omap3isp_csi2_init(struct isp_device *isp);
8853+void omap3isp_csi2_cleanup(struct isp_device *isp);
8854+void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2);
8855+int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
8856+ struct v4l2_device *vdev);
8857+#endif /* OMAP3_ISP_CSI2_H */
8858diff --git a/drivers/media/video/isp/ispcsiphy.c b/drivers/media/video/isp/ispcsiphy.c
8859new file mode 100644
8860index 0000000..59cd477
8861--- /dev/null
8862+++ b/drivers/media/video/isp/ispcsiphy.c
8863@@ -0,0 +1,247 @@
8864+/*
8865+ * ispcsiphy.c
8866+ *
8867+ * TI OMAP3 ISP - CSI PHY module
8868+ *
8869+ * Copyright (C) 2010 Nokia Corporation
8870+ * Copyright (C) 2009 Texas Instruments, Inc.
8871+ *
8872+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
8873+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8874+ *
8875+ * This program is free software; you can redistribute it and/or modify
8876+ * it under the terms of the GNU General Public License version 2 as
8877+ * published by the Free Software Foundation.
8878+ *
8879+ * This program is distributed in the hope that it will be useful, but
8880+ * WITHOUT ANY WARRANTY; without even the implied warranty of
8881+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8882+ * General Public License for more details.
8883+ *
8884+ * You should have received a copy of the GNU General Public License
8885+ * along with this program; if not, write to the Free Software
8886+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
8887+ * 02110-1301 USA
8888+ */
8889+
8890+#include <linux/delay.h>
8891+#include <linux/device.h>
8892+#include <linux/regulator/consumer.h>
8893+
8894+#include "isp.h"
8895+#include "ispreg.h"
8896+#include "ispcsiphy.h"
8897+
8898+/*
8899+ * csiphy_lanes_config - Configuration of CSIPHY lanes.
8900+ *
8901+ * Updates HW configuration.
8902+ * Called with phy->mutex taken.
8903+ */
8904+static void csiphy_lanes_config(struct isp_csiphy *phy)
8905+{
8906+ unsigned int i;
8907+ u32 reg;
8908+
8909+ reg = isp_reg_readl(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG);
8910+
8911+ for (i = 0; i < phy->num_data_lanes; i++) {
8912+ reg &= ~(ISPCSI2_PHY_CFG_DATA_POL_MASK(i + 1) |
8913+ ISPCSI2_PHY_CFG_DATA_POSITION_MASK(i + 1));
8914+ reg |= (phy->lanes.data[i].pol <<
8915+ ISPCSI2_PHY_CFG_DATA_POL_SHIFT(i + 1));
8916+ reg |= (phy->lanes.data[i].pos <<
8917+ ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(i + 1));
8918+ }
8919+
8920+ reg &= ~(ISPCSI2_PHY_CFG_CLOCK_POL_MASK |
8921+ ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK);
8922+ reg |= phy->lanes.clk.pol << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT;
8923+ reg |= phy->lanes.clk.pos << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT;
8924+
8925+ isp_reg_writel(phy->isp, reg, phy->cfg_regs, ISPCSI2_PHY_CFG);
8926+}
8927+
8928+/*
8929+ * csiphy_power_autoswitch_enable
8930+ * @enable: Sets or clears the autoswitch function enable flag.
8931+ */
8932+static void csiphy_power_autoswitch_enable(struct isp_csiphy *phy, bool enable)
8933+{
8934+ isp_reg_clr_set(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG,
8935+ ISPCSI2_PHY_CFG_PWR_AUTO,
8936+ enable ? ISPCSI2_PHY_CFG_PWR_AUTO : 0);
8937+}
8938+
8939+/*
8940+ * csiphy_set_power
8941+ * @power: Power state to be set.
8942+ *
8943+ * Returns 0 if successful, or -EBUSY if the retry count is exceeded.
8944+ */
8945+static int csiphy_set_power(struct isp_csiphy *phy, u32 power)
8946+{
8947+ u32 reg;
8948+ u8 retry_count;
8949+
8950+ isp_reg_clr_set(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG,
8951+ ISPCSI2_PHY_CFG_PWR_CMD_MASK, power);
8952+
8953+ retry_count = 0;
8954+ do {
8955+ udelay(50);
8956+ reg = isp_reg_readl(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG) &
8957+ ISPCSI2_PHY_CFG_PWR_STATUS_MASK;
8958+
8959+ if (reg != power >> 2)
8960+ retry_count++;
8961+
8962+ } while ((reg != power >> 2) && (retry_count < 100));
8963+
8964+ if (retry_count == 100) {
8965+ printk(KERN_ERR "CSI2 CIO set power failed!\n");
8966+ return -EBUSY;
8967+ }
8968+
8969+ return 0;
8970+}
8971+
8972+/*
8973+ * csiphy_dphy_config - Configure CSI2 D-PHY parameters.
8974+ *
8975+ * Called with phy->mutex taken.
8976+ */
8977+static void csiphy_dphy_config(struct isp_csiphy *phy)
8978+{
8979+ u32 reg;
8980+
8981+ /* Set up ISPCSIPHY_REG0 */
8982+ reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG0);
8983+
8984+ reg &= ~(ISPCSIPHY_REG0_THS_TERM_MASK |
8985+ ISPCSIPHY_REG0_THS_SETTLE_MASK);
8986+ reg |= phy->dphy.ths_term << ISPCSIPHY_REG0_THS_TERM_SHIFT;
8987+ reg |= phy->dphy.ths_settle << ISPCSIPHY_REG0_THS_SETTLE_SHIFT;
8988+
8989+ isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG0);
8990+
8991+ /* Set up ISPCSIPHY_REG1 */
8992+ reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG1);
8993+
8994+ reg &= ~(ISPCSIPHY_REG1_TCLK_TERM_MASK |
8995+ ISPCSIPHY_REG1_TCLK_MISS_MASK |
8996+ ISPCSIPHY_REG1_TCLK_SETTLE_MASK);
8997+ reg |= phy->dphy.tclk_term << ISPCSIPHY_REG1_TCLK_TERM_SHIFT;
8998+ reg |= phy->dphy.tclk_miss << ISPCSIPHY_REG1_TCLK_MISS_SHIFT;
8999+ reg |= phy->dphy.tclk_settle << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT;
9000+
9001+ isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG1);
9002+}
9003+
9004+static int csiphy_config(struct isp_csiphy *phy,
9005+ struct isp_csiphy_dphy_cfg *dphy,
9006+ struct isp_csiphy_lanes_cfg *lanes)
9007+{
9008+ unsigned int used_lanes = 0;
9009+ unsigned int i;
9010+
9011+ /* Clock and data lanes verification */
9012+ for (i = 0; i < phy->num_data_lanes; i++) {
9013+ if (lanes->data[i].pol > 1 || lanes->data[i].pos > 3)
9014+ return -EINVAL;
9015+
9016+ if (used_lanes & (1 << lanes->data[i].pos))
9017+ return -EINVAL;
9018+
9019+ used_lanes |= 1 << lanes->data[i].pos;
9020+ }
9021+
9022+ if (lanes->clk.pol > 1 || lanes->clk.pos > 3)
9023+ return -EINVAL;
9024+
9025+ if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos))
9026+ return -EINVAL;
9027+
9028+ mutex_lock(&phy->mutex);
9029+ phy->dphy = *dphy;
9030+ phy->lanes = *lanes;
9031+ mutex_unlock(&phy->mutex);
9032+
9033+ return 0;
9034+}
9035+
9036+int omap3isp_csiphy_acquire(struct isp_csiphy *phy)
9037+{
9038+ int rval;
9039+
9040+ if (phy->vdd == NULL) {
9041+ dev_err(phy->isp->dev, "Power regulator for CSI PHY not "
9042+ "available\n");
9043+ return -ENODEV;
9044+ }
9045+
9046+ mutex_lock(&phy->mutex);
9047+
9048+ rval = regulator_enable(phy->vdd);
9049+ if (rval < 0)
9050+ goto done;
9051+
9052+ omap3isp_csi2_reset(phy->csi2);
9053+
9054+ csiphy_dphy_config(phy);
9055+ csiphy_lanes_config(phy);
9056+
9057+ rval = csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_ON);
9058+ if (rval) {
9059+ regulator_disable(phy->vdd);
9060+ goto done;
9061+ }
9062+
9063+ csiphy_power_autoswitch_enable(phy, true);
9064+ phy->phy_in_use = 1;
9065+
9066+done:
9067+ mutex_unlock(&phy->mutex);
9068+ return rval;
9069+}
9070+
9071+void omap3isp_csiphy_release(struct isp_csiphy *phy)
9072+{
9073+ mutex_lock(&phy->mutex);
9074+ if (phy->phy_in_use) {
9075+ csiphy_power_autoswitch_enable(phy, false);
9076+ csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_OFF);
9077+ regulator_disable(phy->vdd);
9078+ phy->phy_in_use = 0;
9079+ }
9080+ mutex_unlock(&phy->mutex);
9081+}
9082+
9083+/*
9084+ * omap3isp_csiphy_init - Initialize the CSI PHY frontends
9085+ */
9086+int omap3isp_csiphy_init(struct isp_device *isp)
9087+{
9088+ struct isp_csiphy *phy1 = &isp->isp_csiphy1;
9089+ struct isp_csiphy *phy2 = &isp->isp_csiphy2;
9090+
9091+ isp->platform_cb.csiphy_config = csiphy_config;
9092+
9093+ phy2->isp = isp;
9094+ phy2->csi2 = &isp->isp_csi2a;
9095+ phy2->num_data_lanes = ISP_CSIPHY2_NUM_DATA_LANES;
9096+ phy2->cfg_regs = OMAP3_ISP_IOMEM_CSI2A_REGS1;
9097+ phy2->phy_regs = OMAP3_ISP_IOMEM_CSIPHY2;
9098+ mutex_init(&phy2->mutex);
9099+
9100+ if (isp->revision == ISP_REVISION_15_0) {
9101+ phy1->isp = isp;
9102+ phy1->csi2 = &isp->isp_csi2c;
9103+ phy1->num_data_lanes = ISP_CSIPHY1_NUM_DATA_LANES;
9104+ phy1->cfg_regs = OMAP3_ISP_IOMEM_CSI2C_REGS1;
9105+ phy1->phy_regs = OMAP3_ISP_IOMEM_CSIPHY1;
9106+ mutex_init(&phy1->mutex);
9107+ }
9108+
9109+ return 0;
9110+}
9111diff --git a/drivers/media/video/isp/ispcsiphy.h b/drivers/media/video/isp/ispcsiphy.h
9112new file mode 100644
9113index 0000000..39a7e6b
9114--- /dev/null
9115+++ b/drivers/media/video/isp/ispcsiphy.h
9116@@ -0,0 +1,74 @@
9117+/*
9118+ * ispcsiphy.h
9119+ *
9120+ * TI OMAP3 ISP - CSI PHY module
9121+ *
9122+ * Copyright (C) 2010 Nokia Corporation
9123+ * Copyright (C) 2009 Texas Instruments, Inc.
9124+ *
9125+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9126+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
9127+ *
9128+ * This program is free software; you can redistribute it and/or modify
9129+ * it under the terms of the GNU General Public License version 2 as
9130+ * published by the Free Software Foundation.
9131+ *
9132+ * This program is distributed in the hope that it will be useful, but
9133+ * WITHOUT ANY WARRANTY; without even the implied warranty of
9134+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9135+ * General Public License for more details.
9136+ *
9137+ * You should have received a copy of the GNU General Public License
9138+ * along with this program; if not, write to the Free Software
9139+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
9140+ * 02110-1301 USA
9141+ */
9142+
9143+#ifndef OMAP3_ISP_CSI_PHY_H
9144+#define OMAP3_ISP_CSI_PHY_H
9145+
9146+struct isp_csi2_device;
9147+struct regulator;
9148+
9149+struct csiphy_lane {
9150+ u8 pos;
9151+ u8 pol;
9152+};
9153+
9154+#define ISP_CSIPHY2_NUM_DATA_LANES 2
9155+#define ISP_CSIPHY1_NUM_DATA_LANES 1
9156+
9157+struct isp_csiphy_lanes_cfg {
9158+ struct csiphy_lane data[ISP_CSIPHY2_NUM_DATA_LANES];
9159+ struct csiphy_lane clk;
9160+};
9161+
9162+struct isp_csiphy_dphy_cfg {
9163+ u8 ths_term;
9164+ u8 ths_settle;
9165+ u8 tclk_term;
9166+ unsigned tclk_miss:1;
9167+ u8 tclk_settle;
9168+};
9169+
9170+struct isp_csiphy {
9171+ struct isp_device *isp;
9172+ struct mutex mutex; /* serialize csiphy configuration */
9173+ u8 phy_in_use;
9174+ struct isp_csi2_device *csi2;
9175+ struct regulator *vdd;
9176+
9177+ /* mem resources - enums as defined in enum isp_mem_resources */
9178+ unsigned int cfg_regs;
9179+ unsigned int phy_regs;
9180+
9181+ u8 num_data_lanes; /* number of CSI2 Data Lanes supported */
9182+ struct isp_csiphy_lanes_cfg lanes;
9183+ struct isp_csiphy_dphy_cfg dphy;
9184+};
9185+
9186+int omap3isp_csiphy_acquire(struct isp_csiphy *phy);
9187+void omap3isp_csiphy_release(struct isp_csiphy *phy);
9188+int omap3isp_csiphy_init(struct isp_device *isp);
9189+
9190+#endif /* OMAP3_ISP_CSI_PHY_H */
9191diff --git a/drivers/media/video/isp/isph3a.h b/drivers/media/video/isp/isph3a.h
9192new file mode 100644
9193index 0000000..6d43529
9194--- /dev/null
9195+++ b/drivers/media/video/isp/isph3a.h
9196@@ -0,0 +1,117 @@
9197+/*
9198+ * isph3a.h
9199+ *
9200+ * TI OMAP3 ISP - H3A AF module
9201+ *
9202+ * Copyright (C) 2010 Nokia Corporation
9203+ * Copyright (C) 2009 Texas Instruments, Inc.
9204+ *
9205+ * Contacts: David Cohen <david.cohen@nokia.com>
9206+ * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9207+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
9208+ *
9209+ * This program is free software; you can redistribute it and/or modify
9210+ * it under the terms of the GNU General Public License version 2 as
9211+ * published by the Free Software Foundation.
9212+ *
9213+ * This program is distributed in the hope that it will be useful, but
9214+ * WITHOUT ANY WARRANTY; without even the implied warranty of
9215+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9216+ * General Public License for more details.
9217+ *
9218+ * You should have received a copy of the GNU General Public License
9219+ * along with this program; if not, write to the Free Software
9220+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
9221+ * 02110-1301 USA
9222+ */
9223+
9224+#ifndef OMAP3_ISP_H3A_H
9225+#define OMAP3_ISP_H3A_H
9226+
9227+#include <linux/omap3isp.h>
9228+
9229+/*
9230+ * ----------
9231+ * -H3A AEWB-
9232+ * ----------
9233+ */
9234+
9235+#define AEWB_PACKET_SIZE 16
9236+#define AEWB_SATURATION_LIMIT 0x3ff
9237+
9238+/* Flags for changed registers */
9239+#define PCR_CHNG (1 << 0)
9240+#define AEWWIN1_CHNG (1 << 1)
9241+#define AEWINSTART_CHNG (1 << 2)
9242+#define AEWINBLK_CHNG (1 << 3)
9243+#define AEWSUBWIN_CHNG (1 << 4)
9244+#define PRV_WBDGAIN_CHNG (1 << 5)
9245+#define PRV_WBGAIN_CHNG (1 << 6)
9246+
9247+/* ISPH3A REGISTERS bits */
9248+#define ISPH3A_PCR_AF_EN (1 << 0)
9249+#define ISPH3A_PCR_AF_ALAW_EN (1 << 1)
9250+#define ISPH3A_PCR_AF_MED_EN (1 << 2)
9251+#define ISPH3A_PCR_AF_BUSY (1 << 15)
9252+#define ISPH3A_PCR_AEW_EN (1 << 16)
9253+#define ISPH3A_PCR_AEW_ALAW_EN (1 << 17)
9254+#define ISPH3A_PCR_AEW_BUSY (1 << 18)
9255+#define ISPH3A_PCR_AEW_MASK (ISPH3A_PCR_AEW_ALAW_EN | \
9256+ ISPH3A_PCR_AEW_AVE2LMT_MASK)
9257+
9258+/*
9259+ * --------
9260+ * -H3A AF-
9261+ * --------
9262+ */
9263+
9264+/* Peripheral Revision */
9265+#define AFPID 0x0
9266+
9267+#define AFCOEF_OFFSET 0x00000004 /* COEF base address */
9268+
9269+/* PCR fields */
9270+#define AF_BUSYAF (1 << 15)
9271+#define AF_FVMODE (1 << 14)
9272+#define AF_RGBPOS (0x7 << 11)
9273+#define AF_MED_TH (0xFF << 3)
9274+#define AF_MED_EN (1 << 2)
9275+#define AF_ALAW_EN (1 << 1)
9276+#define AF_EN (1 << 0)
9277+#define AF_PCR_MASK (AF_FVMODE | AF_RGBPOS | AF_MED_TH | \
9278+ AF_MED_EN | AF_ALAW_EN)
9279+
9280+/* AFPAX1 fields */
9281+#define AF_PAXW (0x7F << 16)
9282+#define AF_PAXH 0x7F
9283+
9284+/* AFPAX2 fields */
9285+#define AF_AFINCV (0xF << 13)
9286+#define AF_PAXVC (0x7F << 6)
9287+#define AF_PAXHC 0x3F
9288+
9289+/* AFPAXSTART fields */
9290+#define AF_PAXSH (0xFFF<<16)
9291+#define AF_PAXSV 0xFFF
9292+
9293+/* COEFFICIENT MASK */
9294+#define AF_COEF_MASK0 0xFFF
9295+#define AF_COEF_MASK1 (0xFFF<<16)
9296+
9297+/* BIT SHIFTS */
9298+#define AF_RGBPOS_SHIFT 11
9299+#define AF_MED_TH_SHIFT 3
9300+#define AF_PAXW_SHIFT 16
9301+#define AF_LINE_INCR_SHIFT 13
9302+#define AF_VT_COUNT_SHIFT 6
9303+#define AF_HZ_START_SHIFT 16
9304+#define AF_COEF_SHIFT 16
9305+
9306+/* Init and cleanup functions */
9307+int omap3isp_h3a_aewb_init(struct isp_device *isp);
9308+int omap3isp_h3a_af_init(struct isp_device *isp);
9309+
9310+void omap3isp_h3a_aewb_cleanup(struct isp_device *isp);
9311+void omap3isp_h3a_af_cleanup(struct isp_device *isp);
9312+
9313+#endif /* OMAP3_ISP_H3A_H */
9314diff --git a/drivers/media/video/isp/isph3a_aewb.c b/drivers/media/video/isp/isph3a_aewb.c
9315new file mode 100644
9316index 0000000..b4e97f2
9317--- /dev/null
9318+++ b/drivers/media/video/isp/isph3a_aewb.c
9319@@ -0,0 +1,374 @@
9320+/*
9321+ * isph3a.c
9322+ *
9323+ * TI OMAP3 ISP - H3A module
9324+ *
9325+ * Copyright (C) 2010 Nokia Corporation
9326+ * Copyright (C) 2009 Texas Instruments, Inc.
9327+ *
9328+ * Contacts: David Cohen <david.cohen@nokia.com>
9329+ * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9330+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
9331+ *
9332+ * This program is free software; you can redistribute it and/or modify
9333+ * it under the terms of the GNU General Public License version 2 as
9334+ * published by the Free Software Foundation.
9335+ *
9336+ * This program is distributed in the hope that it will be useful, but
9337+ * WITHOUT ANY WARRANTY; without even the implied warranty of
9338+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9339+ * General Public License for more details.
9340+ *
9341+ * You should have received a copy of the GNU General Public License
9342+ * along with this program; if not, write to the Free Software
9343+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
9344+ * 02110-1301 USA
9345+ */
9346+
9347+#include <linux/slab.h>
9348+#include <linux/uaccess.h>
9349+
9350+#include "isp.h"
9351+#include "isph3a.h"
9352+#include "ispstat.h"
9353+
9354+/*
9355+ * h3a_aewb_update_regs - Helper function to update h3a registers.
9356+ */
9357+static void h3a_aewb_setup_regs(struct ispstat *aewb, void *priv)
9358+{
9359+ struct omap3isp_h3a_aewb_config *conf = priv;
9360+ u32 pcr;
9361+ u32 win1;
9362+ u32 start;
9363+ u32 blk;
9364+ u32 subwin;
9365+
9366+ if (aewb->state == ISPSTAT_DISABLED)
9367+ return;
9368+
9369+ isp_reg_writel(aewb->isp, aewb->active_buf->iommu_addr,
9370+ OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST);
9371+
9372+ if (!aewb->update)
9373+ return;
9374+
9375+ /* Converting config metadata into reg values */
9376+ pcr = conf->saturation_limit << ISPH3A_PCR_AEW_AVE2LMT_SHIFT;
9377+ pcr |= !!conf->alaw_enable << ISPH3A_PCR_AEW_ALAW_EN_SHIFT;
9378+
9379+ win1 = ((conf->win_height >> 1) - 1) << ISPH3A_AEWWIN1_WINH_SHIFT;
9380+ win1 |= ((conf->win_width >> 1) - 1) << ISPH3A_AEWWIN1_WINW_SHIFT;
9381+ win1 |= (conf->ver_win_count - 1) << ISPH3A_AEWWIN1_WINVC_SHIFT;
9382+ win1 |= (conf->hor_win_count - 1) << ISPH3A_AEWWIN1_WINHC_SHIFT;
9383+
9384+ start = conf->hor_win_start << ISPH3A_AEWINSTART_WINSH_SHIFT;
9385+ start |= conf->ver_win_start << ISPH3A_AEWINSTART_WINSV_SHIFT;
9386+
9387+ blk = conf->blk_ver_win_start << ISPH3A_AEWINBLK_WINSV_SHIFT;
9388+ blk |= ((conf->blk_win_height >> 1) - 1) << ISPH3A_AEWINBLK_WINH_SHIFT;
9389+
9390+ subwin = ((conf->subsample_ver_inc >> 1) - 1) <<
9391+ ISPH3A_AEWSUBWIN_AEWINCV_SHIFT;
9392+ subwin |= ((conf->subsample_hor_inc >> 1) - 1) <<
9393+ ISPH3A_AEWSUBWIN_AEWINCH_SHIFT;
9394+
9395+ isp_reg_writel(aewb->isp, win1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1);
9396+ isp_reg_writel(aewb->isp, start, OMAP3_ISP_IOMEM_H3A,
9397+ ISPH3A_AEWINSTART);
9398+ isp_reg_writel(aewb->isp, blk, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK);
9399+ isp_reg_writel(aewb->isp, subwin, OMAP3_ISP_IOMEM_H3A,
9400+ ISPH3A_AEWSUBWIN);
9401+ isp_reg_clr_set(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
9402+ ISPH3A_PCR_AEW_MASK, pcr);
9403+
9404+ aewb->update = 0;
9405+ aewb->config_counter += aewb->inc_config;
9406+ aewb->inc_config = 0;
9407+ aewb->buf_size = conf->buf_size;
9408+}
9409+
9410+static void h3a_aewb_enable(struct ispstat *aewb, int enable)
9411+{
9412+ if (enable) {
9413+ isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
9414+ ISPH3A_PCR_AEW_EN);
9415+ /* This bit is already set if AF is enabled */
9416+ if (aewb->isp->isp_af.state != ISPSTAT_ENABLED)
9417+ isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
9418+ ISPCTRL_H3A_CLK_EN);
9419+ } else {
9420+ isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
9421+ ISPH3A_PCR_AEW_EN);
9422+ /* This bit can't be cleared if AF is enabled */
9423+ if (aewb->isp->isp_af.state != ISPSTAT_ENABLED)
9424+ isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
9425+ ISPCTRL_H3A_CLK_EN);
9426+ }
9427+}
9428+
9429+static int h3a_aewb_busy(struct ispstat *aewb)
9430+{
9431+ return isp_reg_readl(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
9432+ & ISPH3A_PCR_BUSYAEAWB;
9433+}
9434+
9435+static u32 h3a_aewb_get_buf_size(struct omap3isp_h3a_aewb_config *conf)
9436+{
9437+ /* Number of configured windows + extra row for black data */
9438+ u32 win_count = (conf->ver_win_count + 1) * conf->hor_win_count;
9439+
9440+ /*
9441+ * Unsaturated block counts for each 8 windows.
9442+ * 1 extra for the last (win_count % 8) windows if win_count is not
9443+ * divisible by 8.
9444+ */
9445+ win_count += (win_count + 7) / 8;
9446+
9447+ return win_count * AEWB_PACKET_SIZE;
9448+}
9449+
9450+static int h3a_aewb_validate_params(struct ispstat *aewb, void *new_conf)
9451+{
9452+ struct omap3isp_h3a_aewb_config *user_cfg = new_conf;
9453+ u32 buf_size;
9454+
9455+ if (unlikely(user_cfg->saturation_limit >
9456+ OMAP3ISP_AEWB_MAX_SATURATION_LIM))
9457+ return -EINVAL;
9458+
9459+ if (unlikely(user_cfg->win_height < OMAP3ISP_AEWB_MIN_WIN_H ||
9460+ user_cfg->win_height > OMAP3ISP_AEWB_MAX_WIN_H ||
9461+ user_cfg->win_height & 0x01))
9462+ return -EINVAL;
9463+
9464+ if (unlikely(user_cfg->win_width < OMAP3ISP_AEWB_MIN_WIN_W ||
9465+ user_cfg->win_width > OMAP3ISP_AEWB_MAX_WIN_W ||
9466+ user_cfg->win_width & 0x01))
9467+ return -EINVAL;
9468+
9469+ if (unlikely(user_cfg->ver_win_count < OMAP3ISP_AEWB_MIN_WINVC ||
9470+ user_cfg->ver_win_count > OMAP3ISP_AEWB_MAX_WINVC))
9471+ return -EINVAL;
9472+
9473+ if (unlikely(user_cfg->hor_win_count < OMAP3ISP_AEWB_MIN_WINHC ||
9474+ user_cfg->hor_win_count > OMAP3ISP_AEWB_MAX_WINHC))
9475+ return -EINVAL;
9476+
9477+ if (unlikely(user_cfg->ver_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
9478+ return -EINVAL;
9479+
9480+ if (unlikely(user_cfg->hor_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
9481+ return -EINVAL;
9482+
9483+ if (unlikely(user_cfg->blk_ver_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
9484+ return -EINVAL;
9485+
9486+ if (unlikely(user_cfg->blk_win_height < OMAP3ISP_AEWB_MIN_WIN_H ||
9487+ user_cfg->blk_win_height > OMAP3ISP_AEWB_MAX_WIN_H ||
9488+ user_cfg->blk_win_height & 0x01))
9489+ return -EINVAL;
9490+
9491+ if (unlikely(user_cfg->subsample_ver_inc < OMAP3ISP_AEWB_MIN_SUB_INC ||
9492+ user_cfg->subsample_ver_inc > OMAP3ISP_AEWB_MAX_SUB_INC ||
9493+ user_cfg->subsample_ver_inc & 0x01))
9494+ return -EINVAL;
9495+
9496+ if (unlikely(user_cfg->subsample_hor_inc < OMAP3ISP_AEWB_MIN_SUB_INC ||
9497+ user_cfg->subsample_hor_inc > OMAP3ISP_AEWB_MAX_SUB_INC ||
9498+ user_cfg->subsample_hor_inc & 0x01))
9499+ return -EINVAL;
9500+
9501+ buf_size = h3a_aewb_get_buf_size(user_cfg);
9502+ if (buf_size > user_cfg->buf_size)
9503+ user_cfg->buf_size = buf_size;
9504+ else if (user_cfg->buf_size > OMAP3ISP_AEWB_MAX_BUF_SIZE)
9505+ user_cfg->buf_size = OMAP3ISP_AEWB_MAX_BUF_SIZE;
9506+
9507+ return 0;
9508+}
9509+
9510+/*
9511+ * h3a_aewb_set_params - Helper function to check & store user given params.
9512+ * @new_conf: Pointer to AE and AWB parameters struct.
9513+ *
9514+ * As most of them are busy-lock registers, need to wait until AEW_BUSY = 0 to
9515+ * program them during ISR.
9516+ */
9517+static void h3a_aewb_set_params(struct ispstat *aewb, void *new_conf)
9518+{
9519+ struct omap3isp_h3a_aewb_config *user_cfg = new_conf;
9520+ struct omap3isp_h3a_aewb_config *cur_cfg = aewb->priv;
9521+ int update = 0;
9522+
9523+ if (cur_cfg->saturation_limit != user_cfg->saturation_limit) {
9524+ cur_cfg->saturation_limit = user_cfg->saturation_limit;
9525+ update = 1;
9526+ }
9527+ if (cur_cfg->alaw_enable != user_cfg->alaw_enable) {
9528+ cur_cfg->alaw_enable = user_cfg->alaw_enable;
9529+ update = 1;
9530+ }
9531+ if (cur_cfg->win_height != user_cfg->win_height) {
9532+ cur_cfg->win_height = user_cfg->win_height;
9533+ update = 1;
9534+ }
9535+ if (cur_cfg->win_width != user_cfg->win_width) {
9536+ cur_cfg->win_width = user_cfg->win_width;
9537+ update = 1;
9538+ }
9539+ if (cur_cfg->ver_win_count != user_cfg->ver_win_count) {
9540+ cur_cfg->ver_win_count = user_cfg->ver_win_count;
9541+ update = 1;
9542+ }
9543+ if (cur_cfg->hor_win_count != user_cfg->hor_win_count) {
9544+ cur_cfg->hor_win_count = user_cfg->hor_win_count;
9545+ update = 1;
9546+ }
9547+ if (cur_cfg->ver_win_start != user_cfg->ver_win_start) {
9548+ cur_cfg->ver_win_start = user_cfg->ver_win_start;
9549+ update = 1;
9550+ }
9551+ if (cur_cfg->hor_win_start != user_cfg->hor_win_start) {
9552+ cur_cfg->hor_win_start = user_cfg->hor_win_start;
9553+ update = 1;
9554+ }
9555+ if (cur_cfg->blk_ver_win_start != user_cfg->blk_ver_win_start) {
9556+ cur_cfg->blk_ver_win_start = user_cfg->blk_ver_win_start;
9557+ update = 1;
9558+ }
9559+ if (cur_cfg->blk_win_height != user_cfg->blk_win_height) {
9560+ cur_cfg->blk_win_height = user_cfg->blk_win_height;
9561+ update = 1;
9562+ }
9563+ if (cur_cfg->subsample_ver_inc != user_cfg->subsample_ver_inc) {
9564+ cur_cfg->subsample_ver_inc = user_cfg->subsample_ver_inc;
9565+ update = 1;
9566+ }
9567+ if (cur_cfg->subsample_hor_inc != user_cfg->subsample_hor_inc) {
9568+ cur_cfg->subsample_hor_inc = user_cfg->subsample_hor_inc;
9569+ update = 1;
9570+ }
9571+
9572+ if (update || !aewb->configured) {
9573+ aewb->inc_config++;
9574+ aewb->update = 1;
9575+ cur_cfg->buf_size = h3a_aewb_get_buf_size(cur_cfg);
9576+ }
9577+}
9578+
9579+static long h3a_aewb_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
9580+{
9581+ struct ispstat *stat = v4l2_get_subdevdata(sd);
9582+
9583+ switch (cmd) {
9584+ case VIDIOC_OMAP3ISP_AEWB_CFG:
9585+ return omap3isp_stat_config(stat, arg);
9586+ case VIDIOC_OMAP3ISP_STAT_REQ:
9587+ return omap3isp_stat_request_statistics(stat, arg);
9588+ case VIDIOC_OMAP3ISP_STAT_EN: {
9589+ unsigned long *en = arg;
9590+ return omap3isp_stat_enable(stat, !!*en);
9591+ }
9592+ }
9593+
9594+ return -ENOIOCTLCMD;
9595+}
9596+
9597+static const struct ispstat_ops h3a_aewb_ops = {
9598+ .validate_params = h3a_aewb_validate_params,
9599+ .set_params = h3a_aewb_set_params,
9600+ .setup_regs = h3a_aewb_setup_regs,
9601+ .enable = h3a_aewb_enable,
9602+ .busy = h3a_aewb_busy,
9603+};
9604+
9605+static const struct v4l2_subdev_core_ops h3a_aewb_subdev_core_ops = {
9606+ .ioctl = h3a_aewb_ioctl,
9607+ .subscribe_event = omap3isp_stat_subscribe_event,
9608+ .unsubscribe_event = omap3isp_stat_unsubscribe_event,
9609+};
9610+
9611+static const struct v4l2_subdev_video_ops h3a_aewb_subdev_video_ops = {
9612+ .s_stream = omap3isp_stat_s_stream,
9613+};
9614+
9615+static const struct v4l2_subdev_ops h3a_aewb_subdev_ops = {
9616+ .core = &h3a_aewb_subdev_core_ops,
9617+ .video = &h3a_aewb_subdev_video_ops,
9618+};
9619+
9620+/*
9621+ * omap3isp_h3a_aewb_init - Module Initialisation.
9622+ */
9623+int omap3isp_h3a_aewb_init(struct isp_device *isp)
9624+{
9625+ struct ispstat *aewb = &isp->isp_aewb;
9626+ struct omap3isp_h3a_aewb_config *aewb_cfg;
9627+ struct omap3isp_h3a_aewb_config *aewb_recover_cfg;
9628+ int ret;
9629+
9630+ aewb_cfg = kzalloc(sizeof(*aewb_cfg), GFP_KERNEL);
9631+ if (!aewb_cfg)
9632+ return -ENOMEM;
9633+
9634+ memset(aewb, 0, sizeof(*aewb));
9635+ aewb->ops = &h3a_aewb_ops;
9636+ aewb->priv = aewb_cfg;
9637+ aewb->dma_ch = -1;
9638+ aewb->event_type = V4L2_EVENT_OMAP3ISP_AEWB;
9639+ aewb->isp = isp;
9640+
9641+ /* Set recover state configuration */
9642+ aewb_recover_cfg = kzalloc(sizeof(*aewb_recover_cfg), GFP_KERNEL);
9643+ if (!aewb_recover_cfg) {
9644+ dev_err(aewb->isp->dev, "AEWB: cannot allocate memory for "
9645+ "recover configuration.\n");
9646+ ret = -ENOMEM;
9647+ goto err_recover_alloc;
9648+ }
9649+
9650+ aewb_recover_cfg->saturation_limit = OMAP3ISP_AEWB_MAX_SATURATION_LIM;
9651+ aewb_recover_cfg->win_height = OMAP3ISP_AEWB_MIN_WIN_H;
9652+ aewb_recover_cfg->win_width = OMAP3ISP_AEWB_MIN_WIN_W;
9653+ aewb_recover_cfg->ver_win_count = OMAP3ISP_AEWB_MIN_WINVC;
9654+ aewb_recover_cfg->hor_win_count = OMAP3ISP_AEWB_MIN_WINHC;
9655+ aewb_recover_cfg->blk_ver_win_start = aewb_recover_cfg->ver_win_start +
9656+ aewb_recover_cfg->win_height * aewb_recover_cfg->ver_win_count;
9657+ aewb_recover_cfg->blk_win_height = OMAP3ISP_AEWB_MIN_WIN_H;
9658+ aewb_recover_cfg->subsample_ver_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
9659+ aewb_recover_cfg->subsample_hor_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
9660+
9661+ if (h3a_aewb_validate_params(aewb, aewb_recover_cfg)) {
9662+ dev_err(aewb->isp->dev, "AEWB: recover configuration is "
9663+ "invalid.\n");
9664+ ret = -EINVAL;
9665+ goto err_conf;
9666+ }
9667+
9668+ aewb_recover_cfg->buf_size = h3a_aewb_get_buf_size(aewb_recover_cfg);
9669+ aewb->recover_priv = aewb_recover_cfg;
9670+
9671+ ret = omap3isp_stat_init(aewb, "AEWB", &h3a_aewb_subdev_ops);
9672+ if (ret)
9673+ goto err_conf;
9674+
9675+ return 0;
9676+
9677+err_conf:
9678+ kfree(aewb_recover_cfg);
9679+err_recover_alloc:
9680+ kfree(aewb_cfg);
9681+
9682+ return ret;
9683+}
9684+
9685+/*
9686+ * omap3isp_h3a_aewb_cleanup - Module exit.
9687+ */
9688+void omap3isp_h3a_aewb_cleanup(struct isp_device *isp)
9689+{
9690+ kfree(isp->isp_aewb.priv);
9691+ kfree(isp->isp_aewb.recover_priv);
9692+ omap3isp_stat_free(&isp->isp_aewb);
9693+}
9694diff --git a/drivers/media/video/isp/isph3a_af.c b/drivers/media/video/isp/isph3a_af.c
9695new file mode 100644
9696index 0000000..c32a18e
9697--- /dev/null
9698+++ b/drivers/media/video/isp/isph3a_af.c
9699@@ -0,0 +1,429 @@
9700+/*
9701+ * isph3a_af.c
9702+ *
9703+ * TI OMAP3 ISP - H3A AF module
9704+ *
9705+ * Copyright (C) 2010 Nokia Corporation
9706+ * Copyright (C) 2009 Texas Instruments, Inc.
9707+ *
9708+ * Contacts: David Cohen <david.cohen@nokia.com>
9709+ * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9710+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
9711+ *
9712+ * This program is free software; you can redistribute it and/or modify
9713+ * it under the terms of the GNU General Public License version 2 as
9714+ * published by the Free Software Foundation.
9715+ *
9716+ * This program is distributed in the hope that it will be useful, but
9717+ * WITHOUT ANY WARRANTY; without even the implied warranty of
9718+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9719+ * General Public License for more details.
9720+ *
9721+ * You should have received a copy of the GNU General Public License
9722+ * along with this program; if not, write to the Free Software
9723+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
9724+ * 02110-1301 USA
9725+ */
9726+
9727+/* Linux specific include files */
9728+#include <linux/device.h>
9729+#include <linux/slab.h>
9730+
9731+#include "isp.h"
9732+#include "isph3a.h"
9733+#include "ispstat.h"
9734+
9735+#define IS_OUT_OF_BOUNDS(value, min, max) \
9736+ (((value) < (min)) || ((value) > (max)))
9737+
9738+static void h3a_af_setup_regs(struct ispstat *af, void *priv)
9739+{
9740+ struct omap3isp_h3a_af_config *conf = priv;
9741+ u32 pcr;
9742+ u32 pax1;
9743+ u32 pax2;
9744+ u32 paxstart;
9745+ u32 coef;
9746+ u32 base_coef_set0;
9747+ u32 base_coef_set1;
9748+ int index;
9749+
9750+ if (af->state == ISPSTAT_DISABLED)
9751+ return;
9752+
9753+ isp_reg_writel(af->isp, af->active_buf->iommu_addr, OMAP3_ISP_IOMEM_H3A,
9754+ ISPH3A_AFBUFST);
9755+
9756+ if (!af->update)
9757+ return;
9758+
9759+ /* Configure Hardware Registers */
9760+ pax1 = ((conf->paxel.width >> 1) - 1) << AF_PAXW_SHIFT;
9761+ /* Set height in AFPAX1 */
9762+ pax1 |= (conf->paxel.height >> 1) - 1;
9763+ isp_reg_writel(af->isp, pax1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1);
9764+
9765+ /* Configure AFPAX2 Register */
9766+ /* Set Line Increment in AFPAX2 Register */
9767+ pax2 = ((conf->paxel.line_inc >> 1) - 1) << AF_LINE_INCR_SHIFT;
9768+ /* Set Vertical Count */
9769+ pax2 |= (conf->paxel.v_cnt - 1) << AF_VT_COUNT_SHIFT;
9770+ /* Set Horizontal Count */
9771+ pax2 |= (conf->paxel.h_cnt - 1);
9772+ isp_reg_writel(af->isp, pax2, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2);
9773+
9774+ /* Configure PAXSTART Register */
9775+ /*Configure Horizontal Start */
9776+ paxstart = conf->paxel.h_start << AF_HZ_START_SHIFT;
9777+ /* Configure Vertical Start */
9778+ paxstart |= conf->paxel.v_start;
9779+ isp_reg_writel(af->isp, paxstart, OMAP3_ISP_IOMEM_H3A,
9780+ ISPH3A_AFPAXSTART);
9781+
9782+ /*SetIIRSH Register */
9783+ isp_reg_writel(af->isp, conf->iir.h_start,
9784+ OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH);
9785+
9786+ base_coef_set0 = ISPH3A_AFCOEF010;
9787+ base_coef_set1 = ISPH3A_AFCOEF110;
9788+ for (index = 0; index <= 8; index += 2) {
9789+ /*Set IIR Filter0 Coefficients */
9790+ coef = 0;
9791+ coef |= conf->iir.coeff_set0[index];
9792+ coef |= conf->iir.coeff_set0[index + 1] <<
9793+ AF_COEF_SHIFT;
9794+ isp_reg_writel(af->isp, coef, OMAP3_ISP_IOMEM_H3A,
9795+ base_coef_set0);
9796+ base_coef_set0 += AFCOEF_OFFSET;
9797+
9798+ /*Set IIR Filter1 Coefficients */
9799+ coef = 0;
9800+ coef |= conf->iir.coeff_set1[index];
9801+ coef |= conf->iir.coeff_set1[index + 1] <<
9802+ AF_COEF_SHIFT;
9803+ isp_reg_writel(af->isp, coef, OMAP3_ISP_IOMEM_H3A,
9804+ base_coef_set1);
9805+ base_coef_set1 += AFCOEF_OFFSET;
9806+ }
9807+ /* set AFCOEF0010 Register */
9808+ isp_reg_writel(af->isp, conf->iir.coeff_set0[10],
9809+ OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF0010);
9810+ /* set AFCOEF1010 Register */
9811+ isp_reg_writel(af->isp, conf->iir.coeff_set1[10],
9812+ OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010);
9813+
9814+ /* PCR Register */
9815+ /* Set RGB Position */
9816+ pcr = conf->rgb_pos << AF_RGBPOS_SHIFT;
9817+ /* Set Accumulator Mode */
9818+ if (conf->fvmode == OMAP3ISP_AF_MODE_PEAK)
9819+ pcr |= AF_FVMODE;
9820+ /* Set A-law */
9821+ if (conf->alaw_enable)
9822+ pcr |= AF_ALAW_EN;
9823+ /* HMF Configurations */
9824+ if (conf->hmf.enable) {
9825+ /* Enable HMF */
9826+ pcr |= AF_MED_EN;
9827+ /* Set Median Threshold */
9828+ pcr |= conf->hmf.threshold << AF_MED_TH_SHIFT;
9829+ }
9830+ /* Set PCR Register */
9831+ isp_reg_clr_set(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
9832+ AF_PCR_MASK, pcr);
9833+
9834+ af->update = 0;
9835+ af->config_counter += af->inc_config;
9836+ af->inc_config = 0;
9837+ af->buf_size = conf->buf_size;
9838+}
9839+
9840+static void h3a_af_enable(struct ispstat *af, int enable)
9841+{
9842+ if (enable) {
9843+ isp_reg_set(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
9844+ ISPH3A_PCR_AF_EN);
9845+ /* This bit is already set if AEWB is enabled */
9846+ if (af->isp->isp_aewb.state != ISPSTAT_ENABLED)
9847+ isp_reg_set(af->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
9848+ ISPCTRL_H3A_CLK_EN);
9849+ } else {
9850+ isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
9851+ ISPH3A_PCR_AF_EN);
9852+ /* This bit can't be cleared if AEWB is enabled */
9853+ if (af->isp->isp_aewb.state != ISPSTAT_ENABLED)
9854+ isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
9855+ ISPCTRL_H3A_CLK_EN);
9856+ }
9857+}
9858+
9859+static int h3a_af_busy(struct ispstat *af)
9860+{
9861+ return isp_reg_readl(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
9862+ & ISPH3A_PCR_BUSYAF;
9863+}
9864+
9865+static u32 h3a_af_get_buf_size(struct omap3isp_h3a_af_config *conf)
9866+{
9867+ return conf->paxel.h_cnt * conf->paxel.v_cnt * OMAP3ISP_AF_PAXEL_SIZE;
9868+}
9869+
9870+/* Function to check paxel parameters */
9871+static int h3a_af_validate_params(struct ispstat *af, void *new_conf)
9872+{
9873+ struct omap3isp_h3a_af_config *user_cfg = new_conf;
9874+ struct omap3isp_h3a_af_paxel *paxel_cfg = &user_cfg->paxel;
9875+ struct omap3isp_h3a_af_iir *iir_cfg = &user_cfg->iir;
9876+ int index;
9877+ u32 buf_size;
9878+
9879+ /* Check horizontal Count */
9880+ if (IS_OUT_OF_BOUNDS(paxel_cfg->h_cnt,
9881+ OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN,
9882+ OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MAX))
9883+ return -EINVAL;
9884+
9885+ /* Check Vertical Count */
9886+ if (IS_OUT_OF_BOUNDS(paxel_cfg->v_cnt,
9887+ OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN,
9888+ OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MAX))
9889+ return -EINVAL;
9890+
9891+ if (IS_OUT_OF_BOUNDS(paxel_cfg->height, OMAP3ISP_AF_PAXEL_HEIGHT_MIN,
9892+ OMAP3ISP_AF_PAXEL_HEIGHT_MAX) ||
9893+ paxel_cfg->height % 2)
9894+ return -EINVAL;
9895+
9896+ /* Check width */
9897+ if (IS_OUT_OF_BOUNDS(paxel_cfg->width, OMAP3ISP_AF_PAXEL_WIDTH_MIN,
9898+ OMAP3ISP_AF_PAXEL_WIDTH_MAX) ||
9899+ paxel_cfg->width % 2)
9900+ return -EINVAL;
9901+
9902+ /* Check Line Increment */
9903+ if (IS_OUT_OF_BOUNDS(paxel_cfg->line_inc,
9904+ OMAP3ISP_AF_PAXEL_INCREMENT_MIN,
9905+ OMAP3ISP_AF_PAXEL_INCREMENT_MAX) ||
9906+ paxel_cfg->line_inc % 2)
9907+ return -EINVAL;
9908+
9909+ /* Check Horizontal Start */
9910+ if ((paxel_cfg->h_start < iir_cfg->h_start) ||
9911+ IS_OUT_OF_BOUNDS(paxel_cfg->h_start,
9912+ OMAP3ISP_AF_PAXEL_HZSTART_MIN,
9913+ OMAP3ISP_AF_PAXEL_HZSTART_MAX))
9914+ return -EINVAL;
9915+
9916+ /* Check IIR */
9917+ for (index = 0; index < OMAP3ISP_AF_NUM_COEF; index++) {
9918+ if ((iir_cfg->coeff_set0[index]) > OMAP3ISP_AF_COEF_MAX)
9919+ return -EINVAL;
9920+
9921+ if ((iir_cfg->coeff_set1[index]) > OMAP3ISP_AF_COEF_MAX)
9922+ return -EINVAL;
9923+ }
9924+
9925+ if (IS_OUT_OF_BOUNDS(iir_cfg->h_start, OMAP3ISP_AF_IIRSH_MIN,
9926+ OMAP3ISP_AF_IIRSH_MAX))
9927+ return -EINVAL;
9928+
9929+ /* Hack: If paxel size is 12, the 10th AF window may be corrupted */
9930+ if ((paxel_cfg->h_cnt * paxel_cfg->v_cnt > 9) &&
9931+ (paxel_cfg->width * paxel_cfg->height == 12))
9932+ return -EINVAL;
9933+
9934+ buf_size = h3a_af_get_buf_size(user_cfg);
9935+ if (buf_size > user_cfg->buf_size)
9936+ /* User buf_size request wasn't enough */
9937+ user_cfg->buf_size = buf_size;
9938+ else if (user_cfg->buf_size > OMAP3ISP_AF_MAX_BUF_SIZE)
9939+ user_cfg->buf_size = OMAP3ISP_AF_MAX_BUF_SIZE;
9940+
9941+ return 0;
9942+}
9943+
9944+/* Update local parameters */
9945+static void h3a_af_set_params(struct ispstat *af, void *new_conf)
9946+{
9947+ struct omap3isp_h3a_af_config *user_cfg = new_conf;
9948+ struct omap3isp_h3a_af_config *cur_cfg = af->priv;
9949+ int update = 0;
9950+ int index;
9951+
9952+ /* alaw */
9953+ if (cur_cfg->alaw_enable != user_cfg->alaw_enable) {
9954+ update = 1;
9955+ goto out;
9956+ }
9957+
9958+ /* hmf */
9959+ if (cur_cfg->hmf.enable != user_cfg->hmf.enable) {
9960+ update = 1;
9961+ goto out;
9962+ }
9963+ if (cur_cfg->hmf.threshold != user_cfg->hmf.threshold) {
9964+ update = 1;
9965+ goto out;
9966+ }
9967+
9968+ /* rgbpos */
9969+ if (cur_cfg->rgb_pos != user_cfg->rgb_pos) {
9970+ update = 1;
9971+ goto out;
9972+ }
9973+
9974+ /* iir */
9975+ if (cur_cfg->iir.h_start != user_cfg->iir.h_start) {
9976+ update = 1;
9977+ goto out;
9978+ }
9979+ for (index = 0; index < OMAP3ISP_AF_NUM_COEF; index++) {
9980+ if (cur_cfg->iir.coeff_set0[index] !=
9981+ user_cfg->iir.coeff_set0[index]) {
9982+ update = 1;
9983+ goto out;
9984+ }
9985+ if (cur_cfg->iir.coeff_set1[index] !=
9986+ user_cfg->iir.coeff_set1[index]) {
9987+ update = 1;
9988+ goto out;
9989+ }
9990+ }
9991+
9992+ /* paxel */
9993+ if ((cur_cfg->paxel.width != user_cfg->paxel.width) ||
9994+ (cur_cfg->paxel.height != user_cfg->paxel.height) ||
9995+ (cur_cfg->paxel.h_start != user_cfg->paxel.h_start) ||
9996+ (cur_cfg->paxel.v_start != user_cfg->paxel.v_start) ||
9997+ (cur_cfg->paxel.h_cnt != user_cfg->paxel.h_cnt) ||
9998+ (cur_cfg->paxel.v_cnt != user_cfg->paxel.v_cnt) ||
9999+ (cur_cfg->paxel.line_inc != user_cfg->paxel.line_inc)) {
10000+ update = 1;
10001+ goto out;
10002+ }
10003+
10004+ /* af_mode */
10005+ if (cur_cfg->fvmode != user_cfg->fvmode)
10006+ update = 1;
10007+
10008+out:
10009+ if (update || !af->configured) {
10010+ memcpy(cur_cfg, user_cfg, sizeof(*cur_cfg));
10011+ af->inc_config++;
10012+ af->update = 1;
10013+ /*
10014+ * User might be asked for a bigger buffer than necessary for
10015+ * this configuration. In order to return the right amount of
10016+ * data during buffer request, let's calculate the size here
10017+ * instead of stick with user_cfg->buf_size.
10018+ */
10019+ cur_cfg->buf_size = h3a_af_get_buf_size(cur_cfg);
10020+ }
10021+}
10022+
10023+static long h3a_af_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
10024+{
10025+ struct ispstat *stat = v4l2_get_subdevdata(sd);
10026+
10027+ switch (cmd) {
10028+ case VIDIOC_OMAP3ISP_AF_CFG:
10029+ return omap3isp_stat_config(stat, arg);
10030+ case VIDIOC_OMAP3ISP_STAT_REQ:
10031+ return omap3isp_stat_request_statistics(stat, arg);
10032+ case VIDIOC_OMAP3ISP_STAT_EN: {
10033+ int *en = arg;
10034+ return omap3isp_stat_enable(stat, !!*en);
10035+ }
10036+ }
10037+
10038+ return -ENOIOCTLCMD;
10039+
10040+}
10041+
10042+static const struct ispstat_ops h3a_af_ops = {
10043+ .validate_params = h3a_af_validate_params,
10044+ .set_params = h3a_af_set_params,
10045+ .setup_regs = h3a_af_setup_regs,
10046+ .enable = h3a_af_enable,
10047+ .busy = h3a_af_busy,
10048+};
10049+
10050+static const struct v4l2_subdev_core_ops h3a_af_subdev_core_ops = {
10051+ .ioctl = h3a_af_ioctl,
10052+ .subscribe_event = omap3isp_stat_subscribe_event,
10053+ .unsubscribe_event = omap3isp_stat_unsubscribe_event,
10054+};
10055+
10056+static const struct v4l2_subdev_video_ops h3a_af_subdev_video_ops = {
10057+ .s_stream = omap3isp_stat_s_stream,
10058+};
10059+
10060+static const struct v4l2_subdev_ops h3a_af_subdev_ops = {
10061+ .core = &h3a_af_subdev_core_ops,
10062+ .video = &h3a_af_subdev_video_ops,
10063+};
10064+
10065+/* Function to register the AF character device driver. */
10066+int omap3isp_h3a_af_init(struct isp_device *isp)
10067+{
10068+ struct ispstat *af = &isp->isp_af;
10069+ struct omap3isp_h3a_af_config *af_cfg;
10070+ struct omap3isp_h3a_af_config *af_recover_cfg;
10071+ int ret;
10072+
10073+ af_cfg = kzalloc(sizeof(*af_cfg), GFP_KERNEL);
10074+ if (af_cfg == NULL)
10075+ return -ENOMEM;
10076+
10077+ memset(af, 0, sizeof(*af));
10078+ af->ops = &h3a_af_ops;
10079+ af->priv = af_cfg;
10080+ af->dma_ch = -1;
10081+ af->event_type = V4L2_EVENT_OMAP3ISP_AF;
10082+ af->isp = isp;
10083+
10084+ /* Set recover state configuration */
10085+ af_recover_cfg = kzalloc(sizeof(*af_recover_cfg), GFP_KERNEL);
10086+ if (!af_recover_cfg) {
10087+ dev_err(af->isp->dev, "AF: cannot allocate memory for recover "
10088+ "configuration.\n");
10089+ ret = -ENOMEM;
10090+ goto err_recover_alloc;
10091+ }
10092+
10093+ af_recover_cfg->paxel.h_start = OMAP3ISP_AF_PAXEL_HZSTART_MIN;
10094+ af_recover_cfg->paxel.width = OMAP3ISP_AF_PAXEL_WIDTH_MIN;
10095+ af_recover_cfg->paxel.height = OMAP3ISP_AF_PAXEL_HEIGHT_MIN;
10096+ af_recover_cfg->paxel.h_cnt = OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN;
10097+ af_recover_cfg->paxel.v_cnt = OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN;
10098+ af_recover_cfg->paxel.line_inc = OMAP3ISP_AF_PAXEL_INCREMENT_MIN;
10099+ if (h3a_af_validate_params(af, af_recover_cfg)) {
10100+ dev_err(af->isp->dev, "AF: recover configuration is "
10101+ "invalid.\n");
10102+ ret = -EINVAL;
10103+ goto err_conf;
10104+ }
10105+
10106+ af_recover_cfg->buf_size = h3a_af_get_buf_size(af_recover_cfg);
10107+ af->recover_priv = af_recover_cfg;
10108+
10109+ ret = omap3isp_stat_init(af, "AF", &h3a_af_subdev_ops);
10110+ if (ret)
10111+ goto err_conf;
10112+
10113+ return 0;
10114+
10115+err_conf:
10116+ kfree(af_recover_cfg);
10117+err_recover_alloc:
10118+ kfree(af_cfg);
10119+
10120+ return ret;
10121+}
10122+
10123+void omap3isp_h3a_af_cleanup(struct isp_device *isp)
10124+{
10125+ kfree(isp->isp_af.priv);
10126+ kfree(isp->isp_af.recover_priv);
10127+ omap3isp_stat_free(&isp->isp_af);
10128+}
10129diff --git a/drivers/media/video/isp/isphist.c b/drivers/media/video/isp/isphist.c
10130new file mode 100644
10131index 0000000..a43eb92
10132--- /dev/null
10133+++ b/drivers/media/video/isp/isphist.c
10134@@ -0,0 +1,520 @@
10135+/*
10136+ * isphist.c
10137+ *
10138+ * TI OMAP3 ISP - Histogram module
10139+ *
10140+ * Copyright (C) 2010 Nokia Corporation
10141+ * Copyright (C) 2009 Texas Instruments, Inc.
10142+ *
10143+ * Contacts: David Cohen <david.cohen@nokia.com>
10144+ * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10145+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
10146+ *
10147+ * This program is free software; you can redistribute it and/or modify
10148+ * it under the terms of the GNU General Public License version 2 as
10149+ * published by the Free Software Foundation.
10150+ *
10151+ * This program is distributed in the hope that it will be useful, but
10152+ * WITHOUT ANY WARRANTY; without even the implied warranty of
10153+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10154+ * General Public License for more details.
10155+ *
10156+ * You should have received a copy of the GNU General Public License
10157+ * along with this program; if not, write to the Free Software
10158+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
10159+ * 02110-1301 USA
10160+ */
10161+
10162+#include <linux/delay.h>
10163+#include <linux/slab.h>
10164+#include <linux/uaccess.h>
10165+#include <linux/device.h>
10166+
10167+#include "isp.h"
10168+#include "ispreg.h"
10169+#include "isphist.h"
10170+
10171+#define HIST_CONFIG_DMA 1
10172+
10173+#define HIST_USING_DMA(hist) ((hist)->dma_ch >= 0)
10174+
10175+/*
10176+ * hist_reset_mem - clear Histogram memory before start stats engine.
10177+ */
10178+static void hist_reset_mem(struct ispstat *hist)
10179+{
10180+ struct isp_device *isp = hist->isp;
10181+ struct omap3isp_hist_config *conf = hist->priv;
10182+ unsigned int i;
10183+
10184+ isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
10185+
10186+ /*
10187+ * By setting it, the histogram internal buffer is being cleared at the
10188+ * same time it's being read. This bit must be cleared afterwards.
10189+ */
10190+ isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);
10191+
10192+ /*
10193+ * We'll clear 4 words at each iteration for optimization. It avoids
10194+ * 3/4 of the jumps. We also know HIST_MEM_SIZE is divisible by 4.
10195+ */
10196+ for (i = OMAP3ISP_HIST_MEM_SIZE / 4; i > 0; i--) {
10197+ isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
10198+ isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
10199+ isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
10200+ isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
10201+ }
10202+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);
10203+
10204+ hist->wait_acc_frames = conf->num_acc_frames;
10205+}
10206+
10207+static void hist_dma_config(struct ispstat *hist)
10208+{
10209+ hist->dma_config.data_type = OMAP_DMA_DATA_TYPE_S32;
10210+ hist->dma_config.sync_mode = OMAP_DMA_SYNC_ELEMENT;
10211+ hist->dma_config.frame_count = 1;
10212+ hist->dma_config.src_amode = OMAP_DMA_AMODE_CONSTANT;
10213+ hist->dma_config.src_start = OMAP3ISP_HIST_REG_BASE + ISPHIST_DATA;
10214+ hist->dma_config.dst_amode = OMAP_DMA_AMODE_POST_INC;
10215+ hist->dma_config.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
10216+}
10217+
10218+/*
10219+ * hist_setup_regs - Helper function to update Histogram registers.
10220+ */
10221+static void hist_setup_regs(struct ispstat *hist, void *priv)
10222+{
10223+ struct isp_device *isp = hist->isp;
10224+ struct omap3isp_hist_config *conf = priv;
10225+ int c;
10226+ u32 cnt;
10227+ u32 wb_gain;
10228+ u32 reg_hor[OMAP3ISP_HIST_MAX_REGIONS];
10229+ u32 reg_ver[OMAP3ISP_HIST_MAX_REGIONS];
10230+
10231+ if (!hist->update || hist->state == ISPSTAT_DISABLED ||
10232+ hist->state == ISPSTAT_DISABLING)
10233+ return;
10234+
10235+ cnt = conf->cfa << ISPHIST_CNT_CFA_SHIFT;
10236+
10237+ wb_gain = conf->wg[0] << ISPHIST_WB_GAIN_WG00_SHIFT;
10238+ wb_gain |= conf->wg[1] << ISPHIST_WB_GAIN_WG01_SHIFT;
10239+ wb_gain |= conf->wg[2] << ISPHIST_WB_GAIN_WG02_SHIFT;
10240+ if (conf->cfa == OMAP3ISP_HIST_CFA_BAYER)
10241+ wb_gain |= conf->wg[3] << ISPHIST_WB_GAIN_WG03_SHIFT;
10242+
10243+ /* Regions size and position */
10244+ for (c = 0; c < OMAP3ISP_HIST_MAX_REGIONS; c++) {
10245+ if (c < conf->num_regions) {
10246+ reg_hor[c] = conf->region[c].h_start <<
10247+ ISPHIST_REG_START_SHIFT;
10248+ reg_hor[c] = conf->region[c].h_end <<
10249+ ISPHIST_REG_END_SHIFT;
10250+ reg_ver[c] = conf->region[c].v_start <<
10251+ ISPHIST_REG_START_SHIFT;
10252+ reg_ver[c] = conf->region[c].v_end <<
10253+ ISPHIST_REG_END_SHIFT;
10254+ } else {
10255+ reg_hor[c] = 0;
10256+ reg_ver[c] = 0;
10257+ }
10258+ }
10259+
10260+ cnt |= conf->hist_bins << ISPHIST_CNT_BINS_SHIFT;
10261+ switch (conf->hist_bins) {
10262+ case OMAP3ISP_HIST_BINS_256:
10263+ cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 8) <<
10264+ ISPHIST_CNT_SHIFT_SHIFT;
10265+ break;
10266+ case OMAP3ISP_HIST_BINS_128:
10267+ cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 7) <<
10268+ ISPHIST_CNT_SHIFT_SHIFT;
10269+ break;
10270+ case OMAP3ISP_HIST_BINS_64:
10271+ cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 6) <<
10272+ ISPHIST_CNT_SHIFT_SHIFT;
10273+ break;
10274+ default: /* OMAP3ISP_HIST_BINS_32 */
10275+ cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 5) <<
10276+ ISPHIST_CNT_SHIFT_SHIFT;
10277+ break;
10278+ }
10279+
10280+ hist_reset_mem(hist);
10281+
10282+ isp_reg_writel(isp, cnt, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT);
10283+ isp_reg_writel(isp, wb_gain, OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN);
10284+ isp_reg_writel(isp, reg_hor[0], OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ);
10285+ isp_reg_writel(isp, reg_ver[0], OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT);
10286+ isp_reg_writel(isp, reg_hor[1], OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ);
10287+ isp_reg_writel(isp, reg_ver[1], OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT);
10288+ isp_reg_writel(isp, reg_hor[2], OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ);
10289+ isp_reg_writel(isp, reg_ver[2], OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT);
10290+ isp_reg_writel(isp, reg_hor[3], OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ);
10291+ isp_reg_writel(isp, reg_ver[3], OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT);
10292+
10293+ hist->update = 0;
10294+ hist->config_counter += hist->inc_config;
10295+ hist->inc_config = 0;
10296+ hist->buf_size = conf->buf_size;
10297+}
10298+
10299+static void hist_enable(struct ispstat *hist, int enable)
10300+{
10301+ if (enable) {
10302+ isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR,
10303+ ISPHIST_PCR_ENABLE);
10304+ isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
10305+ ISPCTRL_HIST_CLK_EN);
10306+ } else {
10307+ isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR,
10308+ ISPHIST_PCR_ENABLE);
10309+ isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
10310+ ISPCTRL_HIST_CLK_EN);
10311+ }
10312+}
10313+
10314+static int hist_busy(struct ispstat *hist)
10315+{
10316+ return isp_reg_readl(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR)
10317+ & ISPHIST_PCR_BUSY;
10318+}
10319+
10320+static void hist_dma_cb(int lch, u16 ch_status, void *data)
10321+{
10322+ struct ispstat *hist = data;
10323+
10324+ if (ch_status & ~OMAP_DMA_BLOCK_IRQ) {
10325+ dev_dbg(hist->isp->dev, "hist: DMA error. status = 0x%04x\n",
10326+ ch_status);
10327+ omap_stop_dma(lch);
10328+ hist_reset_mem(hist);
10329+ atomic_set(&hist->buf_err, 1);
10330+ }
10331+ isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
10332+ ISPHIST_CNT_CLEAR);
10333+
10334+ omap3isp_stat_dma_isr(hist);
10335+ if (hist->state != ISPSTAT_DISABLED)
10336+ omap3isp_hist_dma_done(hist->isp);
10337+}
10338+
10339+static int hist_buf_dma(struct ispstat *hist)
10340+{
10341+ dma_addr_t dma_addr = hist->active_buf->dma_addr;
10342+
10343+ if (unlikely(!dma_addr)) {
10344+ dev_dbg(hist->isp->dev, "hist: invalid DMA buffer address\n");
10345+ hist_reset_mem(hist);
10346+ return STAT_NO_BUF;
10347+ }
10348+
10349+ isp_reg_writel(hist->isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
10350+ isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
10351+ ISPHIST_CNT_CLEAR);
10352+ omap3isp_flush(hist->isp);
10353+ hist->dma_config.dst_start = dma_addr;
10354+ hist->dma_config.elem_count = hist->buf_size / sizeof(u32);
10355+ omap_set_dma_params(hist->dma_ch, &hist->dma_config);
10356+
10357+ omap_start_dma(hist->dma_ch);
10358+
10359+ return STAT_BUF_WAITING_DMA;
10360+}
10361+
10362+static int hist_buf_pio(struct ispstat *hist)
10363+{
10364+ struct isp_device *isp = hist->isp;
10365+ u32 *buf = hist->active_buf->virt_addr;
10366+ unsigned int i;
10367+
10368+ if (!buf) {
10369+ dev_dbg(isp->dev, "hist: invalid PIO buffer address\n");
10370+ hist_reset_mem(hist);
10371+ return STAT_NO_BUF;
10372+ }
10373+
10374+ isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
10375+
10376+ /*
10377+ * By setting it, the histogram internal buffer is being cleared at the
10378+ * same time it's being read. This bit must be cleared just after all
10379+ * data is acquired.
10380+ */
10381+ isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);
10382+
10383+ /*
10384+ * We'll read 4 times a 4-bytes-word at each iteration for
10385+ * optimization. It avoids 3/4 of the jumps. We also know buf_size is
10386+ * divisible by 16.
10387+ */
10388+ for (i = hist->buf_size / 16; i > 0; i--) {
10389+ *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
10390+ *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
10391+ *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
10392+ *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
10393+ }
10394+ isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
10395+ ISPHIST_CNT_CLEAR);
10396+
10397+ return STAT_BUF_DONE;
10398+}
10399+
10400+/*
10401+ * hist_buf_process - Callback from ISP driver for HIST interrupt.
10402+ */
10403+static int hist_buf_process(struct ispstat *hist)
10404+{
10405+ struct omap3isp_hist_config *user_cfg = hist->priv;
10406+ int ret;
10407+
10408+ if (atomic_read(&hist->buf_err) || hist->state != ISPSTAT_ENABLED) {
10409+ hist_reset_mem(hist);
10410+ return STAT_NO_BUF;
10411+ }
10412+
10413+ if (--(hist->wait_acc_frames))
10414+ return STAT_NO_BUF;
10415+
10416+ if (HIST_USING_DMA(hist))
10417+ ret = hist_buf_dma(hist);
10418+ else
10419+ ret = hist_buf_pio(hist);
10420+
10421+ hist->wait_acc_frames = user_cfg->num_acc_frames;
10422+
10423+ return ret;
10424+}
10425+
10426+static u32 hist_get_buf_size(struct omap3isp_hist_config *conf)
10427+{
10428+ return OMAP3ISP_HIST_MEM_SIZE_BINS(conf->hist_bins) * conf->num_regions;
10429+}
10430+
10431+/*
10432+ * hist_validate_params - Helper function to check user given params.
10433+ * @user_cfg: Pointer to user configuration structure.
10434+ *
10435+ * Returns 0 on success configuration.
10436+ */
10437+static int hist_validate_params(struct ispstat *hist, void *new_conf)
10438+{
10439+ struct omap3isp_hist_config *user_cfg = new_conf;
10440+ int c;
10441+ u32 buf_size;
10442+
10443+ if (user_cfg->cfa > OMAP3ISP_HIST_CFA_FOVEONX3)
10444+ return -EINVAL;
10445+
10446+ /* Regions size and position */
10447+
10448+ if ((user_cfg->num_regions < OMAP3ISP_HIST_MIN_REGIONS) ||
10449+ (user_cfg->num_regions > OMAP3ISP_HIST_MAX_REGIONS))
10450+ return -EINVAL;
10451+
10452+ /* Regions */
10453+ for (c = 0; c < user_cfg->num_regions; c++) {
10454+ if (user_cfg->region[c].h_start & ~ISPHIST_REG_START_END_MASK)
10455+ return -EINVAL;
10456+ if (user_cfg->region[c].h_end & ~ISPHIST_REG_START_END_MASK)
10457+ return -EINVAL;
10458+ if (user_cfg->region[c].v_start & ~ISPHIST_REG_START_END_MASK)
10459+ return -EINVAL;
10460+ if (user_cfg->region[c].v_end & ~ISPHIST_REG_START_END_MASK)
10461+ return -EINVAL;
10462+ if (user_cfg->region[c].h_start > user_cfg->region[c].h_end)
10463+ return -EINVAL;
10464+ if (user_cfg->region[c].v_start > user_cfg->region[c].v_end)
10465+ return -EINVAL;
10466+ }
10467+
10468+ switch (user_cfg->num_regions) {
10469+ case 1:
10470+ if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_256)
10471+ return -EINVAL;
10472+ break;
10473+ case 2:
10474+ if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_128)
10475+ return -EINVAL;
10476+ break;
10477+ default: /* 3 or 4 */
10478+ if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_64)
10479+ return -EINVAL;
10480+ break;
10481+ }
10482+
10483+ buf_size = hist_get_buf_size(user_cfg);
10484+ if (buf_size > user_cfg->buf_size)
10485+ /* User's buf_size request wasn't enoght */
10486+ user_cfg->buf_size = buf_size;
10487+ else if (user_cfg->buf_size > OMAP3ISP_HIST_MAX_BUF_SIZE)
10488+ user_cfg->buf_size = OMAP3ISP_HIST_MAX_BUF_SIZE;
10489+
10490+ return 0;
10491+}
10492+
10493+static int hist_comp_params(struct ispstat *hist,
10494+ struct omap3isp_hist_config *user_cfg)
10495+{
10496+ struct omap3isp_hist_config *cur_cfg = hist->priv;
10497+ int c;
10498+
10499+ if (cur_cfg->cfa != user_cfg->cfa)
10500+ return 1;
10501+
10502+ if (cur_cfg->num_acc_frames != user_cfg->num_acc_frames)
10503+ return 1;
10504+
10505+ if (cur_cfg->hist_bins != user_cfg->hist_bins)
10506+ return 1;
10507+
10508+ for (c = 0; c < OMAP3ISP_HIST_MAX_WG; c++) {
10509+ if (c == 3 && user_cfg->cfa == OMAP3ISP_HIST_CFA_FOVEONX3)
10510+ break;
10511+ else if (cur_cfg->wg[c] != user_cfg->wg[c])
10512+ return 1;
10513+ }
10514+
10515+ if (cur_cfg->num_regions != user_cfg->num_regions)
10516+ return 1;
10517+
10518+ /* Regions */
10519+ for (c = 0; c < user_cfg->num_regions; c++) {
10520+ if (cur_cfg->region[c].h_start != user_cfg->region[c].h_start)
10521+ return 1;
10522+ if (cur_cfg->region[c].h_end != user_cfg->region[c].h_end)
10523+ return 1;
10524+ if (cur_cfg->region[c].v_start != user_cfg->region[c].v_start)
10525+ return 1;
10526+ if (cur_cfg->region[c].v_end != user_cfg->region[c].v_end)
10527+ return 1;
10528+ }
10529+
10530+ return 0;
10531+}
10532+
10533+/*
10534+ * hist_update_params - Helper function to check and store user given params.
10535+ * @new_conf: Pointer to user configuration structure.
10536+ */
10537+static void hist_set_params(struct ispstat *hist, void *new_conf)
10538+{
10539+ struct omap3isp_hist_config *user_cfg = new_conf;
10540+ struct omap3isp_hist_config *cur_cfg = hist->priv;
10541+
10542+ if (!hist->configured || hist_comp_params(hist, user_cfg)) {
10543+ memcpy(cur_cfg, user_cfg, sizeof(*user_cfg));
10544+ if (user_cfg->num_acc_frames == 0)
10545+ user_cfg->num_acc_frames = 1;
10546+ hist->inc_config++;
10547+ hist->update = 1;
10548+ /*
10549+ * User might be asked for a bigger buffer than necessary for
10550+ * this configuration. In order to return the right amount of
10551+ * data during buffer request, let's calculate the size here
10552+ * instead of stick with user_cfg->buf_size.
10553+ */
10554+ cur_cfg->buf_size = hist_get_buf_size(cur_cfg);
10555+
10556+ }
10557+}
10558+
10559+static long hist_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
10560+{
10561+ struct ispstat *stat = v4l2_get_subdevdata(sd);
10562+
10563+ switch (cmd) {
10564+ case VIDIOC_OMAP3ISP_HIST_CFG:
10565+ return omap3isp_stat_config(stat, arg);
10566+ case VIDIOC_OMAP3ISP_STAT_REQ:
10567+ return omap3isp_stat_request_statistics(stat, arg);
10568+ case VIDIOC_OMAP3ISP_STAT_EN: {
10569+ int *en = arg;
10570+ return omap3isp_stat_enable(stat, !!*en);
10571+ }
10572+ }
10573+
10574+ return -ENOIOCTLCMD;
10575+
10576+}
10577+
10578+static const struct ispstat_ops hist_ops = {
10579+ .validate_params = hist_validate_params,
10580+ .set_params = hist_set_params,
10581+ .setup_regs = hist_setup_regs,
10582+ .enable = hist_enable,
10583+ .busy = hist_busy,
10584+ .buf_process = hist_buf_process,
10585+};
10586+
10587+static const struct v4l2_subdev_core_ops hist_subdev_core_ops = {
10588+ .ioctl = hist_ioctl,
10589+ .subscribe_event = omap3isp_stat_subscribe_event,
10590+ .unsubscribe_event = omap3isp_stat_unsubscribe_event,
10591+};
10592+
10593+static const struct v4l2_subdev_video_ops hist_subdev_video_ops = {
10594+ .s_stream = omap3isp_stat_s_stream,
10595+};
10596+
10597+static const struct v4l2_subdev_ops hist_subdev_ops = {
10598+ .core = &hist_subdev_core_ops,
10599+ .video = &hist_subdev_video_ops,
10600+};
10601+
10602+/*
10603+ * omap3isp_hist_init - Module Initialization.
10604+ */
10605+int omap3isp_hist_init(struct isp_device *isp)
10606+{
10607+ struct ispstat *hist = &isp->isp_hist;
10608+ struct omap3isp_hist_config *hist_cfg;
10609+ int ret = -1;
10610+
10611+ hist_cfg = kzalloc(sizeof(*hist_cfg), GFP_KERNEL);
10612+ if (hist_cfg == NULL)
10613+ return -ENOMEM;
10614+
10615+ memset(hist, 0, sizeof(*hist));
10616+ if (HIST_CONFIG_DMA)
10617+ ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, "DMA_ISP_HIST",
10618+ hist_dma_cb, hist, &hist->dma_ch);
10619+ if (ret) {
10620+ if (HIST_CONFIG_DMA)
10621+ dev_warn(isp->dev, "hist: DMA request channel failed. "
10622+ "Using PIO only.\n");
10623+ hist->dma_ch = -1;
10624+ } else {
10625+ dev_dbg(isp->dev, "hist: DMA channel = %d\n", hist->dma_ch);
10626+ hist_dma_config(hist);
10627+ omap_enable_dma_irq(hist->dma_ch, OMAP_DMA_BLOCK_IRQ);
10628+ }
10629+
10630+ hist->ops = &hist_ops;
10631+ hist->priv = hist_cfg;
10632+ hist->event_type = V4L2_EVENT_OMAP3ISP_HIST;
10633+ hist->isp = isp;
10634+
10635+ ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops);
10636+ if (ret) {
10637+ kfree(hist_cfg);
10638+ if (HIST_USING_DMA(hist))
10639+ omap_free_dma(hist->dma_ch);
10640+ }
10641+
10642+ return ret;
10643+}
10644+
10645+/*
10646+ * omap3isp_hist_cleanup - Module cleanup.
10647+ */
10648+void omap3isp_hist_cleanup(struct isp_device *isp)
10649+{
10650+ if (HIST_USING_DMA(&isp->isp_hist))
10651+ omap_free_dma(isp->isp_hist.dma_ch);
10652+ kfree(isp->isp_hist.priv);
10653+ omap3isp_stat_free(&isp->isp_hist);
10654+}
10655diff --git a/drivers/media/video/isp/isphist.h b/drivers/media/video/isp/isphist.h
10656new file mode 100644
10657index 0000000..247192b
10658--- /dev/null
10659+++ b/drivers/media/video/isp/isphist.h
10660@@ -0,0 +1,40 @@
10661+/*
10662+ * isphist.h
10663+ *
10664+ * TI OMAP3 ISP - Histogram module
10665+ *
10666+ * Copyright (C) 2010 Nokia Corporation
10667+ * Copyright (C) 2009 Texas Instruments, Inc.
10668+ *
10669+ * Contacts: David Cohen <david.cohen@nokia.com>
10670+ * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10671+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
10672+ *
10673+ * This program is free software; you can redistribute it and/or modify
10674+ * it under the terms of the GNU General Public License version 2 as
10675+ * published by the Free Software Foundation.
10676+ *
10677+ * This program is distributed in the hope that it will be useful, but
10678+ * WITHOUT ANY WARRANTY; without even the implied warranty of
10679+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10680+ * General Public License for more details.
10681+ *
10682+ * You should have received a copy of the GNU General Public License
10683+ * along with this program; if not, write to the Free Software
10684+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
10685+ * 02110-1301 USA
10686+ */
10687+
10688+#ifndef OMAP3_ISP_HIST_H
10689+#define OMAP3_ISP_HIST_H
10690+
10691+#include <linux/omap3isp.h>
10692+
10693+#define ISPHIST_IN_BIT_WIDTH_CCDC 10
10694+
10695+struct isp_device;
10696+
10697+int omap3isp_hist_init(struct isp_device *isp);
10698+void omap3isp_hist_cleanup(struct isp_device *isp);
10699+
10700+#endif /* OMAP3_ISP_HIST */
10701diff --git a/drivers/media/video/isp/isppreview.c b/drivers/media/video/isp/isppreview.c
10702new file mode 100644
10703index 0000000..869583c
10704--- /dev/null
10705+++ b/drivers/media/video/isp/isppreview.c
10706@@ -0,0 +1,2120 @@
10707+/*
10708+ * isppreview.c
10709+ *
10710+ * TI OMAP3 ISP driver - Preview module
10711+ *
10712+ * Copyright (C) 2010 Nokia Corporation
10713+ * Copyright (C) 2009 Texas Instruments, Inc.
10714+ *
10715+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10716+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
10717+ *
10718+ * This program is free software; you can redistribute it and/or modify
10719+ * it under the terms of the GNU General Public License version 2 as
10720+ * published by the Free Software Foundation.
10721+ *
10722+ * This program is distributed in the hope that it will be useful, but
10723+ * WITHOUT ANY WARRANTY; without even the implied warranty of
10724+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10725+ * General Public License for more details.
10726+ *
10727+ * You should have received a copy of the GNU General Public License
10728+ * along with this program; if not, write to the Free Software
10729+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
10730+ * 02110-1301 USA
10731+ */
10732+
10733+#include <linux/device.h>
10734+#include <linux/mm.h>
10735+#include <linux/module.h>
10736+#include <linux/mutex.h>
10737+#include <linux/uaccess.h>
10738+
10739+#include "isp.h"
10740+#include "ispreg.h"
10741+#include "isppreview.h"
10742+
10743+/* Default values in Office Flourescent Light for RGBtoRGB Blending */
10744+static struct omap3isp_prev_rgbtorgb flr_rgb2rgb = {
10745+ { /* RGB-RGB Matrix */
10746+ {0x01E2, 0x0F30, 0x0FEE},
10747+ {0x0F9B, 0x01AC, 0x0FB9},
10748+ {0x0FE0, 0x0EC0, 0x0260}
10749+ }, /* RGB Offset */
10750+ {0x0000, 0x0000, 0x0000}
10751+};
10752+
10753+/* Default values in Office Flourescent Light for RGB to YUV Conversion*/
10754+static struct omap3isp_prev_csc flr_prev_csc = {
10755+ { /* CSC Coef Matrix */
10756+ {66, 129, 25},
10757+ {-38, -75, 112},
10758+ {112, -94 , -18}
10759+ }, /* CSC Offset */
10760+ {0x0, 0x0, 0x0}
10761+};
10762+
10763+/* Default values in Office Flourescent Light for CFA Gradient*/
10764+#define FLR_CFA_GRADTHRS_HORZ 0x28
10765+#define FLR_CFA_GRADTHRS_VERT 0x28
10766+
10767+/* Default values in Office Flourescent Light for Chroma Suppression*/
10768+#define FLR_CSUP_GAIN 0x0D
10769+#define FLR_CSUP_THRES 0xEB
10770+
10771+/* Default values in Office Flourescent Light for Noise Filter*/
10772+#define FLR_NF_STRGTH 0x03
10773+
10774+/* Default values for White Balance */
10775+#define FLR_WBAL_DGAIN 0x100
10776+#define FLR_WBAL_COEF 0x20
10777+
10778+/* Default values in Office Flourescent Light for Black Adjustment*/
10779+#define FLR_BLKADJ_BLUE 0x0
10780+#define FLR_BLKADJ_GREEN 0x0
10781+#define FLR_BLKADJ_RED 0x0
10782+
10783+#define DEF_DETECT_CORRECT_VAL 0xe
10784+
10785+#define PREV_MIN_WIDTH 64
10786+#define PREV_MIN_HEIGHT 8
10787+#define PREV_MAX_HEIGHT 16384
10788+
10789+/*
10790+ * Coeficient Tables for the submodules in Preview.
10791+ * Array is initialised with the values from.the tables text file.
10792+ */
10793+
10794+/*
10795+ * CFA Filter Coefficient Table
10796+ *
10797+ */
10798+static u32 cfa_coef_table[] = {
10799+#include "cfa_coef_table.h"
10800+};
10801+
10802+/*
10803+ * Default Gamma Correction Table - All components
10804+ */
10805+static u32 gamma_table[] = {
10806+#include "gamma_table.h"
10807+};
10808+
10809+/*
10810+ * Noise Filter Threshold table
10811+ */
10812+static u32 noise_filter_table[] = {
10813+#include "noise_filter_table.h"
10814+};
10815+
10816+/*
10817+ * Luminance Enhancement Table
10818+ */
10819+static u32 luma_enhance_table[] = {
10820+#include "luma_enhance_table.h"
10821+};
10822+
10823+/*
10824+ * preview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview.
10825+ * @enable: 1 - Reverse the A-Law done in CCDC.
10826+ */
10827+static void
10828+preview_enable_invalaw(struct isp_prev_device *prev, u8 enable)
10829+{
10830+ struct isp_device *isp = to_isp_device(prev);
10831+
10832+ if (enable)
10833+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10834+ ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
10835+ else
10836+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10837+ ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
10838+}
10839+
10840+/*
10841+ * preview_enable_drkframe_capture - Enable/Disable of the darkframe capture.
10842+ * @prev -
10843+ * @enable: 1 - Enable, 0 - Disable
10844+ *
10845+ * NOTE: PRV_WSDR_ADDR and PRV_WADD_OFFSET must be set also
10846+ * The proccess is applied for each captured frame.
10847+ */
10848+static void
10849+preview_enable_drkframe_capture(struct isp_prev_device *prev, u8 enable)
10850+{
10851+ struct isp_device *isp = to_isp_device(prev);
10852+
10853+ if (enable)
10854+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10855+ ISPPRV_PCR_DRKFCAP);
10856+ else
10857+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10858+ ISPPRV_PCR_DRKFCAP);
10859+}
10860+
10861+/*
10862+ * preview_enable_drkframe - Enable/Disable of the darkframe subtract.
10863+ * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is
10864+ * subtracted with the pixels in the current frame.
10865+ *
10866+ * The proccess is applied for each captured frame.
10867+ */
10868+static void
10869+preview_enable_drkframe(struct isp_prev_device *prev, u8 enable)
10870+{
10871+ struct isp_device *isp = to_isp_device(prev);
10872+
10873+ if (enable)
10874+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10875+ ISPPRV_PCR_DRKFEN);
10876+ else
10877+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10878+ ISPPRV_PCR_DRKFEN);
10879+}
10880+
10881+/*
10882+ * preview_config_drkf_shadcomp - Configures shift value in shading comp.
10883+ * @scomp_shtval: 3bit value of shift used in shading compensation.
10884+ */
10885+static void
10886+preview_config_drkf_shadcomp(struct isp_prev_device *prev,
10887+ const void *scomp_shtval)
10888+{
10889+ struct isp_device *isp = to_isp_device(prev);
10890+ const u32 *shtval = scomp_shtval;
10891+
10892+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10893+ ISPPRV_PCR_SCOMP_SFT_MASK,
10894+ *shtval << ISPPRV_PCR_SCOMP_SFT_SHIFT);
10895+}
10896+
10897+/*
10898+ * preview_enable_hmed - Enables/Disables of the Horizontal Median Filter.
10899+ * @enable: 1 - Enables Horizontal Median Filter.
10900+ */
10901+static void
10902+preview_enable_hmed(struct isp_prev_device *prev, u8 enable)
10903+{
10904+ struct isp_device *isp = to_isp_device(prev);
10905+
10906+ if (enable)
10907+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10908+ ISPPRV_PCR_HMEDEN);
10909+ else
10910+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10911+ ISPPRV_PCR_HMEDEN);
10912+}
10913+
10914+/*
10915+ * preview_config_hmed - Configures the Horizontal Median Filter.
10916+ * @prev_hmed: Structure containing the odd and even distance between the
10917+ * pixels in the image along with the filter threshold.
10918+ */
10919+static void
10920+preview_config_hmed(struct isp_prev_device *prev, const void *prev_hmed)
10921+{
10922+ struct isp_device *isp = to_isp_device(prev);
10923+ const struct omap3isp_prev_hmed *hmed = prev_hmed;
10924+
10925+ isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) |
10926+ (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) |
10927+ (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT),
10928+ OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
10929+}
10930+
10931+/*
10932+ * preview_config_noisefilter - Configures the Noise Filter.
10933+ * @prev_nf: Structure containing the noisefilter table, strength to be used
10934+ * for the noise filter and the defect correction enable flag.
10935+ */
10936+static void
10937+preview_config_noisefilter(struct isp_prev_device *prev, const void *prev_nf)
10938+{
10939+ struct isp_device *isp = to_isp_device(prev);
10940+ const struct omap3isp_prev_nf *nf = prev_nf;
10941+ unsigned int i;
10942+
10943+ isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
10944+ isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR,
10945+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
10946+ for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) {
10947+ isp_reg_writel(isp, nf->table[i],
10948+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
10949+ }
10950+}
10951+
10952+/*
10953+ * preview_config_dcor - Configures the defect correction
10954+ * @prev_dcor: Structure containing the defect correct thresholds
10955+ */
10956+static void
10957+preview_config_dcor(struct isp_prev_device *prev, const void *prev_dcor)
10958+{
10959+ struct isp_device *isp = to_isp_device(prev);
10960+ const struct omap3isp_prev_dcor *dcor = prev_dcor;
10961+
10962+ isp_reg_writel(isp, dcor->detect_correct[0],
10963+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
10964+ isp_reg_writel(isp, dcor->detect_correct[1],
10965+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
10966+ isp_reg_writel(isp, dcor->detect_correct[2],
10967+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
10968+ isp_reg_writel(isp, dcor->detect_correct[3],
10969+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
10970+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10971+ ISPPRV_PCR_DCCOUP,
10972+ dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0);
10973+}
10974+
10975+/*
10976+ * preview_config_cfa - Configures the CFA Interpolation parameters.
10977+ * @prev_cfa: Structure containing the CFA interpolation table, CFA format
10978+ * in the image, vertical and horizontal gradient threshold.
10979+ */
10980+static void
10981+preview_config_cfa(struct isp_prev_device *prev, const void *prev_cfa)
10982+{
10983+ struct isp_device *isp = to_isp_device(prev);
10984+ const struct omap3isp_prev_cfa *cfa = prev_cfa;
10985+ unsigned int i;
10986+
10987+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
10988+ ISPPRV_PCR_CFAFMT_MASK,
10989+ cfa->format << ISPPRV_PCR_CFAFMT_SHIFT);
10990+
10991+ isp_reg_writel(isp,
10992+ (cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
10993+ (cfa->gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
10994+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
10995+
10996+ isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR,
10997+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
10998+
10999+ for (i = 0; i < OMAP3ISP_PREV_CFA_TBL_SIZE; i++) {
11000+ isp_reg_writel(isp, cfa->table[i],
11001+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
11002+ }
11003+}
11004+
11005+/*
11006+ * preview_config_gammacorrn - Configures the Gamma Correction table values
11007+ * @gtable: Structure containing the table for red, blue, green gamma table.
11008+ */
11009+static void
11010+preview_config_gammacorrn(struct isp_prev_device *prev, const void *gtable)
11011+{
11012+ struct isp_device *isp = to_isp_device(prev);
11013+ const struct omap3isp_prev_gtables *gt = gtable;
11014+ unsigned int i;
11015+
11016+ isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR,
11017+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
11018+ for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
11019+ isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV,
11020+ ISPPRV_SET_TBL_DATA);
11021+
11022+ isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR,
11023+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
11024+ for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
11025+ isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV,
11026+ ISPPRV_SET_TBL_DATA);
11027+
11028+ isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR,
11029+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
11030+ for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
11031+ isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV,
11032+ ISPPRV_SET_TBL_DATA);
11033+}
11034+
11035+/*
11036+ * preview_config_luma_enhancement - Sets the Luminance Enhancement table.
11037+ * @ytable: Structure containing the table for Luminance Enhancement table.
11038+ */
11039+static void
11040+preview_config_luma_enhancement(struct isp_prev_device *prev,
11041+ const void *ytable)
11042+{
11043+ struct isp_device *isp = to_isp_device(prev);
11044+ const struct omap3isp_prev_luma *yt = ytable;
11045+ unsigned int i;
11046+
11047+ isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR,
11048+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
11049+ for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) {
11050+ isp_reg_writel(isp, yt->table[i],
11051+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
11052+ }
11053+}
11054+
11055+/*
11056+ * preview_config_chroma_suppression - Configures the Chroma Suppression.
11057+ * @csup: Structure containing the threshold value for suppression
11058+ * and the hypass filter enable flag.
11059+ */
11060+static void
11061+preview_config_chroma_suppression(struct isp_prev_device *prev,
11062+ const void *csup)
11063+{
11064+ struct isp_device *isp = to_isp_device(prev);
11065+ const struct omap3isp_prev_csup *cs = csup;
11066+
11067+ isp_reg_writel(isp,
11068+ cs->gain | (cs->thres << ISPPRV_CSUP_THRES_SHIFT) |
11069+ (cs->hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
11070+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
11071+}
11072+
11073+/*
11074+ * preview_enable_noisefilter - Enables/Disables the Noise Filter.
11075+ * @enable: 1 - Enables the Noise Filter.
11076+ */
11077+static void
11078+preview_enable_noisefilter(struct isp_prev_device *prev, u8 enable)
11079+{
11080+ struct isp_device *isp = to_isp_device(prev);
11081+
11082+ if (enable)
11083+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11084+ ISPPRV_PCR_NFEN);
11085+ else
11086+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11087+ ISPPRV_PCR_NFEN);
11088+}
11089+
11090+/*
11091+ * preview_enable_dcor - Enables/Disables the defect correction.
11092+ * @enable: 1 - Enables the defect correction.
11093+ */
11094+static void
11095+preview_enable_dcor(struct isp_prev_device *prev, u8 enable)
11096+{
11097+ struct isp_device *isp = to_isp_device(prev);
11098+
11099+ if (enable)
11100+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11101+ ISPPRV_PCR_DCOREN);
11102+ else
11103+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11104+ ISPPRV_PCR_DCOREN);
11105+}
11106+
11107+/*
11108+ * preview_enable_cfa - Enable/Disable the CFA Interpolation.
11109+ * @enable: 1 - Enables the CFA.
11110+ */
11111+static void
11112+preview_enable_cfa(struct isp_prev_device *prev, u8 enable)
11113+{
11114+ struct isp_device *isp = to_isp_device(prev);
11115+
11116+ if (enable)
11117+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11118+ ISPPRV_PCR_CFAEN);
11119+ else
11120+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11121+ ISPPRV_PCR_CFAEN);
11122+}
11123+
11124+/*
11125+ * preview_enable_gammabypass - Enables/Disables the GammaByPass
11126+ * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB.
11127+ * 0 - Goes through Gamma Correction. input and output is 10bit.
11128+ */
11129+static void
11130+preview_enable_gammabypass(struct isp_prev_device *prev, u8 enable)
11131+{
11132+ struct isp_device *isp = to_isp_device(prev);
11133+
11134+ if (enable)
11135+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11136+ ISPPRV_PCR_GAMMA_BYPASS);
11137+ else
11138+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11139+ ISPPRV_PCR_GAMMA_BYPASS);
11140+}
11141+
11142+/*
11143+ * preview_enable_luma_enhancement - Enables/Disables Luminance Enhancement
11144+ * @enable: 1 - Enable the Luminance Enhancement.
11145+ */
11146+static void
11147+preview_enable_luma_enhancement(struct isp_prev_device *prev, u8 enable)
11148+{
11149+ struct isp_device *isp = to_isp_device(prev);
11150+
11151+ if (enable)
11152+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11153+ ISPPRV_PCR_YNENHEN);
11154+ else
11155+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11156+ ISPPRV_PCR_YNENHEN);
11157+}
11158+
11159+/*
11160+ * preview_enable_chroma_suppression - Enables/Disables Chrominance Suppr.
11161+ * @enable: 1 - Enable the Chrominance Suppression.
11162+ */
11163+static void
11164+preview_enable_chroma_suppression(struct isp_prev_device *prev, u8 enable)
11165+{
11166+ struct isp_device *isp = to_isp_device(prev);
11167+
11168+ if (enable)
11169+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11170+ ISPPRV_PCR_SUPEN);
11171+ else
11172+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11173+ ISPPRV_PCR_SUPEN);
11174+}
11175+
11176+/*
11177+ * preview_config_whitebalance - Configures the White Balance parameters.
11178+ * @prev_wbal: Structure containing the digital gain and white balance
11179+ * coefficient.
11180+ *
11181+ * Coefficient matrix always with default values.
11182+ */
11183+static void
11184+preview_config_whitebalance(struct isp_prev_device *prev, const void *prev_wbal)
11185+{
11186+ struct isp_device *isp = to_isp_device(prev);
11187+ const struct omap3isp_prev_wbal *wbal = prev_wbal;
11188+ u32 val;
11189+
11190+ isp_reg_writel(isp, wbal->dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
11191+
11192+ val = wbal->coef0 << ISPPRV_WBGAIN_COEF0_SHIFT;
11193+ val |= wbal->coef1 << ISPPRV_WBGAIN_COEF1_SHIFT;
11194+ val |= wbal->coef2 << ISPPRV_WBGAIN_COEF2_SHIFT;
11195+ val |= wbal->coef3 << ISPPRV_WBGAIN_COEF3_SHIFT;
11196+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
11197+
11198+ isp_reg_writel(isp,
11199+ ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT |
11200+ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT |
11201+ ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT |
11202+ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT |
11203+ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT |
11204+ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT |
11205+ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT |
11206+ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT |
11207+ ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT |
11208+ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT |
11209+ ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT |
11210+ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT |
11211+ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT |
11212+ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT |
11213+ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT |
11214+ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT,
11215+ OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
11216+}
11217+
11218+/*
11219+ * preview_config_blkadj - Configures the Black Adjustment parameters.
11220+ * @prev_blkadj: Structure containing the black adjustment towards red, green,
11221+ * blue.
11222+ */
11223+static void
11224+preview_config_blkadj(struct isp_prev_device *prev, const void *prev_blkadj)
11225+{
11226+ struct isp_device *isp = to_isp_device(prev);
11227+ const struct omap3isp_prev_blkadj *blkadj = prev_blkadj;
11228+
11229+ isp_reg_writel(isp, (blkadj->blue << ISPPRV_BLKADJOFF_B_SHIFT) |
11230+ (blkadj->green << ISPPRV_BLKADJOFF_G_SHIFT) |
11231+ (blkadj->red << ISPPRV_BLKADJOFF_R_SHIFT),
11232+ OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
11233+}
11234+
11235+/*
11236+ * preview_config_rgb_blending - Configures the RGB-RGB Blending matrix.
11237+ * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb
11238+ * offset.
11239+ */
11240+static void
11241+preview_config_rgb_blending(struct isp_prev_device *prev, const void *rgb2rgb)
11242+{
11243+ struct isp_device *isp = to_isp_device(prev);
11244+ const struct omap3isp_prev_rgbtorgb *rgbrgb = rgb2rgb;
11245+ u32 val;
11246+
11247+ val = (rgbrgb->matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
11248+ val |= (rgbrgb->matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
11249+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1);
11250+
11251+ val = (rgbrgb->matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
11252+ val |= (rgbrgb->matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
11253+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2);
11254+
11255+ val = (rgbrgb->matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
11256+ val |= (rgbrgb->matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
11257+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3);
11258+
11259+ val = (rgbrgb->matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
11260+ val |= (rgbrgb->matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
11261+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4);
11262+
11263+ val = (rgbrgb->matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
11264+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5);
11265+
11266+ val = (rgbrgb->offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
11267+ val |= (rgbrgb->offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
11268+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1);
11269+
11270+ val = (rgbrgb->offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
11271+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2);
11272+}
11273+
11274+/*
11275+ * Configures the RGB-YCbYCr conversion matrix
11276+ * @prev_csc: Structure containing the RGB to YCbYCr matrix and the
11277+ * YCbCr offset.
11278+ */
11279+static void
11280+preview_config_rgb_to_ycbcr(struct isp_prev_device *prev, const void *prev_csc)
11281+{
11282+ struct isp_device *isp = to_isp_device(prev);
11283+ const struct omap3isp_prev_csc *csc = prev_csc;
11284+ u32 val;
11285+
11286+ val = (csc->matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
11287+ val |= (csc->matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
11288+ val |= (csc->matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
11289+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
11290+
11291+ val = (csc->matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
11292+ val |= (csc->matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
11293+ val |= (csc->matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
11294+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
11295+
11296+ val = (csc->matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
11297+ val |= (csc->matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
11298+ val |= (csc->matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
11299+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
11300+
11301+ val = (csc->offset[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
11302+ val |= (csc->offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
11303+ val |= (csc->offset[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
11304+ isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
11305+}
11306+
11307+/*
11308+ * preview_update_contrast - Updates the contrast.
11309+ * @contrast: Pointer to hold the current programmed contrast value.
11310+ *
11311+ * Value should be programmed before enabling the module.
11312+ */
11313+static void
11314+preview_update_contrast(struct isp_prev_device *prev, u8 contrast)
11315+{
11316+ struct prev_params *params = &prev->params;
11317+
11318+ if (params->contrast != (contrast * ISPPRV_CONTRAST_UNITS)) {
11319+ params->contrast = contrast * ISPPRV_CONTRAST_UNITS;
11320+ prev->update |= PREV_CONTRAST;
11321+ }
11322+}
11323+
11324+/*
11325+ * preview_config_contrast - Configures the Contrast.
11326+ * @params: Contrast value (u8 pointer, U8Q0 format).
11327+ *
11328+ * Value should be programmed before enabling the module.
11329+ */
11330+static void
11331+preview_config_contrast(struct isp_prev_device *prev, const void *params)
11332+{
11333+ struct isp_device *isp = to_isp_device(prev);
11334+
11335+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
11336+ 0xff << ISPPRV_CNT_BRT_CNT_SHIFT,
11337+ *(u8 *)params << ISPPRV_CNT_BRT_CNT_SHIFT);
11338+}
11339+
11340+/*
11341+ * preview_update_brightness - Updates the brightness in preview module.
11342+ * @brightness: Pointer to hold the current programmed brightness value.
11343+ *
11344+ */
11345+static void
11346+preview_update_brightness(struct isp_prev_device *prev, u8 brightness)
11347+{
11348+ struct prev_params *params = &prev->params;
11349+
11350+ if (params->brightness != (brightness * ISPPRV_BRIGHT_UNITS)) {
11351+ params->brightness = brightness * ISPPRV_BRIGHT_UNITS;
11352+ prev->update |= PREV_BRIGHTNESS;
11353+ }
11354+}
11355+
11356+/*
11357+ * preview_config_brightness - Configures the brightness.
11358+ * @params: Brightness value (u8 pointer, U8Q0 format).
11359+ */
11360+static void
11361+preview_config_brightness(struct isp_prev_device *prev, const void *params)
11362+{
11363+ struct isp_device *isp = to_isp_device(prev);
11364+
11365+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
11366+ 0xff << ISPPRV_CNT_BRT_BRT_SHIFT,
11367+ *(u8 *)params << ISPPRV_CNT_BRT_BRT_SHIFT);
11368+}
11369+
11370+/*
11371+ * preview_config_yc_range - Configures the max and min Y and C values.
11372+ * @yclimit: Structure containing the range of Y and C values.
11373+ */
11374+static void
11375+preview_config_yc_range(struct isp_prev_device *prev, const void *yclimit)
11376+{
11377+ struct isp_device *isp = to_isp_device(prev);
11378+ const struct omap3isp_prev_yclimit *yc = yclimit;
11379+
11380+ isp_reg_writel(isp,
11381+ yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
11382+ yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
11383+ yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT |
11384+ yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT,
11385+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
11386+}
11387+
11388+/* preview parameters update structure */
11389+struct preview_update {
11390+ int cfg_bit;
11391+ int feature_bit;
11392+ void (*config)(struct isp_prev_device *, const void *);
11393+ void (*enable)(struct isp_prev_device *, u8);
11394+};
11395+
11396+static struct preview_update update_attrs[] = {
11397+ {OMAP3ISP_PREV_LUMAENH, PREV_LUMA_ENHANCE,
11398+ preview_config_luma_enhancement,
11399+ preview_enable_luma_enhancement},
11400+ {OMAP3ISP_PREV_INVALAW, PREV_INVERSE_ALAW,
11401+ NULL,
11402+ preview_enable_invalaw},
11403+ {OMAP3ISP_PREV_HRZ_MED, PREV_HORZ_MEDIAN_FILTER,
11404+ preview_config_hmed,
11405+ preview_enable_hmed},
11406+ {OMAP3ISP_PREV_CFA, PREV_CFA,
11407+ preview_config_cfa,
11408+ preview_enable_cfa},
11409+ {OMAP3ISP_PREV_CHROMA_SUPP, PREV_CHROMA_SUPPRESS,
11410+ preview_config_chroma_suppression,
11411+ preview_enable_chroma_suppression},
11412+ {OMAP3ISP_PREV_WB, PREV_WB,
11413+ preview_config_whitebalance,
11414+ NULL},
11415+ {OMAP3ISP_PREV_BLKADJ, PREV_BLKADJ,
11416+ preview_config_blkadj,
11417+ NULL},
11418+ {OMAP3ISP_PREV_RGB2RGB, PREV_RGB2RGB,
11419+ preview_config_rgb_blending,
11420+ NULL},
11421+ {OMAP3ISP_PREV_COLOR_CONV, PREV_COLOR_CONV,
11422+ preview_config_rgb_to_ycbcr,
11423+ NULL},
11424+ {OMAP3ISP_PREV_YC_LIMIT, PREV_YCLIMITS,
11425+ preview_config_yc_range,
11426+ NULL},
11427+ {OMAP3ISP_PREV_DEFECT_COR, PREV_DEFECT_COR,
11428+ preview_config_dcor,
11429+ preview_enable_dcor},
11430+ {OMAP3ISP_PREV_GAMMABYPASS, PREV_GAMMA_BYPASS,
11431+ NULL,
11432+ preview_enable_gammabypass},
11433+ {OMAP3ISP_PREV_DRK_FRM_CAPTURE, PREV_DARK_FRAME_CAPTURE,
11434+ NULL,
11435+ preview_enable_drkframe_capture},
11436+ {OMAP3ISP_PREV_DRK_FRM_SUBTRACT, PREV_DARK_FRAME_SUBTRACT,
11437+ NULL,
11438+ preview_enable_drkframe},
11439+ {OMAP3ISP_PREV_LENS_SHADING, PREV_LENS_SHADING,
11440+ preview_config_drkf_shadcomp,
11441+ preview_enable_drkframe},
11442+ {OMAP3ISP_PREV_NF, PREV_NOISE_FILTER,
11443+ preview_config_noisefilter,
11444+ preview_enable_noisefilter},
11445+ {OMAP3ISP_PREV_GAMMA, PREV_GAMMA,
11446+ preview_config_gammacorrn,
11447+ NULL},
11448+ {-1, PREV_CONTRAST,
11449+ preview_config_contrast,
11450+ NULL},
11451+ {-1, PREV_BRIGHTNESS,
11452+ preview_config_brightness,
11453+ NULL},
11454+};
11455+
11456+/*
11457+ * __preview_get_ptrs - helper function which return pointers to members
11458+ * of params and config structures.
11459+ * @params - pointer to preview_params structure.
11460+ * @param - return pointer to appropriate structure field.
11461+ * @configs - pointer to update config structure.
11462+ * @config - return pointer to appropriate structure field.
11463+ * @bit - for which feature to return pointers.
11464+ * Return size of coresponding prev_params member
11465+ */
11466+static u32
11467+__preview_get_ptrs(struct prev_params *params, void **param,
11468+ struct omap3isp_prev_update_config *configs,
11469+ void __user **config, u32 bit)
11470+{
11471+#define CHKARG(cfgs, cfg, field) \
11472+ if (cfgs && cfg) { \
11473+ *(cfg) = (cfgs)->field; \
11474+ }
11475+
11476+ switch (bit) {
11477+ case PREV_HORZ_MEDIAN_FILTER:
11478+ *param = &params->hmed;
11479+ CHKARG(configs, config, hmed)
11480+ return sizeof(params->hmed);
11481+ case PREV_NOISE_FILTER:
11482+ *param = &params->nf;
11483+ CHKARG(configs, config, nf)
11484+ return sizeof(params->nf);
11485+ break;
11486+ case PREV_CFA:
11487+ *param = &params->cfa;
11488+ CHKARG(configs, config, cfa)
11489+ return sizeof(params->cfa);
11490+ case PREV_LUMA_ENHANCE:
11491+ *param = &params->luma;
11492+ CHKARG(configs, config, luma)
11493+ return sizeof(params->luma);
11494+ case PREV_CHROMA_SUPPRESS:
11495+ *param = &params->csup;
11496+ CHKARG(configs, config, csup)
11497+ return sizeof(params->csup);
11498+ case PREV_DEFECT_COR:
11499+ *param = &params->dcor;
11500+ CHKARG(configs, config, dcor)
11501+ return sizeof(params->dcor);
11502+ case PREV_BLKADJ:
11503+ *param = &params->blk_adj;
11504+ CHKARG(configs, config, blkadj)
11505+ return sizeof(params->blk_adj);
11506+ case PREV_YCLIMITS:
11507+ *param = &params->yclimit;
11508+ CHKARG(configs, config, yclimit)
11509+ return sizeof(params->yclimit);
11510+ case PREV_RGB2RGB:
11511+ *param = &params->rgb2rgb;
11512+ CHKARG(configs, config, rgb2rgb)
11513+ return sizeof(params->rgb2rgb);
11514+ case PREV_COLOR_CONV:
11515+ *param = &params->rgb2ycbcr;
11516+ CHKARG(configs, config, csc)
11517+ return sizeof(params->rgb2ycbcr);
11518+ case PREV_WB:
11519+ *param = &params->wbal;
11520+ CHKARG(configs, config, wbal)
11521+ return sizeof(params->wbal);
11522+ case PREV_GAMMA:
11523+ *param = &params->gamma;
11524+ CHKARG(configs, config, gamma)
11525+ return sizeof(params->gamma);
11526+ case PREV_CONTRAST:
11527+ *param = &params->contrast;
11528+ return 0;
11529+ case PREV_BRIGHTNESS:
11530+ *param = &params->brightness;
11531+ return 0;
11532+ default:
11533+ *param = NULL;
11534+ *config = NULL;
11535+ break;
11536+ }
11537+ return 0;
11538+}
11539+
11540+/*
11541+ * preview_config - Copy and update local structure with userspace preview
11542+ * configuration.
11543+ * @prev: ISP preview engine
11544+ * @cfg: Configuration
11545+ *
11546+ * Return zero if success or -EFAULT if the configuration can't be copied from
11547+ * userspace.
11548+ */
11549+static int preview_config(struct isp_prev_device *prev,
11550+ struct omap3isp_prev_update_config *cfg)
11551+{
11552+ struct prev_params *params;
11553+ struct preview_update *attr;
11554+ int i, bit, rval = 0;
11555+
11556+ params = &prev->params;
11557+
11558+ if (prev->state != ISP_PIPELINE_STREAM_STOPPED) {
11559+ unsigned long flags;
11560+
11561+ spin_lock_irqsave(&prev->lock, flags);
11562+ prev->shadow_update = 1;
11563+ spin_unlock_irqrestore(&prev->lock, flags);
11564+ }
11565+
11566+ for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
11567+ attr = &update_attrs[i];
11568+ bit = 0;
11569+
11570+ if (!(cfg->update & attr->cfg_bit))
11571+ continue;
11572+
11573+ bit = cfg->flag & attr->cfg_bit;
11574+ if (bit) {
11575+ void *to = NULL, __user *from = NULL;
11576+ unsigned long sz = 0;
11577+
11578+ sz = __preview_get_ptrs(params, &to, cfg, &from,
11579+ bit);
11580+ if (to && from && sz) {
11581+ if (copy_from_user(to, from, sz)) {
11582+ rval = -EFAULT;
11583+ break;
11584+ }
11585+ }
11586+ params->features |= attr->feature_bit;
11587+ } else {
11588+ params->features &= ~attr->feature_bit;
11589+ }
11590+
11591+ prev->update |= attr->feature_bit;
11592+ }
11593+
11594+ prev->shadow_update = 0;
11595+ return rval;
11596+}
11597+
11598+/*
11599+ * preview_setup_hw - Setup preview registers and/or internal memory
11600+ * @prev: pointer to preview private structure
11601+ * Note: can be called from interrupt context
11602+ * Return none
11603+ */
11604+static void preview_setup_hw(struct isp_prev_device *prev)
11605+{
11606+ struct prev_params *params = &prev->params;
11607+ struct preview_update *attr;
11608+ int i, bit;
11609+ void *param_ptr;
11610+
11611+ for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
11612+ attr = &update_attrs[i];
11613+
11614+ if (!(prev->update & attr->feature_bit))
11615+ continue;
11616+ bit = params->features & attr->feature_bit;
11617+ if (bit) {
11618+ if (attr->config) {
11619+ __preview_get_ptrs(params, &param_ptr, NULL,
11620+ NULL, bit);
11621+ attr->config(prev, param_ptr);
11622+ }
11623+ if (attr->enable)
11624+ attr->enable(prev, 1);
11625+ } else
11626+ if (attr->enable)
11627+ attr->enable(prev, 0);
11628+
11629+ prev->update &= ~attr->feature_bit;
11630+ }
11631+}
11632+
11633+/*
11634+ * preview_config_ycpos - Configure byte layout of YUV image.
11635+ * @mode: Indicates the required byte layout.
11636+ */
11637+static void
11638+preview_config_ycpos(struct isp_prev_device *prev,
11639+ enum v4l2_mbus_pixelcode pixelcode)
11640+{
11641+ struct isp_device *isp = to_isp_device(prev);
11642+ enum preview_ycpos_mode mode;
11643+
11644+ switch (pixelcode) {
11645+ case V4L2_MBUS_FMT_YUYV8_1X16:
11646+ mode = YCPOS_CrYCbY;
11647+ break;
11648+ case V4L2_MBUS_FMT_UYVY8_1X16:
11649+ mode = YCPOS_YCrYCb;
11650+ break;
11651+ default:
11652+ return;
11653+ }
11654+
11655+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
11656+ ISPPRV_PCR_YCPOS_CrYCbY,
11657+ mode << ISPPRV_PCR_YCPOS_SHIFT);
11658+}
11659+
11660+/*
11661+ * preview_config_averager - Enable / disable / configure averager
11662+ * @average: Average value to be configured.
11663+ */
11664+static void preview_config_averager(struct isp_prev_device *prev, u8 average)
11665+{
11666+ struct isp_device *isp = to_isp_device(prev);
11667+ int reg = 0;
11668+
11669+ if (prev->params.cfa.format == OMAP3ISP_CFAFMT_BAYER)
11670+ reg = ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
11671+ ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
11672+ average;
11673+ else if (prev->params.cfa.format == OMAP3ISP_CFAFMT_RGBFOVEON)
11674+ reg = ISPPRV_AVE_EVENDIST_3 << ISPPRV_AVE_EVENDIST_SHIFT |
11675+ ISPPRV_AVE_ODDDIST_3 << ISPPRV_AVE_ODDDIST_SHIFT |
11676+ average;
11677+ isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
11678+}
11679+
11680+/*
11681+ * preview_config_input_size - Configure the input frame size
11682+ *
11683+ * The preview engine crops several rows and columns internally depending on
11684+ * which processing blocks are enabled. The driver assumes all those blocks are
11685+ * enabled when reporting source pad formats to userspace. If this assumption is
11686+ * not true, rows and columns must be manually cropped at the preview engine
11687+ * input to avoid overflows at the end of lines and frames.
11688+ */
11689+static void preview_config_input_size(struct isp_prev_device *prev)
11690+{
11691+ struct isp_device *isp = to_isp_device(prev);
11692+ struct prev_params *params = &prev->params;
11693+ struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK];
11694+ unsigned int sph = 0;
11695+ unsigned int eph = format->width - 1;
11696+ unsigned int slv = 0;
11697+ unsigned int elv = format->height - 1;
11698+
11699+ if (prev->input == PREVIEW_INPUT_CCDC) {
11700+ sph += 2;
11701+ eph -= 2;
11702+ }
11703+
11704+ /*
11705+ * Median filter 4 pixels
11706+ * Noise filter 4 pixels, 4 lines
11707+ * or faulty pixels correction
11708+ * CFA filter 4 pixels, 4 lines in Bayer mode
11709+ * 2 lines in other modes
11710+ * Color suppression 2 pixels
11711+ * or luma enhancement
11712+ * -------------------------------------------------------------
11713+ * Maximum total 14 pixels, 8 lines
11714+ */
11715+
11716+ if (!(params->features & PREV_CFA)) {
11717+ sph += 2;
11718+ eph -= 2;
11719+ slv += 2;
11720+ elv -= 2;
11721+ }
11722+ if (!(params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER))) {
11723+ sph += 2;
11724+ eph -= 2;
11725+ slv += 2;
11726+ elv -= 2;
11727+ }
11728+ if (!(params->features & PREV_HORZ_MEDIAN_FILTER)) {
11729+ sph += 2;
11730+ eph -= 2;
11731+ }
11732+ if (!(params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE)))
11733+ sph += 2;
11734+
11735+ isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
11736+ OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
11737+ isp_reg_writel(isp, (slv << ISPPRV_VERT_INFO_SLV_SHIFT) | elv,
11738+ OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
11739+}
11740+
11741+/*
11742+ * preview_config_inlineoffset - Configures the Read address line offset.
11743+ * @prev: Preview module
11744+ * @offset: Line offset
11745+ *
11746+ * According to the TRM, the line offset must be aligned on a 32 bytes boundary.
11747+ * However, a hardware bug requires the memory start address to be aligned on a
11748+ * 64 bytes boundary, so the offset probably should be aligned on 64 bytes as
11749+ * well.
11750+ */
11751+static void
11752+preview_config_inlineoffset(struct isp_prev_device *prev, u32 offset)
11753+{
11754+ struct isp_device *isp = to_isp_device(prev);
11755+
11756+ isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
11757+ ISPPRV_RADR_OFFSET);
11758+}
11759+
11760+/*
11761+ * preview_set_inaddr - Sets memory address of input frame.
11762+ * @addr: 32bit memory address aligned on 32byte boundary.
11763+ *
11764+ * Configures the memory address from which the input frame is to be read.
11765+ */
11766+static void preview_set_inaddr(struct isp_prev_device *prev, u32 addr)
11767+{
11768+ struct isp_device *isp = to_isp_device(prev);
11769+
11770+ isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
11771+}
11772+
11773+/*
11774+ * preview_config_outlineoffset - Configures the Write address line offset.
11775+ * @offset: Line Offset for the preview output.
11776+ *
11777+ * The offset must be a multiple of 32 bytes.
11778+ */
11779+static void preview_config_outlineoffset(struct isp_prev_device *prev,
11780+ u32 offset)
11781+{
11782+ struct isp_device *isp = to_isp_device(prev);
11783+
11784+ isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
11785+ ISPPRV_WADD_OFFSET);
11786+}
11787+
11788+/*
11789+ * preview_set_outaddr - Sets the memory address to store output frame
11790+ * @addr: 32bit memory address aligned on 32byte boundary.
11791+ *
11792+ * Configures the memory address to which the output frame is written.
11793+ */
11794+static void preview_set_outaddr(struct isp_prev_device *prev, u32 addr)
11795+{
11796+ struct isp_device *isp = to_isp_device(prev);
11797+
11798+ isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR);
11799+}
11800+
11801+static void preview_adjust_bandwidth(struct isp_prev_device *prev)
11802+{
11803+ struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
11804+ struct isp_device *isp = to_isp_device(prev);
11805+ const struct v4l2_mbus_framefmt *ifmt = &prev->formats[PREV_PAD_SINK];
11806+ unsigned long l3_ick = pipe->l3_ick;
11807+ struct v4l2_fract *timeperframe;
11808+ unsigned int cycles_per_frame;
11809+ unsigned int requests_per_frame;
11810+ unsigned int cycles_per_request;
11811+ unsigned int minimum;
11812+ unsigned int maximum;
11813+ unsigned int value;
11814+
11815+ if (prev->input != PREVIEW_INPUT_MEMORY) {
11816+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
11817+ ISPSBL_SDR_REQ_PRV_EXP_MASK);
11818+ return;
11819+ }
11820+
11821+ /* Compute the minimum number of cycles per request, based on the
11822+ * pipeline maximum data rate. This is an absolute lower bound if we
11823+ * don't want SBL overflows, so round the value up.
11824+ */
11825+ cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1,
11826+ pipe->max_rate);
11827+ minimum = DIV_ROUND_UP(cycles_per_request, 32);
11828+
11829+ /* Compute the maximum number of cycles per request, based on the
11830+ * requested frame rate. This is a soft upper bound to achieve a frame
11831+ * rate equal or higher than the requested value, so round the value
11832+ * down.
11833+ */
11834+ timeperframe = &pipe->max_timeperframe;
11835+
11836+ requests_per_frame = DIV_ROUND_UP(ifmt->width * 2, 256) * ifmt->height;
11837+ cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator,
11838+ timeperframe->denominator);
11839+ cycles_per_request = cycles_per_frame / requests_per_frame;
11840+
11841+ maximum = cycles_per_request / 32;
11842+
11843+ value = max(minimum, maximum);
11844+
11845+ dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value);
11846+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
11847+ ISPSBL_SDR_REQ_PRV_EXP_MASK,
11848+ value << ISPSBL_SDR_REQ_PRV_EXP_SHIFT);
11849+}
11850+
11851+/*
11852+ * omap3isp_preview_busy - Gets busy state of preview module.
11853+ */
11854+int omap3isp_preview_busy(struct isp_prev_device *prev)
11855+{
11856+ struct isp_device *isp = to_isp_device(prev);
11857+
11858+ return isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR)
11859+ & ISPPRV_PCR_BUSY;
11860+}
11861+
11862+/*
11863+ * omap3isp_preview_restore_context - Restores the values of preview registers
11864+ */
11865+void omap3isp_preview_restore_context(struct isp_device *isp)
11866+{
11867+ isp->isp_prev.update = PREV_FEATURES_END - 1;
11868+ preview_setup_hw(&isp->isp_prev);
11869+}
11870+
11871+/*
11872+ * preview_print_status - Dump preview module registers to the kernel log
11873+ */
11874+#define PREV_PRINT_REGISTER(isp, name)\
11875+ dev_dbg(isp->dev, "###PRV " #name "=0x%08x\n", \
11876+ isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_##name))
11877+
11878+static void preview_print_status(struct isp_prev_device *prev)
11879+{
11880+ struct isp_device *isp = to_isp_device(prev);
11881+
11882+ dev_dbg(isp->dev, "-------------Preview Register dump----------\n");
11883+
11884+ PREV_PRINT_REGISTER(isp, PCR);
11885+ PREV_PRINT_REGISTER(isp, HORZ_INFO);
11886+ PREV_PRINT_REGISTER(isp, VERT_INFO);
11887+ PREV_PRINT_REGISTER(isp, RSDR_ADDR);
11888+ PREV_PRINT_REGISTER(isp, RADR_OFFSET);
11889+ PREV_PRINT_REGISTER(isp, DSDR_ADDR);
11890+ PREV_PRINT_REGISTER(isp, DRKF_OFFSET);
11891+ PREV_PRINT_REGISTER(isp, WSDR_ADDR);
11892+ PREV_PRINT_REGISTER(isp, WADD_OFFSET);
11893+ PREV_PRINT_REGISTER(isp, AVE);
11894+ PREV_PRINT_REGISTER(isp, HMED);
11895+ PREV_PRINT_REGISTER(isp, NF);
11896+ PREV_PRINT_REGISTER(isp, WB_DGAIN);
11897+ PREV_PRINT_REGISTER(isp, WBGAIN);
11898+ PREV_PRINT_REGISTER(isp, WBSEL);
11899+ PREV_PRINT_REGISTER(isp, CFA);
11900+ PREV_PRINT_REGISTER(isp, BLKADJOFF);
11901+ PREV_PRINT_REGISTER(isp, RGB_MAT1);
11902+ PREV_PRINT_REGISTER(isp, RGB_MAT2);
11903+ PREV_PRINT_REGISTER(isp, RGB_MAT3);
11904+ PREV_PRINT_REGISTER(isp, RGB_MAT4);
11905+ PREV_PRINT_REGISTER(isp, RGB_MAT5);
11906+ PREV_PRINT_REGISTER(isp, RGB_OFF1);
11907+ PREV_PRINT_REGISTER(isp, RGB_OFF2);
11908+ PREV_PRINT_REGISTER(isp, CSC0);
11909+ PREV_PRINT_REGISTER(isp, CSC1);
11910+ PREV_PRINT_REGISTER(isp, CSC2);
11911+ PREV_PRINT_REGISTER(isp, CSC_OFFSET);
11912+ PREV_PRINT_REGISTER(isp, CNT_BRT);
11913+ PREV_PRINT_REGISTER(isp, CSUP);
11914+ PREV_PRINT_REGISTER(isp, SETUP_YC);
11915+ PREV_PRINT_REGISTER(isp, SET_TBL_ADDR);
11916+ PREV_PRINT_REGISTER(isp, CDC_THR0);
11917+ PREV_PRINT_REGISTER(isp, CDC_THR1);
11918+ PREV_PRINT_REGISTER(isp, CDC_THR2);
11919+ PREV_PRINT_REGISTER(isp, CDC_THR3);
11920+
11921+ dev_dbg(isp->dev, "--------------------------------------------\n");
11922+}
11923+
11924+/*
11925+ * preview_init_params - init image processing parameters.
11926+ * @prev: pointer to previewer private structure
11927+ * return none
11928+ */
11929+static void preview_init_params(struct isp_prev_device *prev)
11930+{
11931+ struct prev_params *params = &prev->params;
11932+ int i = 0;
11933+
11934+ /* Init values */
11935+ params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS;
11936+ params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS;
11937+ params->average = NO_AVE;
11938+ params->cfa.format = OMAP3ISP_CFAFMT_BAYER;
11939+ memcpy(params->cfa.table, cfa_coef_table,
11940+ sizeof(params->cfa.table));
11941+ params->cfa.gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
11942+ params->cfa.gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
11943+ params->csup.gain = FLR_CSUP_GAIN;
11944+ params->csup.thres = FLR_CSUP_THRES;
11945+ params->csup.hypf_en = 0;
11946+ memcpy(params->luma.table, luma_enhance_table,
11947+ sizeof(params->luma.table));
11948+ params->nf.spread = FLR_NF_STRGTH;
11949+ memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
11950+ params->dcor.couplet_mode_en = 1;
11951+ for (i = 0; i < OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS; i++)
11952+ params->dcor.detect_correct[i] = DEF_DETECT_CORRECT_VAL;
11953+ memcpy(params->gamma.blue, gamma_table, sizeof(params->gamma.blue));
11954+ memcpy(params->gamma.green, gamma_table, sizeof(params->gamma.green));
11955+ memcpy(params->gamma.red, gamma_table, sizeof(params->gamma.red));
11956+ params->wbal.dgain = FLR_WBAL_DGAIN;
11957+ params->wbal.coef0 = FLR_WBAL_COEF;
11958+ params->wbal.coef1 = FLR_WBAL_COEF;
11959+ params->wbal.coef2 = FLR_WBAL_COEF;
11960+ params->wbal.coef3 = FLR_WBAL_COEF;
11961+ params->blk_adj.red = FLR_BLKADJ_RED;
11962+ params->blk_adj.green = FLR_BLKADJ_GREEN;
11963+ params->blk_adj.blue = FLR_BLKADJ_BLUE;
11964+ params->rgb2rgb = flr_rgb2rgb;
11965+ params->rgb2ycbcr = flr_prev_csc;
11966+ params->yclimit.minC = ISPPRV_YC_MIN;
11967+ params->yclimit.maxC = ISPPRV_YC_MAX;
11968+ params->yclimit.minY = ISPPRV_YC_MIN;
11969+ params->yclimit.maxY = ISPPRV_YC_MAX;
11970+
11971+ params->features = PREV_CFA | PREV_DEFECT_COR | PREV_NOISE_FILTER
11972+ | PREV_GAMMA | PREV_BLKADJ | PREV_YCLIMITS
11973+ | PREV_RGB2RGB | PREV_COLOR_CONV | PREV_WB
11974+ | PREV_BRIGHTNESS | PREV_CONTRAST;
11975+
11976+ prev->update = PREV_FEATURES_END - 1;
11977+}
11978+
11979+/*
11980+ * preview_max_out_width - Handle previewer hardware ouput limitations
11981+ * @isp_revision : ISP revision
11982+ * returns maximum width output for current isp revision
11983+ */
11984+static unsigned int preview_max_out_width(struct isp_prev_device *prev)
11985+{
11986+ struct isp_device *isp = to_isp_device(prev);
11987+
11988+ switch (isp->revision) {
11989+ case ISP_REVISION_1_0:
11990+ return ISPPRV_MAXOUTPUT_WIDTH;
11991+
11992+ case ISP_REVISION_2_0:
11993+ default:
11994+ return ISPPRV_MAXOUTPUT_WIDTH_ES2;
11995+
11996+ case ISP_REVISION_15_0:
11997+ return ISPPRV_MAXOUTPUT_WIDTH_3630;
11998+ }
11999+}
12000+
12001+static void preview_configure(struct isp_prev_device *prev)
12002+{
12003+ struct isp_device *isp = to_isp_device(prev);
12004+ struct v4l2_mbus_framefmt *format;
12005+ unsigned int max_out_width;
12006+ unsigned int format_avg;
12007+
12008+ preview_setup_hw(prev);
12009+
12010+ if (prev->output & PREVIEW_OUTPUT_MEMORY)
12011+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
12012+ ISPPRV_PCR_SDRPORT);
12013+ else
12014+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
12015+ ISPPRV_PCR_SDRPORT);
12016+
12017+ if (prev->output & PREVIEW_OUTPUT_RESIZER)
12018+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
12019+ ISPPRV_PCR_RSZPORT);
12020+ else
12021+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
12022+ ISPPRV_PCR_RSZPORT);
12023+
12024+ /* PREV_PAD_SINK */
12025+ format = &prev->formats[PREV_PAD_SINK];
12026+
12027+ preview_adjust_bandwidth(prev);
12028+
12029+ preview_config_input_size(prev);
12030+
12031+ if (prev->input == PREVIEW_INPUT_CCDC)
12032+ preview_config_inlineoffset(prev, 0);
12033+ else
12034+ preview_config_inlineoffset(prev,
12035+ ALIGN(format->width, 0x20) * 2);
12036+
12037+ /* PREV_PAD_SOURCE */
12038+ format = &prev->formats[PREV_PAD_SOURCE];
12039+
12040+ if (prev->output & PREVIEW_OUTPUT_MEMORY)
12041+ preview_config_outlineoffset(prev,
12042+ ALIGN(format->width, 0x10) * 2);
12043+
12044+ max_out_width = preview_max_out_width(prev);
12045+
12046+ format_avg = fls(DIV_ROUND_UP(format->width, max_out_width) - 1);
12047+ preview_config_averager(prev, format_avg);
12048+ preview_config_ycpos(prev, format->code);
12049+}
12050+
12051+/* -----------------------------------------------------------------------------
12052+ * Interrupt handling
12053+ */
12054+
12055+static void preview_enable_oneshot(struct isp_prev_device *prev)
12056+{
12057+ struct isp_device *isp = to_isp_device(prev);
12058+
12059+ /* The PCR.SOURCE bit is automatically reset to 0 when the PCR.ENABLE
12060+ * bit is set. As the preview engine is used in single-shot mode, we
12061+ * need to set PCR.SOURCE before enabling the preview engine.
12062+ */
12063+ if (prev->input == PREVIEW_INPUT_MEMORY)
12064+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
12065+ ISPPRV_PCR_SOURCE);
12066+
12067+ isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
12068+ ISPPRV_PCR_EN | ISPPRV_PCR_ONESHOT);
12069+}
12070+
12071+void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev)
12072+{
12073+ /*
12074+ * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun
12075+ * condition, the module was paused and now we have a buffer queued
12076+ * on the output again. Restart the pipeline if running in continuous
12077+ * mode.
12078+ */
12079+ if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
12080+ prev->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
12081+ preview_enable_oneshot(prev);
12082+ isp_video_dmaqueue_flags_clr(&prev->video_out);
12083+ }
12084+}
12085+
12086+static void preview_isr_buffer(struct isp_prev_device *prev)
12087+{
12088+ struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
12089+ struct isp_buffer *buffer;
12090+ int restart = 0;
12091+
12092+ if (prev->input == PREVIEW_INPUT_MEMORY) {
12093+ buffer = omap3isp_video_buffer_next(&prev->video_in,
12094+ prev->error);
12095+ if (buffer != NULL)
12096+ preview_set_inaddr(prev, buffer->isp_addr);
12097+ pipe->state |= ISP_PIPELINE_IDLE_INPUT;
12098+ }
12099+
12100+ if (prev->output & PREVIEW_OUTPUT_MEMORY) {
12101+ buffer = omap3isp_video_buffer_next(&prev->video_out,
12102+ prev->error);
12103+ if (buffer != NULL) {
12104+ preview_set_outaddr(prev, buffer->isp_addr);
12105+ restart = 1;
12106+ }
12107+ pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
12108+ }
12109+
12110+ switch (prev->state) {
12111+ case ISP_PIPELINE_STREAM_SINGLESHOT:
12112+ if (isp_pipeline_ready(pipe))
12113+ omap3isp_pipeline_set_stream(pipe,
12114+ ISP_PIPELINE_STREAM_SINGLESHOT);
12115+ break;
12116+
12117+ case ISP_PIPELINE_STREAM_CONTINUOUS:
12118+ /* If an underrun occurs, the video queue operation handler will
12119+ * restart the preview engine. Otherwise restart it immediately.
12120+ */
12121+ if (restart)
12122+ preview_enable_oneshot(prev);
12123+ break;
12124+
12125+ case ISP_PIPELINE_STREAM_STOPPED:
12126+ default:
12127+ return;
12128+ }
12129+
12130+ prev->error = 0;
12131+}
12132+
12133+/*
12134+ * omap3isp_preview_isr - ISP preview engine interrupt handler
12135+ *
12136+ * Manage the preview engine video buffers and configure shadowed registers.
12137+ */
12138+void omap3isp_preview_isr(struct isp_prev_device *prev)
12139+{
12140+ unsigned long flags;
12141+
12142+ if (omap3isp_module_sync_is_stopping(&prev->wait, &prev->stopping))
12143+ return;
12144+
12145+ spin_lock_irqsave(&prev->lock, flags);
12146+ if (prev->shadow_update)
12147+ goto done;
12148+
12149+ preview_setup_hw(prev);
12150+ preview_config_input_size(prev);
12151+
12152+done:
12153+ spin_unlock_irqrestore(&prev->lock, flags);
12154+
12155+ if (prev->input == PREVIEW_INPUT_MEMORY ||
12156+ prev->output & PREVIEW_OUTPUT_MEMORY)
12157+ preview_isr_buffer(prev);
12158+ else if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS)
12159+ preview_enable_oneshot(prev);
12160+}
12161+
12162+/* -----------------------------------------------------------------------------
12163+ * ISP video operations
12164+ */
12165+
12166+static int preview_video_queue(struct isp_video *video,
12167+ struct isp_buffer *buffer)
12168+{
12169+ struct isp_prev_device *prev = &video->isp->isp_prev;
12170+
12171+ if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
12172+ preview_set_inaddr(prev, buffer->isp_addr);
12173+
12174+ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
12175+ preview_set_outaddr(prev, buffer->isp_addr);
12176+
12177+ return 0;
12178+}
12179+
12180+static const struct isp_video_operations preview_video_ops = {
12181+ .queue = preview_video_queue,
12182+};
12183+
12184+/* -----------------------------------------------------------------------------
12185+ * V4L2 subdev operations
12186+ */
12187+
12188+/*
12189+ * preview_s_ctrl - Handle set control subdev method
12190+ * @ctrl: pointer to v4l2 control structure
12191+ */
12192+static int preview_s_ctrl(struct v4l2_ctrl *ctrl)
12193+{
12194+ struct isp_prev_device *prev =
12195+ container_of(ctrl->handler, struct isp_prev_device, ctrls);
12196+
12197+ switch (ctrl->id) {
12198+ case V4L2_CID_BRIGHTNESS:
12199+ preview_update_brightness(prev, ctrl->val);
12200+ break;
12201+ case V4L2_CID_CONTRAST:
12202+ preview_update_contrast(prev, ctrl->val);
12203+ break;
12204+ }
12205+
12206+ return 0;
12207+}
12208+
12209+static const struct v4l2_ctrl_ops preview_ctrl_ops = {
12210+ .s_ctrl = preview_s_ctrl,
12211+};
12212+
12213+/*
12214+ * preview_ioctl - Handle preview module private ioctl's
12215+ * @prev: pointer to preview context structure
12216+ * @cmd: configuration command
12217+ * @arg: configuration argument
12218+ * return -EINVAL or zero on success
12219+ */
12220+static long preview_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
12221+{
12222+ struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
12223+
12224+ switch (cmd) {
12225+ case VIDIOC_OMAP3ISP_PRV_CFG:
12226+ return preview_config(prev, arg);
12227+
12228+ default:
12229+ return -ENOIOCTLCMD;
12230+ }
12231+}
12232+
12233+/*
12234+ * preview_set_stream - Enable/Disable streaming on preview subdev
12235+ * @sd : pointer to v4l2 subdev structure
12236+ * @enable: 1 == Enable, 0 == Disable
12237+ * return -EINVAL or zero on sucess
12238+ */
12239+static int preview_set_stream(struct v4l2_subdev *sd, int enable)
12240+{
12241+ struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
12242+ struct isp_video *video_out = &prev->video_out;
12243+ struct isp_device *isp = to_isp_device(prev);
12244+ struct device *dev = to_device(prev);
12245+ unsigned long flags;
12246+
12247+ if (prev->state == ISP_PIPELINE_STREAM_STOPPED) {
12248+ if (enable == ISP_PIPELINE_STREAM_STOPPED)
12249+ return 0;
12250+
12251+ omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
12252+ preview_configure(prev);
12253+ atomic_set(&prev->stopping, 0);
12254+ prev->error = 0;
12255+ preview_print_status(prev);
12256+ }
12257+
12258+ switch (enable) {
12259+ case ISP_PIPELINE_STREAM_CONTINUOUS:
12260+ if (prev->output & PREVIEW_OUTPUT_MEMORY)
12261+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
12262+
12263+ if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED ||
12264+ !(prev->output & PREVIEW_OUTPUT_MEMORY))
12265+ preview_enable_oneshot(prev);
12266+
12267+ isp_video_dmaqueue_flags_clr(video_out);
12268+ break;
12269+
12270+ case ISP_PIPELINE_STREAM_SINGLESHOT:
12271+ if (prev->input == PREVIEW_INPUT_MEMORY)
12272+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
12273+ if (prev->output & PREVIEW_OUTPUT_MEMORY)
12274+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
12275+
12276+ preview_enable_oneshot(prev);
12277+ break;
12278+
12279+ case ISP_PIPELINE_STREAM_STOPPED:
12280+ if (omap3isp_module_sync_idle(&sd->entity, &prev->wait,
12281+ &prev->stopping))
12282+ dev_dbg(dev, "%s: stop timeout.\n", sd->name);
12283+ spin_lock_irqsave(&prev->lock, flags);
12284+ omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
12285+ omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
12286+ omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
12287+ spin_unlock_irqrestore(&prev->lock, flags);
12288+ isp_video_dmaqueue_flags_clr(video_out);
12289+ break;
12290+ }
12291+
12292+ prev->state = enable;
12293+ return 0;
12294+}
12295+
12296+static struct v4l2_mbus_framefmt *
12297+__preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
12298+ unsigned int pad, enum v4l2_subdev_format_whence which)
12299+{
12300+ if (which == V4L2_SUBDEV_FORMAT_TRY)
12301+ return v4l2_subdev_get_try_format(fh, pad);
12302+ else
12303+ return &prev->formats[pad];
12304+}
12305+
12306+/* previewer format descriptions */
12307+static const unsigned int preview_input_fmts[] = {
12308+ V4L2_MBUS_FMT_SGRBG10_1X10,
12309+ V4L2_MBUS_FMT_SRGGB10_1X10,
12310+ V4L2_MBUS_FMT_SBGGR10_1X10,
12311+ V4L2_MBUS_FMT_SGBRG10_1X10,
12312+};
12313+
12314+static const unsigned int preview_output_fmts[] = {
12315+ V4L2_MBUS_FMT_UYVY8_1X16,
12316+ V4L2_MBUS_FMT_YUYV8_1X16,
12317+};
12318+
12319+/*
12320+ * preview_try_format - Handle try format by pad subdev method
12321+ * @prev: ISP preview device
12322+ * @fh : V4L2 subdev file handle
12323+ * @pad: pad num
12324+ * @fmt: pointer to v4l2 format structure
12325+ */
12326+static void preview_try_format(struct isp_prev_device *prev,
12327+ struct v4l2_subdev_fh *fh, unsigned int pad,
12328+ struct v4l2_mbus_framefmt *fmt,
12329+ enum v4l2_subdev_format_whence which)
12330+{
12331+ struct v4l2_mbus_framefmt *format;
12332+ unsigned int max_out_width;
12333+ enum v4l2_mbus_pixelcode pixelcode;
12334+ unsigned int i;
12335+
12336+ max_out_width = preview_max_out_width(prev);
12337+
12338+ switch (pad) {
12339+ case PREV_PAD_SINK:
12340+ /* When reading data from the CCDC, the input size has already
12341+ * been mangled by the CCDC output pad so it can be accepted
12342+ * as-is.
12343+ *
12344+ * When reading data from memory, clamp the requested width and
12345+ * height. The TRM doesn't specify a minimum input height, make
12346+ * sure we got enough lines to enable the noise filter and color
12347+ * filter array interpolation.
12348+ */
12349+ if (prev->input == PREVIEW_INPUT_MEMORY) {
12350+ fmt->width = clamp_t(u32, fmt->width, PREV_MIN_WIDTH,
12351+ max_out_width * 8);
12352+ fmt->height = clamp_t(u32, fmt->height, PREV_MIN_HEIGHT,
12353+ PREV_MAX_HEIGHT);
12354+ }
12355+
12356+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
12357+
12358+ for (i = 0; i < ARRAY_SIZE(preview_input_fmts); i++) {
12359+ if (fmt->code == preview_input_fmts[i])
12360+ break;
12361+ }
12362+
12363+ /* If not found, use SGRBG10 as default */
12364+ if (i >= ARRAY_SIZE(preview_input_fmts))
12365+ fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
12366+ break;
12367+
12368+ case PREV_PAD_SOURCE:
12369+ pixelcode = fmt->code;
12370+ format = __preview_get_format(prev, fh, PREV_PAD_SINK, which);
12371+ memcpy(fmt, format, sizeof(*fmt));
12372+
12373+ /* The preview module output size is configurable through the
12374+ * input interface (horizontal and vertical cropping) and the
12375+ * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). In
12376+ * spite of this, hardcode the output size to the biggest
12377+ * possible value for simplicity reasons.
12378+ */
12379+ switch (pixelcode) {
12380+ case V4L2_MBUS_FMT_YUYV8_1X16:
12381+ case V4L2_MBUS_FMT_UYVY8_1X16:
12382+ fmt->code = pixelcode;
12383+ break;
12384+
12385+ default:
12386+ fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
12387+ break;
12388+ }
12389+
12390+ /* The TRM states (12.1.4.7.1.2) that 2 pixels must be cropped
12391+ * from the left and right sides when the input source is the
12392+ * CCDC. This seems not to be needed in practice, investigation
12393+ * is required.
12394+ */
12395+ if (prev->input == PREVIEW_INPUT_CCDC)
12396+ fmt->width -= 4;
12397+
12398+ /* The preview module can output a maximum of 3312 pixels
12399+ * horizontally due to fixed memory-line sizes. Compute the
12400+ * horizontal averaging factor accordingly. Note that the limit
12401+ * applies to the noise filter and CFA interpolation blocks, so
12402+ * it doesn't take cropping by further blocks into account.
12403+ *
12404+ * ES 1.0 hardware revision is limited to 1280 pixels
12405+ * horizontally.
12406+ */
12407+ fmt->width >>= fls(DIV_ROUND_UP(fmt->width, max_out_width) - 1);
12408+
12409+ /* Assume that all blocks are enabled and crop pixels and lines
12410+ * accordingly. See preview_config_input_size() for more
12411+ * information.
12412+ */
12413+ fmt->width -= 14;
12414+ fmt->height -= 8;
12415+
12416+ fmt->colorspace = V4L2_COLORSPACE_JPEG;
12417+ break;
12418+ }
12419+
12420+ fmt->field = V4L2_FIELD_NONE;
12421+}
12422+
12423+/*
12424+ * preview_enum_mbus_code - Handle pixel format enumeration
12425+ * @sd : pointer to v4l2 subdev structure
12426+ * @fh : V4L2 subdev file handle
12427+ * @code : pointer to v4l2_subdev_mbus_code_enum structure
12428+ * return -EINVAL or zero on success
12429+ */
12430+static int preview_enum_mbus_code(struct v4l2_subdev *sd,
12431+ struct v4l2_subdev_fh *fh,
12432+ struct v4l2_subdev_mbus_code_enum *code)
12433+{
12434+ switch (code->pad) {
12435+ case PREV_PAD_SINK:
12436+ if (code->index >= ARRAY_SIZE(preview_input_fmts))
12437+ return -EINVAL;
12438+
12439+ code->code = preview_input_fmts[code->index];
12440+ break;
12441+ case PREV_PAD_SOURCE:
12442+ if (code->index >= ARRAY_SIZE(preview_output_fmts))
12443+ return -EINVAL;
12444+
12445+ code->code = preview_output_fmts[code->index];
12446+ break;
12447+ default:
12448+ return -EINVAL;
12449+ }
12450+
12451+ return 0;
12452+}
12453+
12454+static int preview_enum_frame_size(struct v4l2_subdev *sd,
12455+ struct v4l2_subdev_fh *fh,
12456+ struct v4l2_subdev_frame_size_enum *fse)
12457+{
12458+ struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
12459+ struct v4l2_mbus_framefmt format;
12460+
12461+ if (fse->index != 0)
12462+ return -EINVAL;
12463+
12464+ format.code = fse->code;
12465+ format.width = 1;
12466+ format.height = 1;
12467+ preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
12468+ fse->min_width = format.width;
12469+ fse->min_height = format.height;
12470+
12471+ if (format.code != fse->code)
12472+ return -EINVAL;
12473+
12474+ format.code = fse->code;
12475+ format.width = -1;
12476+ format.height = -1;
12477+ preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
12478+ fse->max_width = format.width;
12479+ fse->max_height = format.height;
12480+
12481+ return 0;
12482+}
12483+
12484+/*
12485+ * preview_get_format - Handle get format by pads subdev method
12486+ * @sd : pointer to v4l2 subdev structure
12487+ * @fh : V4L2 subdev file handle
12488+ * @fmt: pointer to v4l2 subdev format structure
12489+ * return -EINVAL or zero on sucess
12490+ */
12491+static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
12492+ struct v4l2_subdev_format *fmt)
12493+{
12494+ struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
12495+ struct v4l2_mbus_framefmt *format;
12496+
12497+ format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
12498+ if (format == NULL)
12499+ return -EINVAL;
12500+
12501+ fmt->format = *format;
12502+ return 0;
12503+}
12504+
12505+/*
12506+ * preview_set_format - Handle set format by pads subdev method
12507+ * @sd : pointer to v4l2 subdev structure
12508+ * @fh : V4L2 subdev file handle
12509+ * @fmt: pointer to v4l2 subdev format structure
12510+ * return -EINVAL or zero on success
12511+ */
12512+static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
12513+ struct v4l2_subdev_format *fmt)
12514+{
12515+ struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
12516+ struct v4l2_mbus_framefmt *format;
12517+
12518+ format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
12519+ if (format == NULL)
12520+ return -EINVAL;
12521+
12522+ preview_try_format(prev, fh, fmt->pad, &fmt->format, fmt->which);
12523+ *format = fmt->format;
12524+
12525+ /* Propagate the format from sink to source */
12526+ if (fmt->pad == PREV_PAD_SINK) {
12527+ format = __preview_get_format(prev, fh, PREV_PAD_SOURCE,
12528+ fmt->which);
12529+ *format = fmt->format;
12530+ preview_try_format(prev, fh, PREV_PAD_SOURCE, format,
12531+ fmt->which);
12532+ }
12533+
12534+ return 0;
12535+}
12536+
12537+/*
12538+ * preview_init_formats - Initialize formats on all pads
12539+ * @sd: ISP preview V4L2 subdevice
12540+ * @fh: V4L2 subdev file handle
12541+ *
12542+ * Initialize all pad formats with default values. If fh is not NULL, try
12543+ * formats are initialized on the file handle. Otherwise active formats are
12544+ * initialized on the device.
12545+ */
12546+static int preview_init_formats(struct v4l2_subdev *sd,
12547+ struct v4l2_subdev_fh *fh)
12548+{
12549+ struct v4l2_subdev_format format;
12550+
12551+ memset(&format, 0, sizeof(format));
12552+ format.pad = PREV_PAD_SINK;
12553+ format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
12554+ format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
12555+ format.format.width = 4096;
12556+ format.format.height = 4096;
12557+ preview_set_format(sd, fh, &format);
12558+
12559+ return 0;
12560+}
12561+
12562+/* subdev core operations */
12563+static const struct v4l2_subdev_core_ops preview_v4l2_core_ops = {
12564+ .queryctrl = v4l2_subdev_queryctrl,
12565+ .querymenu = v4l2_subdev_querymenu,
12566+ .g_ctrl = v4l2_subdev_g_ctrl,
12567+ .s_ctrl = v4l2_subdev_s_ctrl,
12568+ .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
12569+ .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
12570+ .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
12571+ .ioctl = preview_ioctl,
12572+};
12573+
12574+/* subdev file operations */
12575+static const struct v4l2_subdev_file_ops preview_v4l2_file_ops = {
12576+ .open = preview_init_formats,
12577+};
12578+
12579+/* subdev video operations */
12580+static const struct v4l2_subdev_video_ops preview_v4l2_video_ops = {
12581+ .s_stream = preview_set_stream,
12582+};
12583+
12584+/* subdev pad operations */
12585+static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
12586+ .enum_mbus_code = preview_enum_mbus_code,
12587+ .enum_frame_size = preview_enum_frame_size,
12588+ .get_fmt = preview_get_format,
12589+ .set_fmt = preview_set_format,
12590+};
12591+
12592+/* subdev operations */
12593+static const struct v4l2_subdev_ops preview_v4l2_ops = {
12594+ .core = &preview_v4l2_core_ops,
12595+ .file = &preview_v4l2_file_ops,
12596+ .video = &preview_v4l2_video_ops,
12597+ .pad = &preview_v4l2_pad_ops,
12598+};
12599+
12600+/* -----------------------------------------------------------------------------
12601+ * Media entity operations
12602+ */
12603+
12604+/*
12605+ * preview_link_setup - Setup previewer connections.
12606+ * @entity : Pointer to media entity structure
12607+ * @local : Pointer to local pad array
12608+ * @remote : Pointer to remote pad array
12609+ * @flags : Link flags
12610+ * return -EINVAL or zero on success
12611+ */
12612+static int preview_link_setup(struct media_entity *entity,
12613+ const struct media_pad *local,
12614+ const struct media_pad *remote, u32 flags)
12615+{
12616+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
12617+ struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
12618+
12619+ switch (local->index | media_entity_type(remote->entity)) {
12620+ case PREV_PAD_SINK | MEDIA_ENT_T_DEVNODE:
12621+ /* read from memory */
12622+ if (flags & MEDIA_LNK_FL_ENABLED) {
12623+ if (prev->input == PREVIEW_INPUT_CCDC)
12624+ return -EBUSY;
12625+ prev->input = PREVIEW_INPUT_MEMORY;
12626+ } else {
12627+ if (prev->input == PREVIEW_INPUT_MEMORY)
12628+ prev->input = PREVIEW_INPUT_NONE;
12629+ }
12630+ break;
12631+
12632+ case PREV_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
12633+ /* read from ccdc */
12634+ if (flags & MEDIA_LNK_FL_ENABLED) {
12635+ if (prev->input == PREVIEW_INPUT_MEMORY)
12636+ return -EBUSY;
12637+ prev->input = PREVIEW_INPUT_CCDC;
12638+ } else {
12639+ if (prev->input == PREVIEW_INPUT_CCDC)
12640+ prev->input = PREVIEW_INPUT_NONE;
12641+ }
12642+ break;
12643+
12644+ /*
12645+ * The ISP core doesn't support pipelines with multiple video outputs.
12646+ * Revisit this when it will be implemented, and return -EBUSY for now.
12647+ */
12648+
12649+ case PREV_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
12650+ /* write to memory */
12651+ if (flags & MEDIA_LNK_FL_ENABLED) {
12652+ if (prev->output & ~PREVIEW_OUTPUT_MEMORY)
12653+ return -EBUSY;
12654+ prev->output |= PREVIEW_OUTPUT_MEMORY;
12655+ } else {
12656+ prev->output &= ~PREVIEW_OUTPUT_MEMORY;
12657+ }
12658+ break;
12659+
12660+ case PREV_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
12661+ /* write to resizer */
12662+ if (flags & MEDIA_LNK_FL_ENABLED) {
12663+ if (prev->output & ~PREVIEW_OUTPUT_RESIZER)
12664+ return -EBUSY;
12665+ prev->output |= PREVIEW_OUTPUT_RESIZER;
12666+ } else {
12667+ prev->output &= ~PREVIEW_OUTPUT_RESIZER;
12668+ }
12669+ break;
12670+
12671+ default:
12672+ return -EINVAL;
12673+ }
12674+
12675+ return 0;
12676+}
12677+
12678+/* media operations */
12679+static const struct media_entity_operations preview_media_ops = {
12680+ .link_setup = preview_link_setup,
12681+};
12682+
12683+/*
12684+ * review_init_entities - Initialize subdev and media entity.
12685+ * @prev : Pointer to preview structure
12686+ * return -ENOMEM or zero on success
12687+ */
12688+static int preview_init_entities(struct isp_prev_device *prev)
12689+{
12690+ struct v4l2_subdev *sd = &prev->subdev;
12691+ struct media_pad *pads = prev->pads;
12692+ struct media_entity *me = &sd->entity;
12693+ int ret;
12694+
12695+ prev->input = PREVIEW_INPUT_NONE;
12696+
12697+ v4l2_subdev_init(sd, &preview_v4l2_ops);
12698+ strlcpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name));
12699+ sd->grp_id = 1 << 16; /* group ID for isp subdevs */
12700+ v4l2_set_subdevdata(sd, prev);
12701+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
12702+
12703+ v4l2_ctrl_handler_init(&prev->ctrls, 3);
12704+ v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_BRIGHTNESS,
12705+ ISPPRV_BRIGHT_LOW, ISPPRV_BRIGHT_HIGH,
12706+ ISPPRV_BRIGHT_STEP, ISPPRV_BRIGHT_DEF);
12707+ v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_CONTRAST,
12708+ ISPPRV_CONTRAST_LOW, ISPPRV_CONTRAST_HIGH,
12709+ ISPPRV_CONTRAST_STEP, ISPPRV_CONTRAST_DEF);
12710+ v4l2_ctrl_handler_setup(&prev->ctrls);
12711+ sd->ctrl_handler = &prev->ctrls;
12712+
12713+ pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_INPUT;
12714+ pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_OUTPUT;
12715+
12716+ me->ops = &preview_media_ops;
12717+ ret = media_entity_init(me, PREV_PADS_NUM, pads, 0);
12718+ if (ret < 0)
12719+ return ret;
12720+
12721+ preview_init_formats(sd, NULL);
12722+
12723+ /* According to the OMAP34xx TRM, video buffers need to be aligned on a
12724+ * 32 bytes boundary. However, an undocumented hardware bug requires a
12725+ * 64 bytes boundary at the preview engine input.
12726+ */
12727+ prev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
12728+ prev->video_in.ops = &preview_video_ops;
12729+ prev->video_in.isp = to_isp_device(prev);
12730+ prev->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
12731+ prev->video_in.bpl_alignment = 64;
12732+ prev->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
12733+ prev->video_out.ops = &preview_video_ops;
12734+ prev->video_out.isp = to_isp_device(prev);
12735+ prev->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
12736+ prev->video_out.bpl_alignment = 32;
12737+
12738+ ret = omap3isp_video_init(&prev->video_in, "preview");
12739+ if (ret < 0)
12740+ return ret;
12741+
12742+ ret = omap3isp_video_init(&prev->video_out, "preview");
12743+ if (ret < 0)
12744+ return ret;
12745+
12746+ /* Connect the video nodes to the previewer subdev. */
12747+ ret = media_entity_create_link(&prev->video_in.video.entity, 0,
12748+ &prev->subdev.entity, PREV_PAD_SINK, 0);
12749+ if (ret < 0)
12750+ return ret;
12751+
12752+ ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
12753+ &prev->video_out.video.entity, 0, 0);
12754+ if (ret < 0)
12755+ return ret;
12756+
12757+ return 0;
12758+}
12759+
12760+void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
12761+{
12762+ media_entity_cleanup(&prev->subdev.entity);
12763+
12764+ v4l2_device_unregister_subdev(&prev->subdev);
12765+ v4l2_ctrl_handler_free(&prev->ctrls);
12766+ omap3isp_video_unregister(&prev->video_in);
12767+ omap3isp_video_unregister(&prev->video_out);
12768+}
12769+
12770+int omap3isp_preview_register_entities(struct isp_prev_device *prev,
12771+ struct v4l2_device *vdev)
12772+{
12773+ int ret;
12774+
12775+ /* Register the subdev and video nodes. */
12776+ ret = v4l2_device_register_subdev(vdev, &prev->subdev);
12777+ if (ret < 0)
12778+ goto error;
12779+
12780+ ret = omap3isp_video_register(&prev->video_in, vdev);
12781+ if (ret < 0)
12782+ goto error;
12783+
12784+ ret = omap3isp_video_register(&prev->video_out, vdev);
12785+ if (ret < 0)
12786+ goto error;
12787+
12788+ return 0;
12789+
12790+error:
12791+ omap3isp_preview_unregister_entities(prev);
12792+ return ret;
12793+}
12794+
12795+/* -----------------------------------------------------------------------------
12796+ * ISP previewer initialisation and cleanup
12797+ */
12798+
12799+void omap3isp_preview_cleanup(struct isp_device *isp)
12800+{
12801+}
12802+
12803+/*
12804+ * isp_preview_init - Previewer initialization.
12805+ * @dev : Pointer to ISP device
12806+ * return -ENOMEM or zero on success
12807+ */
12808+int omap3isp_preview_init(struct isp_device *isp)
12809+{
12810+ struct isp_prev_device *prev = &isp->isp_prev;
12811+ int ret;
12812+
12813+ spin_lock_init(&prev->lock);
12814+ init_waitqueue_head(&prev->wait);
12815+ preview_init_params(prev);
12816+
12817+ ret = preview_init_entities(prev);
12818+ if (ret < 0)
12819+ goto out;
12820+
12821+out:
12822+ if (ret)
12823+ omap3isp_preview_cleanup(isp);
12824+
12825+ return ret;
12826+}
12827diff --git a/drivers/media/video/isp/isppreview.h b/drivers/media/video/isp/isppreview.h
12828new file mode 100644
12829index 0000000..e20c7c6
12830--- /dev/null
12831+++ b/drivers/media/video/isp/isppreview.h
12832@@ -0,0 +1,214 @@
12833+/*
12834+ * isppreview.h
12835+ *
12836+ * TI OMAP3 ISP - Preview module
12837+ *
12838+ * Copyright (C) 2010 Nokia Corporation
12839+ * Copyright (C) 2009 Texas Instruments, Inc.
12840+ *
12841+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
12842+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
12843+ *
12844+ * This program is free software; you can redistribute it and/or modify
12845+ * it under the terms of the GNU General Public License version 2 as
12846+ * published by the Free Software Foundation.
12847+ *
12848+ * This program is distributed in the hope that it will be useful, but
12849+ * WITHOUT ANY WARRANTY; without even the implied warranty of
12850+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12851+ * General Public License for more details.
12852+ *
12853+ * You should have received a copy of the GNU General Public License
12854+ * along with this program; if not, write to the Free Software
12855+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
12856+ * 02110-1301 USA
12857+ */
12858+
12859+#ifndef OMAP3_ISP_PREVIEW_H
12860+#define OMAP3_ISP_PREVIEW_H
12861+
12862+#include <linux/omap3isp.h>
12863+#include <linux/types.h>
12864+#include <media/v4l2-ctrls.h>
12865+
12866+#include "ispvideo.h"
12867+
12868+#define ISPPRV_BRIGHT_STEP 0x1
12869+#define ISPPRV_BRIGHT_DEF 0x0
12870+#define ISPPRV_BRIGHT_LOW 0x0
12871+#define ISPPRV_BRIGHT_HIGH 0xFF
12872+#define ISPPRV_BRIGHT_UNITS 0x1
12873+
12874+#define ISPPRV_CONTRAST_STEP 0x1
12875+#define ISPPRV_CONTRAST_DEF 0x10
12876+#define ISPPRV_CONTRAST_LOW 0x0
12877+#define ISPPRV_CONTRAST_HIGH 0xFF
12878+#define ISPPRV_CONTRAST_UNITS 0x1
12879+
12880+#define NO_AVE 0x0
12881+#define AVE_2_PIX 0x1
12882+#define AVE_4_PIX 0x2
12883+#define AVE_8_PIX 0x3
12884+
12885+/* Features list */
12886+#define PREV_LUMA_ENHANCE OMAP3ISP_PREV_LUMAENH
12887+#define PREV_INVERSE_ALAW OMAP3ISP_PREV_INVALAW
12888+#define PREV_HORZ_MEDIAN_FILTER OMAP3ISP_PREV_HRZ_MED
12889+#define PREV_CFA OMAP3ISP_PREV_CFA
12890+#define PREV_CHROMA_SUPPRESS OMAP3ISP_PREV_CHROMA_SUPP
12891+#define PREV_WB OMAP3ISP_PREV_WB
12892+#define PREV_BLKADJ OMAP3ISP_PREV_BLKADJ
12893+#define PREV_RGB2RGB OMAP3ISP_PREV_RGB2RGB
12894+#define PREV_COLOR_CONV OMAP3ISP_PREV_COLOR_CONV
12895+#define PREV_YCLIMITS OMAP3ISP_PREV_YC_LIMIT
12896+#define PREV_DEFECT_COR OMAP3ISP_PREV_DEFECT_COR
12897+#define PREV_GAMMA_BYPASS OMAP3ISP_PREV_GAMMABYPASS
12898+#define PREV_DARK_FRAME_CAPTURE OMAP3ISP_PREV_DRK_FRM_CAPTURE
12899+#define PREV_DARK_FRAME_SUBTRACT OMAP3ISP_PREV_DRK_FRM_SUBTRACT
12900+#define PREV_LENS_SHADING OMAP3ISP_PREV_LENS_SHADING
12901+#define PREV_NOISE_FILTER OMAP3ISP_PREV_NF
12902+#define PREV_GAMMA OMAP3ISP_PREV_GAMMA
12903+
12904+#define PREV_CONTRAST (1 << 17)
12905+#define PREV_BRIGHTNESS (1 << 18)
12906+#define PREV_AVERAGER (1 << 19)
12907+#define PREV_FEATURES_END (1 << 20)
12908+
12909+enum preview_input_entity {
12910+ PREVIEW_INPUT_NONE,
12911+ PREVIEW_INPUT_CCDC,
12912+ PREVIEW_INPUT_MEMORY,
12913+};
12914+
12915+#define PREVIEW_OUTPUT_RESIZER (1 << 1)
12916+#define PREVIEW_OUTPUT_MEMORY (1 << 2)
12917+
12918+/* Configure byte layout of YUV image */
12919+enum preview_ycpos_mode {
12920+ YCPOS_YCrYCb = 0,
12921+ YCPOS_YCbYCr = 1,
12922+ YCPOS_CbYCrY = 2,
12923+ YCPOS_CrYCbY = 3
12924+};
12925+
12926+/*
12927+ * struct prev_params - Structure for all configuration
12928+ * @features: Set of features enabled.
12929+ * @cfa: CFA coefficients.
12930+ * @csup: Chroma suppression coefficients.
12931+ * @luma: Luma enhancement coefficients.
12932+ * @nf: Noise filter coefficients.
12933+ * @dcor: Noise filter coefficients.
12934+ * @gamma: Gamma coefficients.
12935+ * @wbal: White Balance parameters.
12936+ * @blk_adj: Black adjustment parameters.
12937+ * @rgb2rgb: RGB blending parameters.
12938+ * @rgb2ycbcr: RGB to ycbcr parameters.
12939+ * @hmed: Horizontal median filter.
12940+ * @yclimit: YC limits parameters.
12941+ * @average: Downsampling rate for averager.
12942+ * @contrast: Contrast.
12943+ * @brightness: Brightness.
12944+ */
12945+struct prev_params {
12946+ u32 features;
12947+ struct omap3isp_prev_cfa cfa;
12948+ struct omap3isp_prev_csup csup;
12949+ struct omap3isp_prev_luma luma;
12950+ struct omap3isp_prev_nf nf;
12951+ struct omap3isp_prev_dcor dcor;
12952+ struct omap3isp_prev_gtables gamma;
12953+ struct omap3isp_prev_wbal wbal;
12954+ struct omap3isp_prev_blkadj blk_adj;
12955+ struct omap3isp_prev_rgbtorgb rgb2rgb;
12956+ struct omap3isp_prev_csc rgb2ycbcr;
12957+ struct omap3isp_prev_hmed hmed;
12958+ struct omap3isp_prev_yclimit yclimit;
12959+ u8 average;
12960+ u8 contrast;
12961+ u8 brightness;
12962+};
12963+
12964+/*
12965+ * struct isptables_update - Structure for Table Configuration.
12966+ * @update: Specifies which tables should be updated.
12967+ * @flag: Specifies which tables should be enabled.
12968+ * @nf: Pointer to structure for Noise Filter
12969+ * @lsc: Pointer to LSC gain table. (currently not used)
12970+ * @gamma: Pointer to gamma correction tables.
12971+ * @cfa: Pointer to color filter array configuration.
12972+ * @wbal: Pointer to colour and digital gain configuration.
12973+ */
12974+struct isptables_update {
12975+ u32 update;
12976+ u32 flag;
12977+ struct omap3isp_prev_nf *nf;
12978+ u32 *lsc;
12979+ struct omap3isp_prev_gtables *gamma;
12980+ struct omap3isp_prev_cfa *cfa;
12981+ struct omap3isp_prev_wbal *wbal;
12982+};
12983+
12984+/* Sink and source previewer pads */
12985+#define PREV_PAD_SINK 0
12986+#define PREV_PAD_SOURCE 1
12987+#define PREV_PADS_NUM 2
12988+
12989+/*
12990+ * struct isp_prev_device - Structure for storing ISP Preview module information
12991+ * @subdev: V4L2 subdevice
12992+ * @pads: Media entity pads
12993+ * @formats: Active formats at the subdev pad
12994+ * @input: Module currently connected to the input pad
12995+ * @output: Bitmask of the active output
12996+ * @video_in: Input video entity
12997+ * @video_out: Output video entity
12998+ * @error: A hardware error occured during capture
12999+ * @params: Module configuration data
13000+ * @shadow_update: If set, update the hardware configured in the next interrupt
13001+ * @underrun: Whether the preview entity has queued buffers on the output
13002+ * @state: Current preview pipeline state
13003+ * @lock: Shadow update lock
13004+ * @update: Bitmask of the parameters to be updated
13005+ *
13006+ * This structure is used to store the OMAP ISP Preview module Information.
13007+ */
13008+struct isp_prev_device {
13009+ struct v4l2_subdev subdev;
13010+ struct media_pad pads[PREV_PADS_NUM];
13011+ struct v4l2_mbus_framefmt formats[PREV_PADS_NUM];
13012+
13013+ struct v4l2_ctrl_handler ctrls;
13014+
13015+ enum preview_input_entity input;
13016+ unsigned int output;
13017+ struct isp_video video_in;
13018+ struct isp_video video_out;
13019+ unsigned int error;
13020+
13021+ struct prev_params params;
13022+ unsigned int shadow_update:1;
13023+ enum isp_pipeline_stream_state state;
13024+ wait_queue_head_t wait;
13025+ atomic_t stopping;
13026+ spinlock_t lock;
13027+ u32 update;
13028+};
13029+
13030+struct isp_device;
13031+
13032+int omap3isp_preview_init(struct isp_device *isp);
13033+void omap3isp_preview_cleanup(struct isp_device *isp);
13034+
13035+int omap3isp_preview_register_entities(struct isp_prev_device *prv,
13036+ struct v4l2_device *vdev);
13037+void omap3isp_preview_unregister_entities(struct isp_prev_device *prv);
13038+
13039+void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev);
13040+void omap3isp_preview_isr(struct isp_prev_device *prev);
13041+
13042+int omap3isp_preview_busy(struct isp_prev_device *isp_prev);
13043+
13044+void omap3isp_preview_restore_context(struct isp_device *isp);
13045+
13046+#endif /* OMAP3_ISP_PREVIEW_H */
13047diff --git a/drivers/media/video/isp/ispqueue.c b/drivers/media/video/isp/ispqueue.c
13048new file mode 100644
13049index 0000000..af78c19
13050--- /dev/null
13051+++ b/drivers/media/video/isp/ispqueue.c
13052@@ -0,0 +1,1136 @@
13053+/*
13054+ * ispqueue.c
13055+ *
13056+ * TI OMAP3 ISP - Video buffers queue handling
13057+ *
13058+ * Copyright (C) 2010 Nokia Corporation
13059+ *
13060+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
13061+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
13062+ *
13063+ * This program is free software; you can redistribute it and/or modify
13064+ * it under the terms of the GNU General Public License version 2 as
13065+ * published by the Free Software Foundation.
13066+ *
13067+ * This program is distributed in the hope that it will be useful, but
13068+ * WITHOUT ANY WARRANTY; without even the implied warranty of
13069+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13070+ * General Public License for more details.
13071+ *
13072+ * You should have received a copy of the GNU General Public License
13073+ * along with this program; if not, write to the Free Software
13074+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
13075+ * 02110-1301 USA
13076+ */
13077+
13078+#include <asm/cacheflush.h>
13079+#include <linux/dma-mapping.h>
13080+#include <linux/mm.h>
13081+#include <linux/pagemap.h>
13082+#include <linux/poll.h>
13083+#include <linux/scatterlist.h>
13084+#include <linux/sched.h>
13085+#include <linux/slab.h>
13086+#include <linux/vmalloc.h>
13087+
13088+#include "ispqueue.h"
13089+
13090+/* -----------------------------------------------------------------------------
13091+ * Video buffers management
13092+ */
13093+
13094+/*
13095+ * isp_video_buffer_cache_sync - Keep the buffers coherent between CPU and ISP
13096+ *
13097+ * The typical operation required here is Cache Invalidation across
13098+ * the (user space) buffer address range. And this _must_ be done
13099+ * at QBUF stage (and *only* at QBUF).
13100+ *
13101+ * We try to use optimal cache invalidation function:
13102+ * - dmac_map_area:
13103+ * - used when the number of pages are _low_.
13104+ * - it becomes quite slow as the number of pages increase.
13105+ * - for 648x492 viewfinder (150 pages) it takes 1.3 ms.
13106+ * - for 5 Mpix buffer (2491 pages) it takes between 25-50 ms.
13107+ *
13108+ * - flush_cache_all:
13109+ * - used when the number of pages are _high_.
13110+ * - time taken in the range of 500-900 us.
13111+ * - has a higher penalty but, as whole dcache + icache is invalidated
13112+ */
13113+/*
13114+ * FIXME: dmac_inv_range crashes randomly on the user space buffer
13115+ * address. Fall back to flush_cache_all for now.
13116+ */
13117+#define ISP_CACHE_FLUSH_PAGES_MAX 0
13118+
13119+static void isp_video_buffer_cache_sync(struct isp_video_buffer *buf)
13120+{
13121+ if (buf->vbuf.m.userptr == 0 || buf->npages == 0 ||
13122+ buf->npages > ISP_CACHE_FLUSH_PAGES_MAX)
13123+ flush_cache_all();
13124+ else {
13125+ dmac_map_area((void *)buf->vbuf.m.userptr, buf->vbuf.length,
13126+ DMA_FROM_DEVICE);
13127+ outer_inv_range(buf->vbuf.m.userptr,
13128+ buf->vbuf.m.userptr + buf->vbuf.length);
13129+ }
13130+}
13131+
13132+/*
13133+ * isp_video_buffer_lock_vma - Prevent VMAs from being unmapped
13134+ *
13135+ * Lock the VMAs underlying the given buffer into memory. This avoids the
13136+ * userspace buffer mapping from being swapped out, making VIPT cache handling
13137+ * easier.
13138+ *
13139+ * Note that the pages will not be freed as the buffers have been locked to
13140+ * memory using by a call to get_user_pages(), but the userspace mapping could
13141+ * still disappear if the VMAs are not locked. This is caused by the memory
13142+ * management code trying to be as lock-less as possible, which results in the
13143+ * userspace mapping manager not finding out that the pages are locked under
13144+ * some conditions.
13145+ */
13146+static int isp_video_buffer_lock_vma(struct isp_video_buffer *buf, int lock)
13147+{
13148+ struct vm_area_struct *vma;
13149+ unsigned long start;
13150+ unsigned long end;
13151+ int ret = 0;
13152+
13153+ if (buf->vbuf.memory == V4L2_MEMORY_MMAP)
13154+ return 0;
13155+
13156+ /* We can be called from workqueue context if the current task dies to
13157+ * unlock the VMAs. In that case there's no current memory management
13158+ * context so unlocking can't be performed, but the VMAs have been or
13159+ * are getting destroyed anyway so it doesn't really matter.
13160+ */
13161+ if (!current || !current->mm)
13162+ return lock ? -EINVAL : 0;
13163+
13164+ start = buf->vbuf.m.userptr;
13165+ end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
13166+
13167+ down_write(&current->mm->mmap_sem);
13168+ spin_lock(&current->mm->page_table_lock);
13169+
13170+ do {
13171+ vma = find_vma(current->mm, start);
13172+ if (vma == NULL) {
13173+ ret = -EFAULT;
13174+ goto out;
13175+ }
13176+
13177+ if (lock)
13178+ vma->vm_flags |= VM_LOCKED;
13179+ else
13180+ vma->vm_flags &= ~VM_LOCKED;
13181+
13182+ start = vma->vm_end + 1;
13183+ } while (vma->vm_end < end);
13184+
13185+ if (lock)
13186+ buf->vm_flags |= VM_LOCKED;
13187+ else
13188+ buf->vm_flags &= ~VM_LOCKED;
13189+
13190+out:
13191+ spin_unlock(&current->mm->page_table_lock);
13192+ up_write(&current->mm->mmap_sem);
13193+ return ret;
13194+}
13195+
13196+/*
13197+ * isp_video_buffer_sglist_kernel - Build a scatter list for a vmalloc'ed buffer
13198+ *
13199+ * Iterate over the vmalloc'ed area and create a scatter list entry for every
13200+ * page.
13201+ */
13202+static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
13203+{
13204+ struct scatterlist *sglist;
13205+ unsigned int npages;
13206+ unsigned int i;
13207+ void *addr;
13208+
13209+ addr = buf->vaddr;
13210+ npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT;
13211+
13212+ sglist = vmalloc(npages * sizeof(*sglist));
13213+ if (sglist == NULL)
13214+ return -ENOMEM;
13215+
13216+ sg_init_table(sglist, npages);
13217+
13218+ for (i = 0; i < npages; ++i, addr += PAGE_SIZE) {
13219+ struct page *page = vmalloc_to_page(addr);
13220+
13221+ if (page == NULL || PageHighMem(page)) {
13222+ vfree(sglist);
13223+ return -EINVAL;
13224+ }
13225+
13226+ sg_set_page(&sglist[i], page, PAGE_SIZE, 0);
13227+ }
13228+
13229+ buf->sglen = npages;
13230+ buf->sglist = sglist;
13231+
13232+ return 0;
13233+}
13234+
13235+/*
13236+ * isp_video_buffer_sglist_user - Build a scatter list for a userspace buffer
13237+ *
13238+ * Walk the buffer pages list and create a 1:1 mapping to a scatter list.
13239+ */
13240+static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf)
13241+{
13242+ struct scatterlist *sglist;
13243+ unsigned int offset = buf->offset;
13244+ unsigned int i;
13245+
13246+ sglist = vmalloc(buf->npages * sizeof(*sglist));
13247+ if (sglist == NULL)
13248+ return -ENOMEM;
13249+
13250+ sg_init_table(sglist, buf->npages);
13251+
13252+ for (i = 0; i < buf->npages; ++i) {
13253+ if (PageHighMem(buf->pages[i])) {
13254+ vfree(sglist);
13255+ return -EINVAL;
13256+ }
13257+
13258+ sg_set_page(&sglist[i], buf->pages[i], PAGE_SIZE - offset,
13259+ offset);
13260+ offset = 0;
13261+ }
13262+
13263+ buf->sglen = buf->npages;
13264+ buf->sglist = sglist;
13265+
13266+ return 0;
13267+}
13268+
13269+/*
13270+ * isp_video_buffer_sglist_pfnmap - Build a scatter list for a VM_PFNMAP buffer
13271+ *
13272+ * Create a scatter list of physically contiguous pages starting at the buffer
13273+ * memory physical address.
13274+ */
13275+static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf)
13276+{
13277+ struct scatterlist *sglist;
13278+ unsigned int offset = buf->offset;
13279+ unsigned long pfn = buf->paddr >> PAGE_SHIFT;
13280+ unsigned int i;
13281+
13282+ sglist = vmalloc(buf->npages * sizeof(*sglist));
13283+ if (sglist == NULL)
13284+ return -ENOMEM;
13285+
13286+ sg_init_table(sglist, buf->npages);
13287+
13288+ for (i = 0; i < buf->npages; ++i, ++pfn) {
13289+ sg_set_page(&sglist[i], pfn_to_page(pfn), PAGE_SIZE - offset,
13290+ offset);
13291+ /* PFNMAP buffers will not get DMA-mapped, set the DMA address
13292+ * manually.
13293+ */
13294+ sg_dma_address(&sglist[i]) = (pfn << PAGE_SHIFT) + offset;
13295+ offset = 0;
13296+ }
13297+
13298+ buf->sglen = buf->npages;
13299+ buf->sglist = sglist;
13300+
13301+ return 0;
13302+}
13303+
13304+/*
13305+ * isp_video_buffer_cleanup - Release pages for a userspace VMA.
13306+ *
13307+ * Release pages locked by a call isp_video_buffer_prepare_user and free the
13308+ * pages table.
13309+ */
13310+static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
13311+{
13312+ enum dma_data_direction direction;
13313+ unsigned int i;
13314+
13315+ if (buf->queue->ops->buffer_cleanup)
13316+ buf->queue->ops->buffer_cleanup(buf);
13317+
13318+ if (!(buf->vm_flags & VM_PFNMAP)) {
13319+ direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
13320+ ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
13321+ dma_unmap_sg(buf->queue->dev, buf->sglist, buf->sglen,
13322+ direction);
13323+ }
13324+
13325+ vfree(buf->sglist);
13326+ buf->sglist = NULL;
13327+ buf->sglen = 0;
13328+
13329+ if (buf->pages != NULL) {
13330+ isp_video_buffer_lock_vma(buf, 0);
13331+
13332+ for (i = 0; i < buf->npages; ++i)
13333+ page_cache_release(buf->pages[i]);
13334+
13335+ vfree(buf->pages);
13336+ buf->pages = NULL;
13337+ }
13338+
13339+ buf->npages = 0;
13340+}
13341+
13342+/*
13343+ * isp_video_buffer_prepare_user - Pin userspace VMA pages to memory.
13344+ *
13345+ * This function creates a list of pages for a userspace VMA. The number of
13346+ * pages is first computed based on the buffer size, and pages are then
13347+ * retrieved by a call to get_user_pages.
13348+ *
13349+ * Pages are pinned to memory by get_user_pages, making them available for DMA
13350+ * transfers. However, due to memory management optimization, it seems the
13351+ * get_user_pages doesn't guarantee that the pinned pages will not be written
13352+ * to swap and removed from the userspace mapping(s). When this happens, a page
13353+ * fault can be generated when accessing those unmapped pages.
13354+ *
13355+ * If the fault is triggered by a page table walk caused by VIPT cache
13356+ * management operations, the page fault handler might oops if the MM semaphore
13357+ * is held, as it can't handle kernel page faults in that case. To fix that, a
13358+ * fixup entry needs to be added to the cache management code, or the userspace
13359+ * VMA must be locked to avoid removing pages from the userspace mapping in the
13360+ * first place.
13361+ *
13362+ * If the number of pages retrieved is smaller than the number required by the
13363+ * buffer size, the function returns -EFAULT.
13364+ */
13365+static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
13366+{
13367+ unsigned long data;
13368+ unsigned int first;
13369+ unsigned int last;
13370+ int ret;
13371+
13372+ data = buf->vbuf.m.userptr;
13373+ first = (data & PAGE_MASK) >> PAGE_SHIFT;
13374+ last = ((data + buf->vbuf.length - 1) & PAGE_MASK) >> PAGE_SHIFT;
13375+
13376+ buf->offset = data & ~PAGE_MASK;
13377+ buf->npages = last - first + 1;
13378+ buf->pages = vmalloc(buf->npages * sizeof(buf->pages[0]));
13379+ if (buf->pages == NULL)
13380+ return -ENOMEM;
13381+
13382+ down_read(&current->mm->mmap_sem);
13383+ ret = get_user_pages(current, current->mm, data & PAGE_MASK,
13384+ buf->npages,
13385+ buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
13386+ buf->pages, NULL);
13387+ up_read(&current->mm->mmap_sem);
13388+
13389+ if (ret != buf->npages) {
13390+ buf->npages = ret;
13391+ isp_video_buffer_cleanup(buf);
13392+ return -EFAULT;
13393+ }
13394+
13395+ ret = isp_video_buffer_lock_vma(buf, 1);
13396+ if (ret < 0)
13397+ isp_video_buffer_cleanup(buf);
13398+
13399+ return ret;
13400+}
13401+
13402+/*
13403+ * isp_video_buffer_prepare_pfnmap - Validate a VM_PFNMAP userspace buffer
13404+ *
13405+ * Userspace VM_PFNMAP buffers are supported only if they are contiguous in
13406+ * memory and if they span a single VMA.
13407+ *
13408+ * Return 0 if the buffer is valid, or -EFAULT otherwise.
13409+ */
13410+static int isp_video_buffer_prepare_pfnmap(struct isp_video_buffer *buf)
13411+{
13412+ struct vm_area_struct *vma;
13413+ unsigned long prev_pfn;
13414+ unsigned long this_pfn;
13415+ unsigned long start;
13416+ unsigned long end;
13417+ dma_addr_t pa;
13418+ int ret = -EFAULT;
13419+
13420+ start = buf->vbuf.m.userptr;
13421+ end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
13422+
13423+ buf->offset = start & ~PAGE_MASK;
13424+ buf->npages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
13425+ buf->pages = NULL;
13426+
13427+ down_read(&current->mm->mmap_sem);
13428+ vma = find_vma(current->mm, start);
13429+ if (vma == NULL || vma->vm_end < end)
13430+ goto done;
13431+
13432+ for (prev_pfn = 0; start <= end; start += PAGE_SIZE) {
13433+ ret = follow_pfn(vma, start, &this_pfn);
13434+ if (ret)
13435+ goto done;
13436+
13437+ if (prev_pfn == 0)
13438+ pa = this_pfn << PAGE_SHIFT;
13439+ else if (this_pfn != prev_pfn + 1) {
13440+ ret = -EFAULT;
13441+ goto done;
13442+ }
13443+
13444+ prev_pfn = this_pfn;
13445+ }
13446+
13447+ buf->paddr = pa + buf->offset;
13448+ ret = 0;
13449+
13450+done:
13451+ up_read(&current->mm->mmap_sem);
13452+ return ret;
13453+}
13454+
13455+/*
13456+ * isp_video_buffer_prepare_vm_flags - Get VMA flags for a userspace address
13457+ *
13458+ * This function locates the VMAs for the buffer's userspace address and checks
13459+ * that their flags match. The onlflag that we need to care for at the moment is
13460+ * VM_PFNMAP.
13461+ *
13462+ * The buffer vm_flags field is set to the first VMA flags.
13463+ *
13464+ * Return -EFAULT if no VMA can be found for part of the buffer, or if the VMAs
13465+ * have incompatible flags.
13466+ */
13467+static int isp_video_buffer_prepare_vm_flags(struct isp_video_buffer *buf)
13468+{
13469+ struct vm_area_struct *vma;
13470+ unsigned long start;
13471+ unsigned long end;
13472+ int ret = -EFAULT;
13473+
13474+ start = buf->vbuf.m.userptr;
13475+ end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
13476+
13477+ down_read(&current->mm->mmap_sem);
13478+
13479+ do {
13480+ vma = find_vma(current->mm, start);
13481+ if (vma == NULL)
13482+ goto done;
13483+
13484+ if (start == buf->vbuf.m.userptr)
13485+ buf->vm_flags = vma->vm_flags;
13486+
13487+ if ((buf->vm_flags ^ vma->vm_flags) & VM_PFNMAP)
13488+ goto done;
13489+
13490+ start = vma->vm_end + 1;
13491+ } while (vma->vm_end < end);
13492+
13493+ ret = 0;
13494+
13495+done:
13496+ up_read(&current->mm->mmap_sem);
13497+ return ret;
13498+}
13499+
13500+/*
13501+ * isp_video_buffer_prepare - Make a buffer ready for operation
13502+ *
13503+ * Preparing a buffer involves:
13504+ *
13505+ * - validating VMAs (userspace buffers only)
13506+ * - locking pages and VMAs into memory (userspace buffers only)
13507+ * - building page and scatter-gather lists
13508+ * - mapping buffers for DMA operation
13509+ * - performing driver-specific preparation
13510+ *
13511+ * The function must be called in userspace context with a valid mm context
13512+ * (this excludes cleanup paths such as sys_close when the userspace process
13513+ * segfaults).
13514+ */
13515+static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
13516+{
13517+ enum dma_data_direction direction;
13518+ int ret;
13519+
13520+ switch (buf->vbuf.memory) {
13521+ case V4L2_MEMORY_MMAP:
13522+ ret = isp_video_buffer_sglist_kernel(buf);
13523+ break;
13524+
13525+ case V4L2_MEMORY_USERPTR:
13526+ ret = isp_video_buffer_prepare_vm_flags(buf);
13527+ if (ret < 0)
13528+ return ret;
13529+
13530+ if (buf->vm_flags & VM_PFNMAP) {
13531+ ret = isp_video_buffer_prepare_pfnmap(buf);
13532+ if (ret < 0)
13533+ return ret;
13534+
13535+ ret = isp_video_buffer_sglist_pfnmap(buf);
13536+ } else {
13537+ ret = isp_video_buffer_prepare_user(buf);
13538+ if (ret < 0)
13539+ return ret;
13540+
13541+ ret = isp_video_buffer_sglist_user(buf);
13542+ }
13543+ break;
13544+
13545+ default:
13546+ return -EINVAL;
13547+ }
13548+
13549+ if (ret < 0)
13550+ goto done;
13551+
13552+ if (!(buf->vm_flags & VM_PFNMAP)) {
13553+ direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
13554+ ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
13555+ ret = dma_map_sg(buf->queue->dev, buf->sglist, buf->sglen,
13556+ direction);
13557+ if (ret != buf->sglen) {
13558+ ret = -EFAULT;
13559+ goto done;
13560+ }
13561+ }
13562+
13563+ if (buf->queue->ops->buffer_prepare)
13564+ ret = buf->queue->ops->buffer_prepare(buf);
13565+
13566+done:
13567+ if (ret < 0) {
13568+ isp_video_buffer_cleanup(buf);
13569+ return ret;
13570+ }
13571+
13572+ return ret;
13573+}
13574+
13575+/*
13576+ * isp_video_queue_query - Query the status of a given buffer
13577+ *
13578+ * Locking: must be called with the queue lock held.
13579+ */
13580+static void isp_video_buffer_query(struct isp_video_buffer *buf,
13581+ struct v4l2_buffer *vbuf)
13582+{
13583+ memcpy(vbuf, &buf->vbuf, sizeof(*vbuf));
13584+
13585+ if (buf->vma_use_count)
13586+ vbuf->flags |= V4L2_BUF_FLAG_MAPPED;
13587+
13588+ switch (buf->state) {
13589+ case ISP_BUF_STATE_ERROR:
13590+ vbuf->flags |= V4L2_BUF_FLAG_ERROR;
13591+ case ISP_BUF_STATE_DONE:
13592+ vbuf->flags |= V4L2_BUF_FLAG_DONE;
13593+ case ISP_BUF_STATE_QUEUED:
13594+ case ISP_BUF_STATE_ACTIVE:
13595+ vbuf->flags |= V4L2_BUF_FLAG_QUEUED;
13596+ break;
13597+ case ISP_BUF_STATE_IDLE:
13598+ default:
13599+ break;
13600+ }
13601+}
13602+
13603+/*
13604+ * isp_video_buffer_wait - Wait for a buffer to be ready
13605+ *
13606+ * In non-blocking mode, return immediately with 0 if the buffer is ready or
13607+ * -EAGAIN if the buffer is in the QUEUED or ACTIVE state.
13608+ *
13609+ * In blocking mode, wait (interruptibly but with no timeout) on the buffer wait
13610+ * queue using the same condition.
13611+ */
13612+static int isp_video_buffer_wait(struct isp_video_buffer *buf, int nonblocking)
13613+{
13614+ if (nonblocking) {
13615+ return (buf->state != ISP_BUF_STATE_QUEUED &&
13616+ buf->state != ISP_BUF_STATE_ACTIVE)
13617+ ? 0 : -EAGAIN;
13618+ }
13619+
13620+ return wait_event_interruptible(buf->wait,
13621+ buf->state != ISP_BUF_STATE_QUEUED &&
13622+ buf->state != ISP_BUF_STATE_ACTIVE);
13623+}
13624+
13625+/* -----------------------------------------------------------------------------
13626+ * Queue management
13627+ */
13628+
13629+/*
13630+ * isp_video_queue_free - Free video buffers memory
13631+ *
13632+ * Buffers can only be freed if the queue isn't streaming and if no buffer is
13633+ * mapped to userspace. Return -EBUSY if those conditions aren't statisfied.
13634+ *
13635+ * This function must be called with the queue lock held.
13636+ */
13637+static int isp_video_queue_free(struct isp_video_queue *queue)
13638+{
13639+ unsigned int i;
13640+
13641+ if (queue->streaming)
13642+ return -EBUSY;
13643+
13644+ for (i = 0; i < queue->count; ++i) {
13645+ if (queue->buffers[i]->vma_use_count != 0)
13646+ return -EBUSY;
13647+ }
13648+
13649+ for (i = 0; i < queue->count; ++i) {
13650+ struct isp_video_buffer *buf = queue->buffers[i];
13651+
13652+ isp_video_buffer_cleanup(buf);
13653+
13654+ vfree(buf->vaddr);
13655+ buf->vaddr = NULL;
13656+
13657+ kfree(buf);
13658+ queue->buffers[i] = NULL;
13659+ }
13660+
13661+ INIT_LIST_HEAD(&queue->queue);
13662+ queue->count = 0;
13663+ return 0;
13664+}
13665+
13666+/*
13667+ * isp_video_queue_alloc - Allocate video buffers memory
13668+ *
13669+ * This function must be called with the queue lock held.
13670+ */
13671+static int isp_video_queue_alloc(struct isp_video_queue *queue,
13672+ unsigned int nbuffers,
13673+ unsigned int size, enum v4l2_memory memory)
13674+{
13675+ struct isp_video_buffer *buf;
13676+ unsigned int i;
13677+ void *mem;
13678+ int ret;
13679+
13680+ /* Start by freeing the buffers. */
13681+ ret = isp_video_queue_free(queue);
13682+ if (ret < 0)
13683+ return ret;
13684+
13685+ /* Bail out of no buffers should be allocated. */
13686+ if (nbuffers == 0)
13687+ return 0;
13688+
13689+ /* Initialize the allocated buffers. */
13690+ for (i = 0; i < nbuffers; ++i) {
13691+ buf = kzalloc(queue->bufsize, GFP_KERNEL);
13692+ if (buf == NULL)
13693+ break;
13694+
13695+ if (memory == V4L2_MEMORY_MMAP) {
13696+ /* Allocate video buffers memory for mmap mode. Align
13697+ * the size to the page size.
13698+ */
13699+ mem = vmalloc_32_user(PAGE_ALIGN(size));
13700+ if (mem == NULL) {
13701+ kfree(buf);
13702+ break;
13703+ }
13704+
13705+ buf->vbuf.m.offset = i * PAGE_ALIGN(size);
13706+ buf->vaddr = mem;
13707+ }
13708+
13709+ buf->vbuf.index = i;
13710+ buf->vbuf.length = size;
13711+ buf->vbuf.type = queue->type;
13712+ buf->vbuf.field = V4L2_FIELD_NONE;
13713+ buf->vbuf.memory = memory;
13714+
13715+ buf->queue = queue;
13716+ init_waitqueue_head(&buf->wait);
13717+
13718+ queue->buffers[i] = buf;
13719+ }
13720+
13721+ if (i == 0)
13722+ return -ENOMEM;
13723+
13724+ queue->count = i;
13725+ return nbuffers;
13726+}
13727+
13728+/**
13729+ * omap3isp_video_queue_cleanup - Clean up the video buffers queue
13730+ * @queue: Video buffers queue
13731+ *
13732+ * Free all allocated resources and clean up the video buffers queue. The queue
13733+ * must not be busy (no ongoing video stream) and buffers must have been
13734+ * unmapped.
13735+ *
13736+ * Return 0 on success or -EBUSY if the queue is busy or buffers haven't been
13737+ * unmapped.
13738+ */
13739+int omap3isp_video_queue_cleanup(struct isp_video_queue *queue)
13740+{
13741+ return isp_video_queue_free(queue);
13742+}
13743+
13744+/**
13745+ * omap3isp_video_queue_init - Initialize the video buffers queue
13746+ * @queue: Video buffers queue
13747+ * @type: V4L2 buffer type (capture or output)
13748+ * @ops: Driver-specific queue operations
13749+ * @dev: Device used for DMA operations
13750+ * @bufsize: Size of the driver-specific buffer structure
13751+ *
13752+ * Initialize the video buffers queue with the supplied parameters.
13753+ *
13754+ * The queue type must be one of V4L2_BUF_TYPE_VIDEO_CAPTURE or
13755+ * V4L2_BUF_TYPE_VIDEO_OUTPUT. Other buffer types are not supported yet.
13756+ *
13757+ * Buffer objects will be allocated using the given buffer size to allow room
13758+ * for driver-specific fields. Driver-specific buffer structures must start
13759+ * with a struct isp_video_buffer field. Drivers with no driver-specific buffer
13760+ * structure must pass the size of the isp_video_buffer structure in the bufsize
13761+ * parameter.
13762+ *
13763+ * Return 0 on success.
13764+ */
13765+int omap3isp_video_queue_init(struct isp_video_queue *queue,
13766+ enum v4l2_buf_type type,
13767+ const struct isp_video_queue_operations *ops,
13768+ struct device *dev, unsigned int bufsize)
13769+{
13770+ INIT_LIST_HEAD(&queue->queue);
13771+ mutex_init(&queue->lock);
13772+ spin_lock_init(&queue->irqlock);
13773+
13774+ queue->type = type;
13775+ queue->ops = ops;
13776+ queue->dev = dev;
13777+ queue->bufsize = bufsize;
13778+
13779+ return 0;
13780+}
13781+
13782+/* -----------------------------------------------------------------------------
13783+ * V4L2 operations
13784+ */
13785+
13786+/**
13787+ * omap3isp_video_queue_reqbufs - Allocate video buffers memory
13788+ *
13789+ * This function is intended to be used as a VIDIOC_REQBUFS ioctl handler. It
13790+ * allocated video buffer objects and, for MMAP buffers, buffer memory.
13791+ *
13792+ * If the number of buffers is 0, all buffers are freed and the function returns
13793+ * without performing any allocation.
13794+ *
13795+ * If the number of buffers is not 0, currently allocated buffers (if any) are
13796+ * freed and the requested number of buffers are allocated. Depending on
13797+ * driver-specific requirements and on memory availability, a number of buffer
13798+ * smaller or bigger than requested can be allocated. This isn't considered as
13799+ * an error.
13800+ *
13801+ * Return 0 on success or one of the following error codes:
13802+ *
13803+ * -EINVAL if the buffer type or index are invalid
13804+ * -EBUSY if the queue is busy (streaming or buffers mapped)
13805+ * -ENOMEM if the buffers can't be allocated due to an out-of-memory condition
13806+ */
13807+int omap3isp_video_queue_reqbufs(struct isp_video_queue *queue,
13808+ struct v4l2_requestbuffers *rb)
13809+{
13810+ unsigned int nbuffers = rb->count;
13811+ unsigned int size;
13812+ int ret;
13813+
13814+ if (rb->type != queue->type)
13815+ return -EINVAL;
13816+
13817+ queue->ops->queue_prepare(queue, &nbuffers, &size);
13818+ if (size == 0)
13819+ return -EINVAL;
13820+
13821+ nbuffers = min_t(unsigned int, nbuffers, ISP_VIDEO_MAX_BUFFERS);
13822+
13823+ mutex_lock(&queue->lock);
13824+
13825+ ret = isp_video_queue_alloc(queue, nbuffers, size, rb->memory);
13826+ if (ret < 0)
13827+ goto done;
13828+
13829+ rb->count = ret;
13830+ ret = 0;
13831+
13832+done:
13833+ mutex_unlock(&queue->lock);
13834+ return ret;
13835+}
13836+
13837+/**
13838+ * omap3isp_video_queue_querybuf - Query the status of a buffer in a queue
13839+ *
13840+ * This function is intended to be used as a VIDIOC_QUERYBUF ioctl handler. It
13841+ * returns the status of a given video buffer.
13842+ *
13843+ * Return 0 on success or -EINVAL if the buffer type or index are invalid.
13844+ */
13845+int omap3isp_video_queue_querybuf(struct isp_video_queue *queue,
13846+ struct v4l2_buffer *vbuf)
13847+{
13848+ struct isp_video_buffer *buf;
13849+ int ret = 0;
13850+
13851+ if (vbuf->type != queue->type)
13852+ return -EINVAL;
13853+
13854+ mutex_lock(&queue->lock);
13855+
13856+ if (vbuf->index >= queue->count) {
13857+ ret = -EINVAL;
13858+ goto done;
13859+ }
13860+
13861+ buf = queue->buffers[vbuf->index];
13862+ isp_video_buffer_query(buf, vbuf);
13863+
13864+done:
13865+ mutex_unlock(&queue->lock);
13866+ return ret;
13867+}
13868+
13869+/**
13870+ * omap3isp_video_queue_qbuf - Queue a buffer
13871+ *
13872+ * This function is intended to be used as a VIDIOC_QBUF ioctl handler.
13873+ *
13874+ * The v4l2_buffer structure passed from userspace is first sanity tested. If
13875+ * sane, the buffer is then processed and added to the main queue and, if the
13876+ * queue is streaming, to the IRQ queue.
13877+ *
13878+ * Before being enqueued, USERPTR buffers are checked for address changes. If
13879+ * the buffer has a different userspace address, the old memory area is unlocked
13880+ * and the new memory area is locked.
13881+ */
13882+int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
13883+ struct v4l2_buffer *vbuf)
13884+{
13885+ struct isp_video_buffer *buf;
13886+ unsigned long flags;
13887+ int ret = -EINVAL;
13888+
13889+ if (vbuf->type != queue->type)
13890+ goto done;
13891+
13892+ mutex_lock(&queue->lock);
13893+
13894+ if (vbuf->index >= queue->count)
13895+ goto done;
13896+
13897+ buf = queue->buffers[vbuf->index];
13898+
13899+ if (vbuf->memory != buf->vbuf.memory)
13900+ goto done;
13901+
13902+ if (buf->state != ISP_BUF_STATE_IDLE)
13903+ goto done;
13904+
13905+ if (vbuf->memory == V4L2_MEMORY_USERPTR &&
13906+ vbuf->m.userptr != buf->vbuf.m.userptr) {
13907+ isp_video_buffer_cleanup(buf);
13908+ buf->vbuf.m.userptr = vbuf->m.userptr;
13909+ buf->prepared = 0;
13910+ }
13911+
13912+ if (!buf->prepared) {
13913+ ret = isp_video_buffer_prepare(buf);
13914+ if (ret < 0)
13915+ goto done;
13916+ buf->prepared = 1;
13917+ }
13918+
13919+ isp_video_buffer_cache_sync(buf);
13920+
13921+ buf->state = ISP_BUF_STATE_QUEUED;
13922+ list_add_tail(&buf->stream, &queue->queue);
13923+
13924+ if (queue->streaming) {
13925+ spin_lock_irqsave(&queue->irqlock, flags);
13926+ queue->ops->buffer_queue(buf);
13927+ spin_unlock_irqrestore(&queue->irqlock, flags);
13928+ }
13929+
13930+ ret = 0;
13931+
13932+done:
13933+ mutex_unlock(&queue->lock);
13934+ return ret;
13935+}
13936+
13937+/**
13938+ * omap3isp_video_queue_dqbuf - Dequeue a buffer
13939+ *
13940+ * This function is intended to be used as a VIDIOC_DQBUF ioctl handler.
13941+ *
13942+ * The v4l2_buffer structure passed from userspace is first sanity tested. If
13943+ * sane, the buffer is then processed and added to the main queue and, if the
13944+ * queue is streaming, to the IRQ queue.
13945+ *
13946+ * Before being enqueued, USERPTR buffers are checked for address changes. If
13947+ * the buffer has a different userspace address, the old memory area is unlocked
13948+ * and the new memory area is locked.
13949+ */
13950+int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
13951+ struct v4l2_buffer *vbuf, int nonblocking)
13952+{
13953+ struct isp_video_buffer *buf;
13954+ int ret;
13955+
13956+ if (vbuf->type != queue->type)
13957+ return -EINVAL;
13958+
13959+ mutex_lock(&queue->lock);
13960+
13961+ if (list_empty(&queue->queue)) {
13962+ ret = -EINVAL;
13963+ goto done;
13964+ }
13965+
13966+ buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
13967+ ret = isp_video_buffer_wait(buf, nonblocking);
13968+ if (ret < 0)
13969+ goto done;
13970+
13971+ list_del(&buf->stream);
13972+
13973+ isp_video_buffer_query(buf, vbuf);
13974+ buf->state = ISP_BUF_STATE_IDLE;
13975+ vbuf->flags &= ~V4L2_BUF_FLAG_QUEUED;
13976+
13977+done:
13978+ mutex_unlock(&queue->lock);
13979+ return ret;
13980+}
13981+
13982+/**
13983+ * omap3isp_video_queue_streamon - Start streaming
13984+ *
13985+ * This function is intended to be used as a VIDIOC_STREAMON ioctl handler. It
13986+ * starts streaming on the queue and calls the buffer_queue operation for all
13987+ * queued buffers.
13988+ *
13989+ * Return 0 on success.
13990+ */
13991+int omap3isp_video_queue_streamon(struct isp_video_queue *queue)
13992+{
13993+ struct isp_video_buffer *buf;
13994+ unsigned long flags;
13995+
13996+ mutex_lock(&queue->lock);
13997+
13998+ if (queue->streaming)
13999+ goto done;
14000+
14001+ queue->streaming = 1;
14002+
14003+ spin_lock_irqsave(&queue->irqlock, flags);
14004+ list_for_each_entry(buf, &queue->queue, stream)
14005+ queue->ops->buffer_queue(buf);
14006+ spin_unlock_irqrestore(&queue->irqlock, flags);
14007+
14008+done:
14009+ mutex_unlock(&queue->lock);
14010+ return 0;
14011+}
14012+
14013+/**
14014+ * omap3isp_video_queue_streamoff - Stop streaming
14015+ *
14016+ * This function is intended to be used as a VIDIOC_STREAMOFF ioctl handler. It
14017+ * stops streaming on the queue and wakes up all the buffers.
14018+ *
14019+ * Drivers must stop the hardware and synchronize with interrupt handlers and/or
14020+ * delayed works before calling this function to make sure no buffer will be
14021+ * touched by the driver and/or hardware.
14022+ */
14023+void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
14024+{
14025+ struct isp_video_buffer *buf;
14026+ unsigned long flags;
14027+ unsigned int i;
14028+
14029+ mutex_lock(&queue->lock);
14030+
14031+ if (!queue->streaming)
14032+ goto done;
14033+
14034+ queue->streaming = 0;
14035+
14036+ spin_lock_irqsave(&queue->irqlock, flags);
14037+ for (i = 0; i < queue->count; ++i) {
14038+ buf = queue->buffers[i];
14039+
14040+ if (buf->state == ISP_BUF_STATE_ACTIVE)
14041+ wake_up(&buf->wait);
14042+
14043+ buf->state = ISP_BUF_STATE_IDLE;
14044+ }
14045+ spin_unlock_irqrestore(&queue->irqlock, flags);
14046+
14047+ INIT_LIST_HEAD(&queue->queue);
14048+
14049+done:
14050+ mutex_unlock(&queue->lock);
14051+}
14052+
14053+/**
14054+ * omap3isp_video_queue_discard_done - Discard all buffers marked as DONE
14055+ *
14056+ * This function is intended to be used with suspend/resume operations. It
14057+ * discards all 'done' buffers as they would be too old to be requested after
14058+ * resume.
14059+ *
14060+ * Drivers must stop the hardware and synchronize with interrupt handlers and/or
14061+ * delayed works before calling this function to make sure no buffer will be
14062+ * touched by the driver and/or hardware.
14063+ */
14064+void omap3isp_video_queue_discard_done(struct isp_video_queue *queue)
14065+{
14066+ struct isp_video_buffer *buf;
14067+ unsigned int i;
14068+
14069+ mutex_lock(&queue->lock);
14070+
14071+ if (!queue->streaming)
14072+ goto done;
14073+
14074+ for (i = 0; i < queue->count; ++i) {
14075+ buf = queue->buffers[i];
14076+
14077+ if (buf->state == ISP_BUF_STATE_DONE)
14078+ buf->state = ISP_BUF_STATE_ERROR;
14079+ }
14080+
14081+done:
14082+ mutex_unlock(&queue->lock);
14083+}
14084+
14085+static void isp_video_queue_vm_open(struct vm_area_struct *vma)
14086+{
14087+ struct isp_video_buffer *buf = vma->vm_private_data;
14088+
14089+ buf->vma_use_count++;
14090+}
14091+
14092+static void isp_video_queue_vm_close(struct vm_area_struct *vma)
14093+{
14094+ struct isp_video_buffer *buf = vma->vm_private_data;
14095+
14096+ buf->vma_use_count--;
14097+}
14098+
14099+static const struct vm_operations_struct isp_video_queue_vm_ops = {
14100+ .open = isp_video_queue_vm_open,
14101+ .close = isp_video_queue_vm_close,
14102+};
14103+
14104+/**
14105+ * omap3isp_video_queue_mmap - Map buffers to userspace
14106+ *
14107+ * This function is intended to be used as an mmap() file operation handler. It
14108+ * maps a buffer to userspace based on the VMA offset.
14109+ *
14110+ * Only buffers of memory type MMAP are supported.
14111+ */
14112+int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
14113+ struct vm_area_struct *vma)
14114+{
14115+ struct isp_video_buffer *uninitialized_var(buf);
14116+ unsigned long size;
14117+ unsigned int i;
14118+ int ret = 0;
14119+
14120+ mutex_lock(&queue->lock);
14121+
14122+ for (i = 0; i < queue->count; ++i) {
14123+ buf = queue->buffers[i];
14124+ if ((buf->vbuf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
14125+ break;
14126+ }
14127+
14128+ if (i == queue->count) {
14129+ ret = -EINVAL;
14130+ goto done;
14131+ }
14132+
14133+ size = vma->vm_end - vma->vm_start;
14134+
14135+ if (buf->vbuf.memory != V4L2_MEMORY_MMAP ||
14136+ size != PAGE_ALIGN(buf->vbuf.length)) {
14137+ ret = -EINVAL;
14138+ goto done;
14139+ }
14140+
14141+ ret = remap_vmalloc_range(vma, buf->vaddr, 0);
14142+ if (ret < 0)
14143+ goto done;
14144+
14145+ vma->vm_ops = &isp_video_queue_vm_ops;
14146+ vma->vm_private_data = buf;
14147+ isp_video_queue_vm_open(vma);
14148+
14149+done:
14150+ mutex_unlock(&queue->lock);
14151+ return ret;
14152+}
14153+
14154+/**
14155+ * omap3isp_video_queue_poll - Poll video queue state
14156+ *
14157+ * This function is intended to be used as a poll() file operation handler. It
14158+ * polls the state of the video buffer at the front of the queue and returns an
14159+ * events mask.
14160+ *
14161+ * If no buffer is present at the front of the queue, POLLERR is returned.
14162+ */
14163+unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
14164+ struct file *file, poll_table *wait)
14165+{
14166+ struct isp_video_buffer *buf;
14167+ unsigned int mask = 0;
14168+
14169+ mutex_lock(&queue->lock);
14170+ if (list_empty(&queue->queue)) {
14171+ mask |= POLLERR;
14172+ goto done;
14173+ }
14174+ buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
14175+
14176+ poll_wait(file, &buf->wait, wait);
14177+ if (buf->state == ISP_BUF_STATE_DONE ||
14178+ buf->state == ISP_BUF_STATE_ERROR) {
14179+ if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
14180+ mask |= POLLIN | POLLRDNORM;
14181+ else
14182+ mask |= POLLOUT | POLLWRNORM;
14183+ }
14184+
14185+done:
14186+ mutex_unlock(&queue->lock);
14187+ return mask;
14188+}
14189diff --git a/drivers/media/video/isp/ispqueue.h b/drivers/media/video/isp/ispqueue.h
14190new file mode 100644
14191index 0000000..f05aba3
14192--- /dev/null
14193+++ b/drivers/media/video/isp/ispqueue.h
14194@@ -0,0 +1,185 @@
14195+/*
14196+ * ispqueue.h
14197+ *
14198+ * TI OMAP3 ISP - Video buffers queue handling
14199+ *
14200+ * Copyright (C) 2010 Nokia Corporation
14201+ *
14202+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
14203+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
14204+ *
14205+ * This program is free software; you can redistribute it and/or modify
14206+ * it under the terms of the GNU General Public License version 2 as
14207+ * published by the Free Software Foundation.
14208+ *
14209+ * This program is distributed in the hope that it will be useful, but
14210+ * WITHOUT ANY WARRANTY; without even the implied warranty of
14211+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14212+ * General Public License for more details.
14213+ *
14214+ * You should have received a copy of the GNU General Public License
14215+ * along with this program; if not, write to the Free Software
14216+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
14217+ * 02110-1301 USA
14218+ */
14219+
14220+#ifndef OMAP3_ISP_QUEUE_H
14221+#define OMAP3_ISP_QUEUE_H
14222+
14223+#include <linux/kernel.h>
14224+#include <linux/list.h>
14225+#include <linux/mutex.h>
14226+#include <linux/videodev2.h>
14227+#include <linux/wait.h>
14228+
14229+struct isp_video_queue;
14230+struct page;
14231+struct scatterlist;
14232+
14233+#define ISP_VIDEO_MAX_BUFFERS 16
14234+
14235+/**
14236+ * enum isp_video_buffer_state - ISP video buffer state
14237+ * @ISP_BUF_STATE_IDLE: The buffer is under userspace control (dequeued
14238+ * or not queued yet).
14239+ * @ISP_BUF_STATE_QUEUED: The buffer has been queued but isn't used by the
14240+ * device yet.
14241+ * @ISP_BUF_STATE_ACTIVE: The buffer is in use for an active video transfer.
14242+ * @ISP_BUF_STATE_ERROR: The device is done with the buffer and an error
14243+ * occured. For capture device the buffer likely contains corrupted data or
14244+ * no data at all.
14245+ * @ISP_BUF_STATE_DONE: The device is done with the buffer and no error occured.
14246+ * For capture devices the buffer contains valid data.
14247+ */
14248+enum isp_video_buffer_state {
14249+ ISP_BUF_STATE_IDLE,
14250+ ISP_BUF_STATE_QUEUED,
14251+ ISP_BUF_STATE_ACTIVE,
14252+ ISP_BUF_STATE_ERROR,
14253+ ISP_BUF_STATE_DONE,
14254+};
14255+
14256+/**
14257+ * struct isp_video_buffer - ISP video buffer
14258+ * @vma_use_count: Number of times the buffer is mmap'ed to userspace
14259+ * @stream: List head for insertion into main queue
14260+ * @queue: ISP buffers queue this buffer belongs to
14261+ * @prepared: Whether the buffer has been prepared
14262+ * @vaddr: Memory virtual address (for kernel buffers)
14263+ * @vm_flags: Buffer VMA flags (for userspace buffers)
14264+ * @offset: Offset inside the first page (for userspace buffers)
14265+ * @npages: Number of pages (for userspace buffers)
14266+ * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
14267+ * @paddr: Memory physical address (for userspace VM_PFNMAP buffers)
14268+ * @sglen: Number of elements in the scatter list (for non-VM_PFNMAP buffers)
14269+ * @sglist: Scatter list (for non-VM_PFNMAP buffers)
14270+ * @vbuf: V4L2 buffer
14271+ * @irqlist: List head for insertion into IRQ queue
14272+ * @state: Current buffer state
14273+ * @wait: Wait queue to signal buffer completion
14274+ */
14275+struct isp_video_buffer {
14276+ unsigned long vma_use_count;
14277+ struct list_head stream;
14278+ struct isp_video_queue *queue;
14279+ unsigned int prepared:1;
14280+
14281+ /* For kernel buffers. */
14282+ void *vaddr;
14283+
14284+ /* For userspace buffers. */
14285+ unsigned long vm_flags;
14286+ unsigned long offset;
14287+ unsigned int npages;
14288+ struct page **pages;
14289+ dma_addr_t paddr;
14290+
14291+ /* For all buffers except VM_PFNMAP. */
14292+ unsigned int sglen;
14293+ struct scatterlist *sglist;
14294+
14295+ /* Touched by the interrupt handler. */
14296+ struct v4l2_buffer vbuf;
14297+ struct list_head irqlist;
14298+ enum isp_video_buffer_state state;
14299+ wait_queue_head_t wait;
14300+};
14301+
14302+#define to_isp_video_buffer(vb) container_of(vb, struct isp_video_buffer, vb)
14303+
14304+/**
14305+ * struct isp_video_queue_operations - Driver-specific operations
14306+ * @queue_prepare: Called before allocating buffers. Drivers should clamp the
14307+ * number of buffers according to their requirements, and must return the
14308+ * buffer size in bytes.
14309+ * @buffer_prepare: Called the first time a buffer is queued, or after changing
14310+ * the userspace memory address for a USERPTR buffer, with the queue lock
14311+ * held. Drivers should perform device-specific buffer preparation (such as
14312+ * mapping the buffer memory in an IOMMU). This operation is optional.
14313+ * @buffer_queue: Called when a buffer is being added to the queue with the
14314+ * queue irqlock spinlock held.
14315+ * @buffer_cleanup: Called before freeing buffers, or before changing the
14316+ * userspace memory address for a USERPTR buffer, with the queue lock held.
14317+ * Drivers must perform cleanup operations required to undo the
14318+ * buffer_prepare call. This operation is optional.
14319+ */
14320+struct isp_video_queue_operations {
14321+ void (*queue_prepare)(struct isp_video_queue *queue,
14322+ unsigned int *nbuffers, unsigned int *size);
14323+ int (*buffer_prepare)(struct isp_video_buffer *buf);
14324+ void (*buffer_queue)(struct isp_video_buffer *buf);
14325+ void (*buffer_cleanup)(struct isp_video_buffer *buf);
14326+};
14327+
14328+/**
14329+ * struct isp_video_queue - ISP video buffers queue
14330+ * @type: Type of video buffers handled by this queue
14331+ * @ops: Queue operations
14332+ * @dev: Device used for DMA operations
14333+ * @bufsize: Size of a driver-specific buffer object
14334+ * @count: Number of currently allocated buffers
14335+ * @buffers: ISP video buffers
14336+ * @lock: Mutex to protect access to the buffers, main queue and state
14337+ * @irqlock: Spinlock to protect access to the IRQ queue
14338+ * @streaming: Queue state, indicates whether the queue is streaming
14339+ * @queue: List of all queued buffers
14340+ */
14341+struct isp_video_queue {
14342+ enum v4l2_buf_type type;
14343+ const struct isp_video_queue_operations *ops;
14344+ struct device *dev;
14345+ unsigned int bufsize;
14346+
14347+ unsigned int count;
14348+ struct isp_video_buffer *buffers[ISP_VIDEO_MAX_BUFFERS];
14349+ struct mutex lock;
14350+ spinlock_t irqlock;
14351+
14352+ unsigned int streaming:1;
14353+
14354+ struct list_head queue;
14355+};
14356+
14357+int omap3isp_video_queue_cleanup(struct isp_video_queue *queue);
14358+int omap3isp_video_queue_init(struct isp_video_queue *queue,
14359+ enum v4l2_buf_type type,
14360+ const struct isp_video_queue_operations *ops,
14361+ struct device *dev, unsigned int bufsize);
14362+
14363+int omap3isp_video_queue_reqbufs(struct isp_video_queue *queue,
14364+ struct v4l2_requestbuffers *rb);
14365+int omap3isp_video_queue_querybuf(struct isp_video_queue *queue,
14366+ struct v4l2_buffer *vbuf);
14367+int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
14368+ struct v4l2_buffer *vbuf);
14369+int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
14370+ struct v4l2_buffer *vbuf, int nonblocking);
14371+int omap3isp_video_queue_streamon(struct isp_video_queue *queue);
14372+void omap3isp_video_queue_streamoff(struct isp_video_queue *queue);
14373+void omap3isp_video_queue_discard_done(struct isp_video_queue *queue);
14374+int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
14375+ struct vm_area_struct *vma);
14376+unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
14377+ struct file *file, poll_table *wait);
14378+
14379+#endif /* OMAP3_ISP_QUEUE_H */
14380diff --git a/drivers/media/video/isp/ispreg.h b/drivers/media/video/isp/ispreg.h
14381new file mode 100644
14382index 0000000..e78c7e3
14383--- /dev/null
14384+++ b/drivers/media/video/isp/ispreg.h
14385@@ -0,0 +1,1589 @@
14386+/*
14387+ * ispreg.h
14388+ *
14389+ * TI OMAP3 ISP - Registers definitions
14390+ *
14391+ * Copyright (C) 2010 Nokia Corporation
14392+ * Copyright (C) 2009 Texas Instruments, Inc
14393+ *
14394+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
14395+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
14396+ *
14397+ * This program is free software; you can redistribute it and/or modify
14398+ * it under the terms of the GNU General Public License version 2 as
14399+ * published by the Free Software Foundation.
14400+ *
14401+ * This program is distributed in the hope that it will be useful, but
14402+ * WITHOUT ANY WARRANTY; without even the implied warranty of
14403+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14404+ * General Public License for more details.
14405+ *
14406+ * You should have received a copy of the GNU General Public License
14407+ * along with this program; if not, write to the Free Software
14408+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
14409+ * 02110-1301 USA
14410+ */
14411+
14412+#ifndef OMAP3_ISP_REG_H
14413+#define OMAP3_ISP_REG_H
14414+
14415+#include <plat/omap34xx.h>
14416+
14417+
14418+#define CM_CAM_MCLK_HZ 172800000 /* Hz */
14419+
14420+/* ISP Submodules offset */
14421+
14422+#define OMAP3ISP_REG_BASE OMAP3430_ISP_BASE
14423+#define OMAP3ISP_REG(offset) (OMAP3ISP_REG_BASE + (offset))
14424+
14425+#define OMAP3ISP_CCP2_REG_OFFSET 0x0400
14426+#define OMAP3ISP_CCP2_REG_BASE (OMAP3ISP_REG_BASE + \
14427+ OMAP3ISP_CCP2_REG_OFFSET)
14428+#define OMAP3ISP_CCP2_REG(offset) (OMAP3ISP_CCP2_REG_BASE + (offset))
14429+
14430+#define OMAP3ISP_CCDC_REG_OFFSET 0x0600
14431+#define OMAP3ISP_CCDC_REG_BASE (OMAP3ISP_REG_BASE + \
14432+ OMAP3ISP_CCDC_REG_OFFSET)
14433+#define OMAP3ISP_CCDC_REG(offset) (OMAP3ISP_CCDC_REG_BASE + (offset))
14434+
14435+#define OMAP3ISP_HIST_REG_OFFSET 0x0A00
14436+#define OMAP3ISP_HIST_REG_BASE (OMAP3ISP_REG_BASE + \
14437+ OMAP3ISP_HIST_REG_OFFSET)
14438+#define OMAP3ISP_HIST_REG(offset) (OMAP3ISP_HIST_REG_BASE + (offset))
14439+
14440+#define OMAP3ISP_H3A_REG_OFFSET 0x0C00
14441+#define OMAP3ISP_H3A_REG_BASE (OMAP3ISP_REG_BASE + \
14442+ OMAP3ISP_H3A_REG_OFFSET)
14443+#define OMAP3ISP_H3A_REG(offset) (OMAP3ISP_H3A_REG_BASE + (offset))
14444+
14445+#define OMAP3ISP_PREV_REG_OFFSET 0x0E00
14446+#define OMAP3ISP_PREV_REG_BASE (OMAP3ISP_REG_BASE + \
14447+ OMAP3ISP_PREV_REG_OFFSET)
14448+#define OMAP3ISP_PREV_REG(offset) (OMAP3ISP_PREV_REG_BASE + (offset))
14449+
14450+#define OMAP3ISP_RESZ_REG_OFFSET 0x1000
14451+#define OMAP3ISP_RESZ_REG_BASE (OMAP3ISP_REG_BASE + \
14452+ OMAP3ISP_RESZ_REG_OFFSET)
14453+#define OMAP3ISP_RESZ_REG(offset) (OMAP3ISP_RESZ_REG_BASE + (offset))
14454+
14455+#define OMAP3ISP_SBL_REG_OFFSET 0x1200
14456+#define OMAP3ISP_SBL_REG_BASE (OMAP3ISP_REG_BASE + \
14457+ OMAP3ISP_SBL_REG_OFFSET)
14458+#define OMAP3ISP_SBL_REG(offset) (OMAP3ISP_SBL_REG_BASE + (offset))
14459+
14460+#define OMAP3ISP_CSI2A_REGS1_REG_OFFSET 0x1800
14461+#define OMAP3ISP_CSI2A_REGS1_REG_BASE (OMAP3ISP_REG_BASE + \
14462+ OMAP3ISP_CSI2A_REGS1_REG_OFFSET)
14463+#define OMAP3ISP_CSI2A_REGS1_REG(offset) \
14464+ (OMAP3ISP_CSI2A_REGS1_REG_BASE + (offset))
14465+
14466+#define OMAP3ISP_CSIPHY2_REG_OFFSET 0x1970
14467+#define OMAP3ISP_CSIPHY2_REG_BASE (OMAP3ISP_REG_BASE + \
14468+ OMAP3ISP_CSIPHY2_REG_OFFSET)
14469+#define OMAP3ISP_CSIPHY2_REG(offset) (OMAP3ISP_CSIPHY2_REG_BASE + (offset))
14470+
14471+#define OMAP3ISP_CSI2A_REGS2_REG_OFFSET 0x19C0
14472+#define OMAP3ISP_CSI2A_REGS2_REG_BASE (OMAP3ISP_REG_BASE + \
14473+ OMAP3ISP_CSI2A_REGS2_REG_OFFSET)
14474+#define OMAP3ISP_CSI2A_REGS2_REG(offset) \
14475+ (OMAP3ISP_CSI2A_REGS2_REG_BASE + (offset))
14476+
14477+#define OMAP3ISP_CSI2C_REGS1_REG_OFFSET 0x1C00
14478+#define OMAP3ISP_CSI2C_REGS1_REG_BASE (OMAP3ISP_REG_BASE + \
14479+ OMAP3ISP_CSI2C_REGS1_REG_OFFSET)
14480+#define OMAP3ISP_CSI2C_REGS1_REG(offset) \
14481+ (OMAP3ISP_CSI2C_REGS1_REG_BASE + (offset))
14482+
14483+#define OMAP3ISP_CSIPHY1_REG_OFFSET 0x1D70
14484+#define OMAP3ISP_CSIPHY1_REG_BASE (OMAP3ISP_REG_BASE + \
14485+ OMAP3ISP_CSIPHY1_REG_OFFSET)
14486+#define OMAP3ISP_CSIPHY1_REG(offset) (OMAP3ISP_CSIPHY1_REG_BASE + (offset))
14487+
14488+#define OMAP3ISP_CSI2C_REGS2_REG_OFFSET 0x1DC0
14489+#define OMAP3ISP_CSI2C_REGS2_REG_BASE (OMAP3ISP_REG_BASE + \
14490+ OMAP3ISP_CSI2C_REGS2_REG_OFFSET)
14491+#define OMAP3ISP_CSI2C_REGS2_REG(offset) \
14492+ (OMAP3ISP_CSI2C_REGS2_REG_BASE + (offset))
14493+
14494+/* ISP module register offset */
14495+
14496+#define ISP_REVISION (0x000)
14497+#define ISP_SYSCONFIG (0x004)
14498+#define ISP_SYSSTATUS (0x008)
14499+#define ISP_IRQ0ENABLE (0x00C)
14500+#define ISP_IRQ0STATUS (0x010)
14501+#define ISP_IRQ1ENABLE (0x014)
14502+#define ISP_IRQ1STATUS (0x018)
14503+#define ISP_TCTRL_GRESET_LENGTH (0x030)
14504+#define ISP_TCTRL_PSTRB_REPLAY (0x034)
14505+#define ISP_CTRL (0x040)
14506+#define ISP_SECURE (0x044)
14507+#define ISP_TCTRL_CTRL (0x050)
14508+#define ISP_TCTRL_FRAME (0x054)
14509+#define ISP_TCTRL_PSTRB_DELAY (0x058)
14510+#define ISP_TCTRL_STRB_DELAY (0x05C)
14511+#define ISP_TCTRL_SHUT_DELAY (0x060)
14512+#define ISP_TCTRL_PSTRB_LENGTH (0x064)
14513+#define ISP_TCTRL_STRB_LENGTH (0x068)
14514+#define ISP_TCTRL_SHUT_LENGTH (0x06C)
14515+#define ISP_PING_PONG_ADDR (0x070)
14516+#define ISP_PING_PONG_MEM_RANGE (0x074)
14517+#define ISP_PING_PONG_BUF_SIZE (0x078)
14518+
14519+/* CCP2 receiver registers */
14520+
14521+#define ISPCCP2_REVISION (0x000)
14522+#define ISPCCP2_SYSCONFIG (0x004)
14523+#define ISPCCP2_SYSCONFIG_SOFT_RESET (1 << 1)
14524+#define ISPCCP2_SYSCONFIG_AUTO_IDLE 0x1
14525+#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT 12
14526+#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_FORCE \
14527+ (0x0 << ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
14528+#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_NO \
14529+ (0x1 << ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
14530+#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SMART \
14531+ (0x2 << ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
14532+#define ISPCCP2_SYSSTATUS (0x008)
14533+#define ISPCCP2_SYSSTATUS_RESET_DONE (1 << 0)
14534+#define ISPCCP2_LC01_IRQENABLE (0x00C)
14535+#define ISPCCP2_LC01_IRQSTATUS (0x010)
14536+#define ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ (1 << 11)
14537+#define ISPCCP2_LC01_IRQSTATUS_LC0_LE_IRQ (1 << 10)
14538+#define ISPCCP2_LC01_IRQSTATUS_LC0_LS_IRQ (1 << 9)
14539+#define ISPCCP2_LC01_IRQSTATUS_LC0_FE_IRQ (1 << 8)
14540+#define ISPCCP2_LC01_IRQSTATUS_LC0_COUNT_IRQ (1 << 7)
14541+#define ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ (1 << 5)
14542+#define ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ (1 << 4)
14543+#define ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ (1 << 3)
14544+#define ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ (1 << 2)
14545+#define ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ (1 << 1)
14546+#define ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ (1 << 0)
14547+
14548+#define ISPCCP2_LC23_IRQENABLE (0x014)
14549+#define ISPCCP2_LC23_IRQSTATUS (0x018)
14550+#define ISPCCP2_LCM_IRQENABLE (0x02C)
14551+#define ISPCCP2_LCM_IRQSTATUS_EOF_IRQ (1 << 0)
14552+#define ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ (1 << 1)
14553+#define ISPCCP2_LCM_IRQSTATUS (0x030)
14554+#define ISPCCP2_CTRL (0x040)
14555+#define ISPCCP2_CTRL_IF_EN (1 << 0)
14556+#define ISPCCP2_CTRL_PHY_SEL (1 << 1)
14557+#define ISPCCP2_CTRL_PHY_SEL_CLOCK (0 << 1)
14558+#define ISPCCP2_CTRL_PHY_SEL_STROBE (1 << 1)
14559+#define ISPCCP2_CTRL_PHY_SEL_MASK 0x1
14560+#define ISPCCP2_CTRL_PHY_SEL_SHIFT 1
14561+#define ISPCCP2_CTRL_IO_OUT_SEL (1 << 2)
14562+#define ISPCCP2_CTRL_MODE (1 << 4)
14563+#define ISPCCP2_CTRL_VP_CLK_FORCE_ON (1 << 9)
14564+#define ISPCCP2_CTRL_INV (1 << 10)
14565+#define ISPCCP2_CTRL_INV_MASK 0x1
14566+#define ISPCCP2_CTRL_INV_SHIFT 10
14567+#define ISPCCP2_CTRL_VP_ONLY_EN (1 << 11)
14568+#define ISPCCP2_CTRL_VP_CLK_POL (1 << 12)
14569+#define ISPCCP2_CTRL_VPCLK_DIV_SHIFT 15
14570+#define ISPCCP2_CTRL_VPCLK_DIV_MASK 0x1ffff /* [31:15] */
14571+#define ISPCCP2_CTRL_VP_OUT_CTRL_SHIFT 8 /* 3430 bits */
14572+#define ISPCCP2_CTRL_VP_OUT_CTRL_MASK 0x3 /* 3430 bits */
14573+#define ISPCCP2_DBG (0x044)
14574+#define ISPCCP2_GNQ (0x048)
14575+#define ISPCCP2_LCx_CTRL(x) ((0x050)+0x30*(x))
14576+#define ISPCCP2_LCx_CTRL_CHAN_EN (1 << 0)
14577+#define ISPCCP2_LCx_CTRL_CRC_EN (1 << 19)
14578+#define ISPCCP2_LCx_CTRL_CRC_MASK 0x1
14579+#define ISPCCP2_LCx_CTRL_CRC_SHIFT 2
14580+#define ISPCCP2_LCx_CTRL_CRC_SHIFT_15_0 19
14581+#define ISPCCP2_LCx_CTRL_REGION_EN (1 << 1)
14582+#define ISPCCP2_LCx_CTRL_REGION_MASK 0x1
14583+#define ISPCCP2_LCx_CTRL_REGION_SHIFT 1
14584+#define ISPCCP2_LCx_CTRL_FORMAT_MASK_15_0 0x3f
14585+#define ISPCCP2_LCx_CTRL_FORMAT_SHIFT_15_0 0x2
14586+#define ISPCCP2_LCx_CTRL_FORMAT_MASK 0x1f
14587+#define ISPCCP2_LCx_CTRL_FORMAT_SHIFT 0x3
14588+#define ISPCCP2_LCx_CODE(x) ((0x054)+0x30*(x))
14589+#define ISPCCP2_LCx_STAT_START(x) ((0x058)+0x30*(x))
14590+#define ISPCCP2_LCx_STAT_SIZE(x) ((0x05C)+0x30*(x))
14591+#define ISPCCP2_LCx_SOF_ADDR(x) ((0x060)+0x30*(x))
14592+#define ISPCCP2_LCx_EOF_ADDR(x) ((0x064)+0x30*(x))
14593+#define ISPCCP2_LCx_DAT_START(x) ((0x068)+0x30*(x))
14594+#define ISPCCP2_LCx_DAT_SIZE(x) ((0x06C)+0x30*(x))
14595+#define ISPCCP2_LCx_DAT_MASK 0xFFF
14596+#define ISPCCP2_LCx_DAT_SHIFT 16
14597+#define ISPCCP2_LCx_DAT_PING_ADDR(x) ((0x070)+0x30*(x))
14598+#define ISPCCP2_LCx_DAT_PONG_ADDR(x) ((0x074)+0x30*(x))
14599+#define ISPCCP2_LCx_DAT_OFST(x) ((0x078)+0x30*(x))
14600+#define ISPCCP2_LCM_CTRL (0x1D0)
14601+#define ISPCCP2_LCM_CTRL_CHAN_EN (1 << 0)
14602+#define ISPCCP2_LCM_CTRL_DST_PORT (1 << 2)
14603+#define ISPCCP2_LCM_CTRL_DST_PORT_SHIFT 2
14604+#define ISPCCP2_LCM_CTRL_READ_THROTTLE_SHIFT 3
14605+#define ISPCCP2_LCM_CTRL_READ_THROTTLE_MASK 0x11
14606+#define ISPCCP2_LCM_CTRL_BURST_SIZE_SHIFT 5
14607+#define ISPCCP2_LCM_CTRL_BURST_SIZE_MASK 0x7
14608+#define ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT 16
14609+#define ISPCCP2_LCM_CTRL_SRC_FORMAT_MASK 0x7
14610+#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_SHIFT 20
14611+#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_MASK 0x3
14612+#define ISPCCP2_LCM_CTRL_SRC_DPCM_PRED (1 << 22)
14613+#define ISPCCP2_LCM_CTRL_SRC_PACK (1 << 23)
14614+#define ISPCCP2_LCM_CTRL_DST_FORMAT_SHIFT 24
14615+#define ISPCCP2_LCM_CTRL_DST_FORMAT_MASK 0x7
14616+#define ISPCCP2_LCM_VSIZE (0x1D4)
14617+#define ISPCCP2_LCM_VSIZE_SHIFT 16
14618+#define ISPCCP2_LCM_HSIZE (0x1D8)
14619+#define ISPCCP2_LCM_HSIZE_SHIFT 16
14620+#define ISPCCP2_LCM_PREFETCH (0x1DC)
14621+#define ISPCCP2_LCM_PREFETCH_SHIFT 3
14622+#define ISPCCP2_LCM_SRC_ADDR (0x1E0)
14623+#define ISPCCP2_LCM_SRC_OFST (0x1E4)
14624+#define ISPCCP2_LCM_DST_ADDR (0x1E8)
14625+#define ISPCCP2_LCM_DST_OFST (0x1EC)
14626+
14627+/* CCDC module register offset */
14628+
14629+#define ISPCCDC_PID (0x000)
14630+#define ISPCCDC_PCR (0x004)
14631+#define ISPCCDC_SYN_MODE (0x008)
14632+#define ISPCCDC_HD_VD_WID (0x00C)
14633+#define ISPCCDC_PIX_LINES (0x010)
14634+#define ISPCCDC_HORZ_INFO (0x014)
14635+#define ISPCCDC_VERT_START (0x018)
14636+#define ISPCCDC_VERT_LINES (0x01C)
14637+#define ISPCCDC_CULLING (0x020)
14638+#define ISPCCDC_HSIZE_OFF (0x024)
14639+#define ISPCCDC_SDOFST (0x028)
14640+#define ISPCCDC_SDR_ADDR (0x02C)
14641+#define ISPCCDC_CLAMP (0x030)
14642+#define ISPCCDC_DCSUB (0x034)
14643+#define ISPCCDC_COLPTN (0x038)
14644+#define ISPCCDC_BLKCMP (0x03C)
14645+#define ISPCCDC_FPC (0x040)
14646+#define ISPCCDC_FPC_ADDR (0x044)
14647+#define ISPCCDC_VDINT (0x048)
14648+#define ISPCCDC_ALAW (0x04C)
14649+#define ISPCCDC_REC656IF (0x050)
14650+#define ISPCCDC_CFG (0x054)
14651+#define ISPCCDC_FMTCFG (0x058)
14652+#define ISPCCDC_FMT_HORZ (0x05C)
14653+#define ISPCCDC_FMT_VERT (0x060)
14654+#define ISPCCDC_FMT_ADDR0 (0x064)
14655+#define ISPCCDC_FMT_ADDR1 (0x068)
14656+#define ISPCCDC_FMT_ADDR2 (0x06C)
14657+#define ISPCCDC_FMT_ADDR3 (0x070)
14658+#define ISPCCDC_FMT_ADDR4 (0x074)
14659+#define ISPCCDC_FMT_ADDR5 (0x078)
14660+#define ISPCCDC_FMT_ADDR6 (0x07C)
14661+#define ISPCCDC_FMT_ADDR7 (0x080)
14662+#define ISPCCDC_PRGEVEN0 (0x084)
14663+#define ISPCCDC_PRGEVEN1 (0x088)
14664+#define ISPCCDC_PRGODD0 (0x08C)
14665+#define ISPCCDC_PRGODD1 (0x090)
14666+#define ISPCCDC_VP_OUT (0x094)
14667+
14668+#define ISPCCDC_LSC_CONFIG (0x098)
14669+#define ISPCCDC_LSC_INITIAL (0x09C)
14670+#define ISPCCDC_LSC_TABLE_BASE (0x0A0)
14671+#define ISPCCDC_LSC_TABLE_OFFSET (0x0A4)
14672+
14673+/* SBL */
14674+#define ISPSBL_PCR 0x4
14675+#define ISPSBL_PCR_H3A_AEAWB_WBL_OVF (1 << 16)
14676+#define ISPSBL_PCR_H3A_AF_WBL_OVF (1 << 17)
14677+#define ISPSBL_PCR_RSZ4_WBL_OVF (1 << 18)
14678+#define ISPSBL_PCR_RSZ3_WBL_OVF (1 << 19)
14679+#define ISPSBL_PCR_RSZ2_WBL_OVF (1 << 20)
14680+#define ISPSBL_PCR_RSZ1_WBL_OVF (1 << 21)
14681+#define ISPSBL_PCR_PRV_WBL_OVF (1 << 22)
14682+#define ISPSBL_PCR_CCDC_WBL_OVF (1 << 23)
14683+#define ISPSBL_PCR_CCDCPRV_2_RSZ_OVF (1 << 24)
14684+#define ISPSBL_PCR_CSIA_WBL_OVF (1 << 25)
14685+#define ISPSBL_PCR_CSIB_WBL_OVF (1 << 26)
14686+#define ISPSBL_CCDC_WR_0 (0x028)
14687+#define ISPSBL_CCDC_WR_0_DATA_READY (1 << 21)
14688+#define ISPSBL_CCDC_WR_1 (0x02C)
14689+#define ISPSBL_CCDC_WR_2 (0x030)
14690+#define ISPSBL_CCDC_WR_3 (0x034)
14691+
14692+#define ISPSBL_SDR_REQ_EXP 0xF8
14693+#define ISPSBL_SDR_REQ_HIST_EXP_SHIFT 0
14694+#define ISPSBL_SDR_REQ_HIST_EXP_MASK (0x3FF)
14695+#define ISPSBL_SDR_REQ_RSZ_EXP_SHIFT 10
14696+#define ISPSBL_SDR_REQ_RSZ_EXP_MASK (0x3FF << ISPSBL_SDR_REQ_RSZ_EXP_SHIFT)
14697+#define ISPSBL_SDR_REQ_PRV_EXP_SHIFT 20
14698+#define ISPSBL_SDR_REQ_PRV_EXP_MASK (0x3FF << ISPSBL_SDR_REQ_PRV_EXP_SHIFT)
14699+
14700+/* Histogram registers */
14701+#define ISPHIST_PID (0x000)
14702+#define ISPHIST_PCR (0x004)
14703+#define ISPHIST_CNT (0x008)
14704+#define ISPHIST_WB_GAIN (0x00C)
14705+#define ISPHIST_R0_HORZ (0x010)
14706+#define ISPHIST_R0_VERT (0x014)
14707+#define ISPHIST_R1_HORZ (0x018)
14708+#define ISPHIST_R1_VERT (0x01C)
14709+#define ISPHIST_R2_HORZ (0x020)
14710+#define ISPHIST_R2_VERT (0x024)
14711+#define ISPHIST_R3_HORZ (0x028)
14712+#define ISPHIST_R3_VERT (0x02C)
14713+#define ISPHIST_ADDR (0x030)
14714+#define ISPHIST_DATA (0x034)
14715+#define ISPHIST_RADD (0x038)
14716+#define ISPHIST_RADD_OFF (0x03C)
14717+#define ISPHIST_H_V_INFO (0x040)
14718+
14719+/* H3A module registers */
14720+#define ISPH3A_PID (0x000)
14721+#define ISPH3A_PCR (0x004)
14722+#define ISPH3A_AEWWIN1 (0x04C)
14723+#define ISPH3A_AEWINSTART (0x050)
14724+#define ISPH3A_AEWINBLK (0x054)
14725+#define ISPH3A_AEWSUBWIN (0x058)
14726+#define ISPH3A_AEWBUFST (0x05C)
14727+#define ISPH3A_AFPAX1 (0x008)
14728+#define ISPH3A_AFPAX2 (0x00C)
14729+#define ISPH3A_AFPAXSTART (0x010)
14730+#define ISPH3A_AFIIRSH (0x014)
14731+#define ISPH3A_AFBUFST (0x018)
14732+#define ISPH3A_AFCOEF010 (0x01C)
14733+#define ISPH3A_AFCOEF032 (0x020)
14734+#define ISPH3A_AFCOEF054 (0x024)
14735+#define ISPH3A_AFCOEF076 (0x028)
14736+#define ISPH3A_AFCOEF098 (0x02C)
14737+#define ISPH3A_AFCOEF0010 (0x030)
14738+#define ISPH3A_AFCOEF110 (0x034)
14739+#define ISPH3A_AFCOEF132 (0x038)
14740+#define ISPH3A_AFCOEF154 (0x03C)
14741+#define ISPH3A_AFCOEF176 (0x040)
14742+#define ISPH3A_AFCOEF198 (0x044)
14743+#define ISPH3A_AFCOEF1010 (0x048)
14744+
14745+#define ISPPRV_PCR (0x004)
14746+#define ISPPRV_HORZ_INFO (0x008)
14747+#define ISPPRV_VERT_INFO (0x00C)
14748+#define ISPPRV_RSDR_ADDR (0x010)
14749+#define ISPPRV_RADR_OFFSET (0x014)
14750+#define ISPPRV_DSDR_ADDR (0x018)
14751+#define ISPPRV_DRKF_OFFSET (0x01C)
14752+#define ISPPRV_WSDR_ADDR (0x020)
14753+#define ISPPRV_WADD_OFFSET (0x024)
14754+#define ISPPRV_AVE (0x028)
14755+#define ISPPRV_HMED (0x02C)
14756+#define ISPPRV_NF (0x030)
14757+#define ISPPRV_WB_DGAIN (0x034)
14758+#define ISPPRV_WBGAIN (0x038)
14759+#define ISPPRV_WBSEL (0x03C)
14760+#define ISPPRV_CFA (0x040)
14761+#define ISPPRV_BLKADJOFF (0x044)
14762+#define ISPPRV_RGB_MAT1 (0x048)
14763+#define ISPPRV_RGB_MAT2 (0x04C)
14764+#define ISPPRV_RGB_MAT3 (0x050)
14765+#define ISPPRV_RGB_MAT4 (0x054)
14766+#define ISPPRV_RGB_MAT5 (0x058)
14767+#define ISPPRV_RGB_OFF1 (0x05C)
14768+#define ISPPRV_RGB_OFF2 (0x060)
14769+#define ISPPRV_CSC0 (0x064)
14770+#define ISPPRV_CSC1 (0x068)
14771+#define ISPPRV_CSC2 (0x06C)
14772+#define ISPPRV_CSC_OFFSET (0x070)
14773+#define ISPPRV_CNT_BRT (0x074)
14774+#define ISPPRV_CSUP (0x078)
14775+#define ISPPRV_SETUP_YC (0x07C)
14776+#define ISPPRV_SET_TBL_ADDR (0x080)
14777+#define ISPPRV_SET_TBL_DATA (0x084)
14778+#define ISPPRV_CDC_THR0 (0x090)
14779+#define ISPPRV_CDC_THR1 (ISPPRV_CDC_THR0 + (0x4))
14780+#define ISPPRV_CDC_THR2 (ISPPRV_CDC_THR0 + (0x4) * 2)
14781+#define ISPPRV_CDC_THR3 (ISPPRV_CDC_THR0 + (0x4) * 3)
14782+
14783+#define ISPPRV_REDGAMMA_TABLE_ADDR 0x0000
14784+#define ISPPRV_GREENGAMMA_TABLE_ADDR 0x0400
14785+#define ISPPRV_BLUEGAMMA_TABLE_ADDR 0x0800
14786+#define ISPPRV_NF_TABLE_ADDR 0x0C00
14787+#define ISPPRV_YENH_TABLE_ADDR 0x1000
14788+#define ISPPRV_CFA_TABLE_ADDR 0x1400
14789+
14790+#define ISPPRV_MAXOUTPUT_WIDTH 1280
14791+#define ISPPRV_MAXOUTPUT_WIDTH_ES2 3300
14792+#define ISPPRV_MAXOUTPUT_WIDTH_3630 4096
14793+#define ISPRSZ_MIN_OUTPUT 64
14794+#define ISPRSZ_MAX_OUTPUT 3312
14795+
14796+/* Resizer module register offset */
14797+#define ISPRSZ_PID (0x000)
14798+#define ISPRSZ_PCR (0x004)
14799+#define ISPRSZ_CNT (0x008)
14800+#define ISPRSZ_OUT_SIZE (0x00C)
14801+#define ISPRSZ_IN_START (0x010)
14802+#define ISPRSZ_IN_SIZE (0x014)
14803+#define ISPRSZ_SDR_INADD (0x018)
14804+#define ISPRSZ_SDR_INOFF (0x01C)
14805+#define ISPRSZ_SDR_OUTADD (0x020)
14806+#define ISPRSZ_SDR_OUTOFF (0x024)
14807+#define ISPRSZ_HFILT10 (0x028)
14808+#define ISPRSZ_HFILT32 (0x02C)
14809+#define ISPRSZ_HFILT54 (0x030)
14810+#define ISPRSZ_HFILT76 (0x034)
14811+#define ISPRSZ_HFILT98 (0x038)
14812+#define ISPRSZ_HFILT1110 (0x03C)
14813+#define ISPRSZ_HFILT1312 (0x040)
14814+#define ISPRSZ_HFILT1514 (0x044)
14815+#define ISPRSZ_HFILT1716 (0x048)
14816+#define ISPRSZ_HFILT1918 (0x04C)
14817+#define ISPRSZ_HFILT2120 (0x050)
14818+#define ISPRSZ_HFILT2322 (0x054)
14819+#define ISPRSZ_HFILT2524 (0x058)
14820+#define ISPRSZ_HFILT2726 (0x05C)
14821+#define ISPRSZ_HFILT2928 (0x060)
14822+#define ISPRSZ_HFILT3130 (0x064)
14823+#define ISPRSZ_VFILT10 (0x068)
14824+#define ISPRSZ_VFILT32 (0x06C)
14825+#define ISPRSZ_VFILT54 (0x070)
14826+#define ISPRSZ_VFILT76 (0x074)
14827+#define ISPRSZ_VFILT98 (0x078)
14828+#define ISPRSZ_VFILT1110 (0x07C)
14829+#define ISPRSZ_VFILT1312 (0x080)
14830+#define ISPRSZ_VFILT1514 (0x084)
14831+#define ISPRSZ_VFILT1716 (0x088)
14832+#define ISPRSZ_VFILT1918 (0x08C)
14833+#define ISPRSZ_VFILT2120 (0x090)
14834+#define ISPRSZ_VFILT2322 (0x094)
14835+#define ISPRSZ_VFILT2524 (0x098)
14836+#define ISPRSZ_VFILT2726 (0x09C)
14837+#define ISPRSZ_VFILT2928 (0x0A0)
14838+#define ISPRSZ_VFILT3130 (0x0A4)
14839+#define ISPRSZ_YENH (0x0A8)
14840+
14841+#define ISP_INT_CLR 0xFF113F11
14842+#define ISPPRV_PCR_EN 1
14843+#define ISPPRV_PCR_BUSY (1 << 1)
14844+#define ISPPRV_PCR_SOURCE (1 << 2)
14845+#define ISPPRV_PCR_ONESHOT (1 << 3)
14846+#define ISPPRV_PCR_WIDTH (1 << 4)
14847+#define ISPPRV_PCR_INVALAW (1 << 5)
14848+#define ISPPRV_PCR_DRKFEN (1 << 6)
14849+#define ISPPRV_PCR_DRKFCAP (1 << 7)
14850+#define ISPPRV_PCR_HMEDEN (1 << 8)
14851+#define ISPPRV_PCR_NFEN (1 << 9)
14852+#define ISPPRV_PCR_CFAEN (1 << 10)
14853+#define ISPPRV_PCR_CFAFMT_SHIFT 11
14854+#define ISPPRV_PCR_CFAFMT_MASK 0x7800
14855+#define ISPPRV_PCR_CFAFMT_BAYER (0 << 11)
14856+#define ISPPRV_PCR_CFAFMT_SONYVGA (1 << 11)
14857+#define ISPPRV_PCR_CFAFMT_RGBFOVEON (2 << 11)
14858+#define ISPPRV_PCR_CFAFMT_DNSPL (3 << 11)
14859+#define ISPPRV_PCR_CFAFMT_HONEYCOMB (4 << 11)
14860+#define ISPPRV_PCR_CFAFMT_RRGGBBFOVEON (5 << 11)
14861+#define ISPPRV_PCR_YNENHEN (1 << 15)
14862+#define ISPPRV_PCR_SUPEN (1 << 16)
14863+#define ISPPRV_PCR_YCPOS_SHIFT 17
14864+#define ISPPRV_PCR_YCPOS_YCrYCb (0 << 17)
14865+#define ISPPRV_PCR_YCPOS_YCbYCr (1 << 17)
14866+#define ISPPRV_PCR_YCPOS_CbYCrY (2 << 17)
14867+#define ISPPRV_PCR_YCPOS_CrYCbY (3 << 17)
14868+#define ISPPRV_PCR_RSZPORT (1 << 19)
14869+#define ISPPRV_PCR_SDRPORT (1 << 20)
14870+#define ISPPRV_PCR_SCOMP_EN (1 << 21)
14871+#define ISPPRV_PCR_SCOMP_SFT_SHIFT (22)
14872+#define ISPPRV_PCR_SCOMP_SFT_MASK (7 << 22)
14873+#define ISPPRV_PCR_GAMMA_BYPASS (1 << 26)
14874+#define ISPPRV_PCR_DCOREN (1 << 27)
14875+#define ISPPRV_PCR_DCCOUP (1 << 28)
14876+#define ISPPRV_PCR_DRK_FAIL (1 << 31)
14877+
14878+#define ISPPRV_HORZ_INFO_EPH_SHIFT 0
14879+#define ISPPRV_HORZ_INFO_EPH_MASK 0x3fff
14880+#define ISPPRV_HORZ_INFO_SPH_SHIFT 16
14881+#define ISPPRV_HORZ_INFO_SPH_MASK 0x3fff0
14882+
14883+#define ISPPRV_VERT_INFO_ELV_SHIFT 0
14884+#define ISPPRV_VERT_INFO_ELV_MASK 0x3fff
14885+#define ISPPRV_VERT_INFO_SLV_SHIFT 16
14886+#define ISPPRV_VERT_INFO_SLV_MASK 0x3fff0
14887+
14888+#define ISPPRV_AVE_EVENDIST_SHIFT 2
14889+#define ISPPRV_AVE_EVENDIST_1 0x0
14890+#define ISPPRV_AVE_EVENDIST_2 0x1
14891+#define ISPPRV_AVE_EVENDIST_3 0x2
14892+#define ISPPRV_AVE_EVENDIST_4 0x3
14893+#define ISPPRV_AVE_ODDDIST_SHIFT 4
14894+#define ISPPRV_AVE_ODDDIST_1 0x0
14895+#define ISPPRV_AVE_ODDDIST_2 0x1
14896+#define ISPPRV_AVE_ODDDIST_3 0x2
14897+#define ISPPRV_AVE_ODDDIST_4 0x3
14898+
14899+#define ISPPRV_HMED_THRESHOLD_SHIFT 0
14900+#define ISPPRV_HMED_EVENDIST (1 << 8)
14901+#define ISPPRV_HMED_ODDDIST (1 << 9)
14902+
14903+#define ISPPRV_WBGAIN_COEF0_SHIFT 0
14904+#define ISPPRV_WBGAIN_COEF1_SHIFT 8
14905+#define ISPPRV_WBGAIN_COEF2_SHIFT 16
14906+#define ISPPRV_WBGAIN_COEF3_SHIFT 24
14907+
14908+#define ISPPRV_WBSEL_COEF0 0x0
14909+#define ISPPRV_WBSEL_COEF1 0x1
14910+#define ISPPRV_WBSEL_COEF2 0x2
14911+#define ISPPRV_WBSEL_COEF3 0x3
14912+
14913+#define ISPPRV_WBSEL_N0_0_SHIFT 0
14914+#define ISPPRV_WBSEL_N0_1_SHIFT 2
14915+#define ISPPRV_WBSEL_N0_2_SHIFT 4
14916+#define ISPPRV_WBSEL_N0_3_SHIFT 6
14917+#define ISPPRV_WBSEL_N1_0_SHIFT 8
14918+#define ISPPRV_WBSEL_N1_1_SHIFT 10
14919+#define ISPPRV_WBSEL_N1_2_SHIFT 12
14920+#define ISPPRV_WBSEL_N1_3_SHIFT 14
14921+#define ISPPRV_WBSEL_N2_0_SHIFT 16
14922+#define ISPPRV_WBSEL_N2_1_SHIFT 18
14923+#define ISPPRV_WBSEL_N2_2_SHIFT 20
14924+#define ISPPRV_WBSEL_N2_3_SHIFT 22
14925+#define ISPPRV_WBSEL_N3_0_SHIFT 24
14926+#define ISPPRV_WBSEL_N3_1_SHIFT 26
14927+#define ISPPRV_WBSEL_N3_2_SHIFT 28
14928+#define ISPPRV_WBSEL_N3_3_SHIFT 30
14929+
14930+#define ISPPRV_CFA_GRADTH_HOR_SHIFT 0
14931+#define ISPPRV_CFA_GRADTH_VER_SHIFT 8
14932+
14933+#define ISPPRV_BLKADJOFF_B_SHIFT 0
14934+#define ISPPRV_BLKADJOFF_G_SHIFT 8
14935+#define ISPPRV_BLKADJOFF_R_SHIFT 16
14936+
14937+#define ISPPRV_RGB_MAT1_MTX_RR_SHIFT 0
14938+#define ISPPRV_RGB_MAT1_MTX_GR_SHIFT 16
14939+
14940+#define ISPPRV_RGB_MAT2_MTX_BR_SHIFT 0
14941+#define ISPPRV_RGB_MAT2_MTX_RG_SHIFT 16
14942+
14943+#define ISPPRV_RGB_MAT3_MTX_GG_SHIFT 0
14944+#define ISPPRV_RGB_MAT3_MTX_BG_SHIFT 16
14945+
14946+#define ISPPRV_RGB_MAT4_MTX_RB_SHIFT 0
14947+#define ISPPRV_RGB_MAT4_MTX_GB_SHIFT 16
14948+
14949+#define ISPPRV_RGB_MAT5_MTX_BB_SHIFT 0
14950+
14951+#define ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT 0
14952+#define ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT 16
14953+
14954+#define ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT 0
14955+
14956+#define ISPPRV_CSC0_RY_SHIFT 0
14957+#define ISPPRV_CSC0_GY_SHIFT 10
14958+#define ISPPRV_CSC0_BY_SHIFT 20
14959+
14960+#define ISPPRV_CSC1_RCB_SHIFT 0
14961+#define ISPPRV_CSC1_GCB_SHIFT 10
14962+#define ISPPRV_CSC1_BCB_SHIFT 20
14963+
14964+#define ISPPRV_CSC2_RCR_SHIFT 0
14965+#define ISPPRV_CSC2_GCR_SHIFT 10
14966+#define ISPPRV_CSC2_BCR_SHIFT 20
14967+
14968+#define ISPPRV_CSC_OFFSET_CR_SHIFT 0
14969+#define ISPPRV_CSC_OFFSET_CB_SHIFT 8
14970+#define ISPPRV_CSC_OFFSET_Y_SHIFT 16
14971+
14972+#define ISPPRV_CNT_BRT_BRT_SHIFT 0
14973+#define ISPPRV_CNT_BRT_CNT_SHIFT 8
14974+
14975+#define ISPPRV_CONTRAST_MAX 0x10
14976+#define ISPPRV_CONTRAST_MIN 0xFF
14977+#define ISPPRV_BRIGHT_MIN 0x00
14978+#define ISPPRV_BRIGHT_MAX 0xFF
14979+
14980+#define ISPPRV_CSUP_CSUPG_SHIFT 0
14981+#define ISPPRV_CSUP_THRES_SHIFT 8
14982+#define ISPPRV_CSUP_HPYF_SHIFT 16
14983+
14984+#define ISPPRV_SETUP_YC_MINC_SHIFT 0
14985+#define ISPPRV_SETUP_YC_MAXC_SHIFT 8
14986+#define ISPPRV_SETUP_YC_MINY_SHIFT 16
14987+#define ISPPRV_SETUP_YC_MAXY_SHIFT 24
14988+#define ISPPRV_YC_MAX 0xFF
14989+#define ISPPRV_YC_MIN 0x0
14990+
14991+/* Define bit fields within selected registers */
14992+#define ISP_REVISION_SHIFT 0
14993+
14994+#define ISP_SYSCONFIG_AUTOIDLE (1 << 0)
14995+#define ISP_SYSCONFIG_SOFTRESET (1 << 1)
14996+#define ISP_SYSCONFIG_MIDLEMODE_SHIFT 12
14997+#define ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY 0x0
14998+#define ISP_SYSCONFIG_MIDLEMODE_NOSTANBY 0x1
14999+#define ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY 0x2
15000+
15001+#define ISP_SYSSTATUS_RESETDONE 0
15002+
15003+#define IRQ0ENABLE_CSIA_IRQ (1 << 0)
15004+#define IRQ0ENABLE_CSIC_IRQ (1 << 1)
15005+#define IRQ0ENABLE_CCP2_LCM_IRQ (1 << 3)
15006+#define IRQ0ENABLE_CCP2_LC0_IRQ (1 << 4)
15007+#define IRQ0ENABLE_CCP2_LC1_IRQ (1 << 5)
15008+#define IRQ0ENABLE_CCP2_LC2_IRQ (1 << 6)
15009+#define IRQ0ENABLE_CCP2_LC3_IRQ (1 << 7)
15010+#define IRQ0ENABLE_CSIB_IRQ (IRQ0ENABLE_CCP2_LCM_IRQ | \
15011+ IRQ0ENABLE_CCP2_LC0_IRQ | \
15012+ IRQ0ENABLE_CCP2_LC1_IRQ | \
15013+ IRQ0ENABLE_CCP2_LC2_IRQ | \
15014+ IRQ0ENABLE_CCP2_LC3_IRQ)
15015+
15016+#define IRQ0ENABLE_CCDC_VD0_IRQ (1 << 8)
15017+#define IRQ0ENABLE_CCDC_VD1_IRQ (1 << 9)
15018+#define IRQ0ENABLE_CCDC_VD2_IRQ (1 << 10)
15019+#define IRQ0ENABLE_CCDC_ERR_IRQ (1 << 11)
15020+#define IRQ0ENABLE_H3A_AF_DONE_IRQ (1 << 12)
15021+#define IRQ0ENABLE_H3A_AWB_DONE_IRQ (1 << 13)
15022+#define IRQ0ENABLE_HIST_DONE_IRQ (1 << 16)
15023+#define IRQ0ENABLE_CCDC_LSC_DONE_IRQ (1 << 17)
15024+#define IRQ0ENABLE_CCDC_LSC_PREF_COMP_IRQ (1 << 18)
15025+#define IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ (1 << 19)
15026+#define IRQ0ENABLE_PRV_DONE_IRQ (1 << 20)
15027+#define IRQ0ENABLE_RSZ_DONE_IRQ (1 << 24)
15028+#define IRQ0ENABLE_OVF_IRQ (1 << 25)
15029+#define IRQ0ENABLE_PING_IRQ (1 << 26)
15030+#define IRQ0ENABLE_PONG_IRQ (1 << 27)
15031+#define IRQ0ENABLE_MMU_ERR_IRQ (1 << 28)
15032+#define IRQ0ENABLE_OCP_ERR_IRQ (1 << 29)
15033+#define IRQ0ENABLE_SEC_ERR_IRQ (1 << 30)
15034+#define IRQ0ENABLE_HS_VS_IRQ (1 << 31)
15035+
15036+#define IRQ0STATUS_CSIA_IRQ (1 << 0)
15037+#define IRQ0STATUS_CSI2C_IRQ (1 << 1)
15038+#define IRQ0STATUS_CCP2_LCM_IRQ (1 << 3)
15039+#define IRQ0STATUS_CCP2_LC0_IRQ (1 << 4)
15040+#define IRQ0STATUS_CSIB_IRQ (IRQ0STATUS_CCP2_LCM_IRQ | \
15041+ IRQ0STATUS_CCP2_LC0_IRQ)
15042+
15043+#define IRQ0STATUS_CSIB_LC1_IRQ (1 << 5)
15044+#define IRQ0STATUS_CSIB_LC2_IRQ (1 << 6)
15045+#define IRQ0STATUS_CSIB_LC3_IRQ (1 << 7)
15046+#define IRQ0STATUS_CCDC_VD0_IRQ (1 << 8)
15047+#define IRQ0STATUS_CCDC_VD1_IRQ (1 << 9)
15048+#define IRQ0STATUS_CCDC_VD2_IRQ (1 << 10)
15049+#define IRQ0STATUS_CCDC_ERR_IRQ (1 << 11)
15050+#define IRQ0STATUS_H3A_AF_DONE_IRQ (1 << 12)
15051+#define IRQ0STATUS_H3A_AWB_DONE_IRQ (1 << 13)
15052+#define IRQ0STATUS_HIST_DONE_IRQ (1 << 16)
15053+#define IRQ0STATUS_CCDC_LSC_DONE_IRQ (1 << 17)
15054+#define IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ (1 << 18)
15055+#define IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ (1 << 19)
15056+#define IRQ0STATUS_PRV_DONE_IRQ (1 << 20)
15057+#define IRQ0STATUS_RSZ_DONE_IRQ (1 << 24)
15058+#define IRQ0STATUS_OVF_IRQ (1 << 25)
15059+#define IRQ0STATUS_PING_IRQ (1 << 26)
15060+#define IRQ0STATUS_PONG_IRQ (1 << 27)
15061+#define IRQ0STATUS_MMU_ERR_IRQ (1 << 28)
15062+#define IRQ0STATUS_OCP_ERR_IRQ (1 << 29)
15063+#define IRQ0STATUS_SEC_ERR_IRQ (1 << 30)
15064+#define IRQ0STATUS_HS_VS_IRQ (1 << 31)
15065+
15066+#define TCTRL_GRESET_LEN 0
15067+
15068+#define TCTRL_PSTRB_REPLAY_DELAY 0
15069+#define TCTRL_PSTRB_REPLAY_COUNTER_SHIFT 25
15070+
15071+#define ISPCTRL_PAR_SER_CLK_SEL_PARALLEL 0x0
15072+#define ISPCTRL_PAR_SER_CLK_SEL_CSIA 0x1
15073+#define ISPCTRL_PAR_SER_CLK_SEL_CSIB 0x2
15074+#define ISPCTRL_PAR_SER_CLK_SEL_CSIC 0x3
15075+#define ISPCTRL_PAR_SER_CLK_SEL_MASK 0x3
15076+
15077+#define ISPCTRL_PAR_BRIDGE_SHIFT 2
15078+#define ISPCTRL_PAR_BRIDGE_DISABLE (0x0 << 2)
15079+#define ISPCTRL_PAR_BRIDGE_LENDIAN (0x2 << 2)
15080+#define ISPCTRL_PAR_BRIDGE_BENDIAN (0x3 << 2)
15081+#define ISPCTRL_PAR_BRIDGE_MASK (0x3 << 2)
15082+
15083+#define ISPCTRL_PAR_CLK_POL_SHIFT 4
15084+#define ISPCTRL_PAR_CLK_POL_INV (1 << 4)
15085+#define ISPCTRL_PING_PONG_EN (1 << 5)
15086+#define ISPCTRL_SHIFT_SHIFT 6
15087+#define ISPCTRL_SHIFT_0 (0x0 << 6)
15088+#define ISPCTRL_SHIFT_2 (0x1 << 6)
15089+#define ISPCTRL_SHIFT_4 (0x2 << 6)
15090+#define ISPCTRL_SHIFT_MASK (0x3 << 6)
15091+
15092+#define ISPCTRL_CCDC_CLK_EN (1 << 8)
15093+#define ISPCTRL_SCMP_CLK_EN (1 << 9)
15094+#define ISPCTRL_H3A_CLK_EN (1 << 10)
15095+#define ISPCTRL_HIST_CLK_EN (1 << 11)
15096+#define ISPCTRL_PREV_CLK_EN (1 << 12)
15097+#define ISPCTRL_RSZ_CLK_EN (1 << 13)
15098+#define ISPCTRL_SYNC_DETECT_SHIFT 14
15099+#define ISPCTRL_SYNC_DETECT_HSFALL (0x0 << ISPCTRL_SYNC_DETECT_SHIFT)
15100+#define ISPCTRL_SYNC_DETECT_HSRISE (0x1 << ISPCTRL_SYNC_DETECT_SHIFT)
15101+#define ISPCTRL_SYNC_DETECT_VSFALL (0x2 << ISPCTRL_SYNC_DETECT_SHIFT)
15102+#define ISPCTRL_SYNC_DETECT_VSRISE (0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
15103+#define ISPCTRL_SYNC_DETECT_MASK (0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
15104+
15105+#define ISPCTRL_CCDC_RAM_EN (1 << 16)
15106+#define ISPCTRL_PREV_RAM_EN (1 << 17)
15107+#define ISPCTRL_SBL_RD_RAM_EN (1 << 18)
15108+#define ISPCTRL_SBL_WR1_RAM_EN (1 << 19)
15109+#define ISPCTRL_SBL_WR0_RAM_EN (1 << 20)
15110+#define ISPCTRL_SBL_AUTOIDLE (1 << 21)
15111+#define ISPCTRL_SBL_SHARED_WPORTC (1 << 26)
15112+#define ISPCTRL_SBL_SHARED_RPORTA (1 << 27)
15113+#define ISPCTRL_SBL_SHARED_RPORTB (1 << 28)
15114+#define ISPCTRL_JPEG_FLUSH (1 << 30)
15115+#define ISPCTRL_CCDC_FLUSH (1 << 31)
15116+
15117+#define ISPSECURE_SECUREMODE 0
15118+
15119+#define ISPTCTRL_CTRL_DIV_LOW 0x0
15120+#define ISPTCTRL_CTRL_DIV_HIGH 0x1
15121+#define ISPTCTRL_CTRL_DIV_BYPASS 0x1F
15122+
15123+#define ISPTCTRL_CTRL_DIVA_SHIFT 0
15124+#define ISPTCTRL_CTRL_DIVA_MASK (0x1F << ISPTCTRL_CTRL_DIVA_SHIFT)
15125+
15126+#define ISPTCTRL_CTRL_DIVB_SHIFT 5
15127+#define ISPTCTRL_CTRL_DIVB_MASK (0x1F << ISPTCTRL_CTRL_DIVB_SHIFT)
15128+
15129+#define ISPTCTRL_CTRL_DIVC_SHIFT 10
15130+#define ISPTCTRL_CTRL_DIVC_NOCLOCK (0x0 << 10)
15131+
15132+#define ISPTCTRL_CTRL_SHUTEN (1 << 21)
15133+#define ISPTCTRL_CTRL_PSTRBEN (1 << 22)
15134+#define ISPTCTRL_CTRL_STRBEN (1 << 23)
15135+#define ISPTCTRL_CTRL_SHUTPOL (1 << 24)
15136+#define ISPTCTRL_CTRL_STRBPSTRBPOL (1 << 26)
15137+
15138+#define ISPTCTRL_CTRL_INSEL_SHIFT 27
15139+#define ISPTCTRL_CTRL_INSEL_PARALLEL (0x0 << 27)
15140+#define ISPTCTRL_CTRL_INSEL_CSIA (0x1 << 27)
15141+#define ISPTCTRL_CTRL_INSEL_CSIB (0x2 << 27)
15142+
15143+#define ISPTCTRL_CTRL_GRESETEn (1 << 29)
15144+#define ISPTCTRL_CTRL_GRESETPOL (1 << 30)
15145+#define ISPTCTRL_CTRL_GRESETDIR (1 << 31)
15146+
15147+#define ISPTCTRL_FRAME_SHUT_SHIFT 0
15148+#define ISPTCTRL_FRAME_PSTRB_SHIFT 6
15149+#define ISPTCTRL_FRAME_STRB_SHIFT 12
15150+
15151+#define ISPCCDC_PID_PREV_SHIFT 0
15152+#define ISPCCDC_PID_CID_SHIFT 8
15153+#define ISPCCDC_PID_TID_SHIFT 16
15154+
15155+#define ISPCCDC_PCR_EN 1
15156+#define ISPCCDC_PCR_BUSY (1 << 1)
15157+
15158+#define ISPCCDC_SYN_MODE_VDHDOUT 0x1
15159+#define ISPCCDC_SYN_MODE_FLDOUT (1 << 1)
15160+#define ISPCCDC_SYN_MODE_VDPOL (1 << 2)
15161+#define ISPCCDC_SYN_MODE_HDPOL (1 << 3)
15162+#define ISPCCDC_SYN_MODE_FLDPOL (1 << 4)
15163+#define ISPCCDC_SYN_MODE_EXWEN (1 << 5)
15164+#define ISPCCDC_SYN_MODE_DATAPOL (1 << 6)
15165+#define ISPCCDC_SYN_MODE_FLDMODE (1 << 7)
15166+#define ISPCCDC_SYN_MODE_DATSIZ_MASK (0x7 << 8)
15167+#define ISPCCDC_SYN_MODE_DATSIZ_8_16 (0x0 << 8)
15168+#define ISPCCDC_SYN_MODE_DATSIZ_12 (0x4 << 8)
15169+#define ISPCCDC_SYN_MODE_DATSIZ_11 (0x5 << 8)
15170+#define ISPCCDC_SYN_MODE_DATSIZ_10 (0x6 << 8)
15171+#define ISPCCDC_SYN_MODE_DATSIZ_8 (0x7 << 8)
15172+#define ISPCCDC_SYN_MODE_PACK8 (1 << 11)
15173+#define ISPCCDC_SYN_MODE_INPMOD_MASK (3 << 12)
15174+#define ISPCCDC_SYN_MODE_INPMOD_RAW (0 << 12)
15175+#define ISPCCDC_SYN_MODE_INPMOD_YCBCR16 (1 << 12)
15176+#define ISPCCDC_SYN_MODE_INPMOD_YCBCR8 (2 << 12)
15177+#define ISPCCDC_SYN_MODE_LPF (1 << 14)
15178+#define ISPCCDC_SYN_MODE_FLDSTAT (1 << 15)
15179+#define ISPCCDC_SYN_MODE_VDHDEN (1 << 16)
15180+#define ISPCCDC_SYN_MODE_WEN (1 << 17)
15181+#define ISPCCDC_SYN_MODE_VP2SDR (1 << 18)
15182+#define ISPCCDC_SYN_MODE_SDR2RSZ (1 << 19)
15183+
15184+#define ISPCCDC_HD_VD_WID_VDW_SHIFT 0
15185+#define ISPCCDC_HD_VD_WID_HDW_SHIFT 16
15186+
15187+#define ISPCCDC_PIX_LINES_HLPRF_SHIFT 0
15188+#define ISPCCDC_PIX_LINES_PPLN_SHIFT 16
15189+
15190+#define ISPCCDC_HORZ_INFO_NPH_SHIFT 0
15191+#define ISPCCDC_HORZ_INFO_NPH_MASK 0xFFFF8000
15192+#define ISPCCDC_HORZ_INFO_SPH_MASK 0x1000FFFF
15193+#define ISPCCDC_HORZ_INFO_SPH_SHIFT 16
15194+
15195+#define ISPCCDC_VERT_START_SLV0_SHIFT 16
15196+#define ISPCCDC_VERT_START_SLV0_MASK 0x1000FFFF
15197+#define ISPCCDC_VERT_START_SLV1_SHIFT 0
15198+
15199+#define ISPCCDC_VERT_LINES_NLV_MASK 0xFFFF8000
15200+#define ISPCCDC_VERT_LINES_NLV_SHIFT 0
15201+
15202+#define ISPCCDC_CULLING_CULV_SHIFT 0
15203+#define ISPCCDC_CULLING_CULHODD_SHIFT 16
15204+#define ISPCCDC_CULLING_CULHEVN_SHIFT 24
15205+
15206+#define ISPCCDC_HSIZE_OFF_SHIFT 0
15207+
15208+#define ISPCCDC_SDOFST_FINV (1 << 14)
15209+#define ISPCCDC_SDOFST_FOFST_1L 0
15210+#define ISPCCDC_SDOFST_FOFST_4L (3 << 12)
15211+#define ISPCCDC_SDOFST_LOFST3_SHIFT 0
15212+#define ISPCCDC_SDOFST_LOFST2_SHIFT 3
15213+#define ISPCCDC_SDOFST_LOFST1_SHIFT 6
15214+#define ISPCCDC_SDOFST_LOFST0_SHIFT 9
15215+#define EVENEVEN 1
15216+#define ODDEVEN 2
15217+#define EVENODD 3
15218+#define ODDODD 4
15219+
15220+#define ISPCCDC_CLAMP_OBGAIN_SHIFT 0
15221+#define ISPCCDC_CLAMP_OBST_SHIFT 10
15222+#define ISPCCDC_CLAMP_OBSLN_SHIFT 25
15223+#define ISPCCDC_CLAMP_OBSLEN_SHIFT 28
15224+#define ISPCCDC_CLAMP_CLAMPEN (1 << 31)
15225+
15226+#define ISPCCDC_COLPTN_R_Ye 0x0
15227+#define ISPCCDC_COLPTN_Gr_Cy 0x1
15228+#define ISPCCDC_COLPTN_Gb_G 0x2
15229+#define ISPCCDC_COLPTN_B_Mg 0x3
15230+#define ISPCCDC_COLPTN_CP0PLC0_SHIFT 0
15231+#define ISPCCDC_COLPTN_CP0PLC1_SHIFT 2
15232+#define ISPCCDC_COLPTN_CP0PLC2_SHIFT 4
15233+#define ISPCCDC_COLPTN_CP0PLC3_SHIFT 6
15234+#define ISPCCDC_COLPTN_CP1PLC0_SHIFT 8
15235+#define ISPCCDC_COLPTN_CP1PLC1_SHIFT 10
15236+#define ISPCCDC_COLPTN_CP1PLC2_SHIFT 12
15237+#define ISPCCDC_COLPTN_CP1PLC3_SHIFT 14
15238+#define ISPCCDC_COLPTN_CP2PLC0_SHIFT 16
15239+#define ISPCCDC_COLPTN_CP2PLC1_SHIFT 18
15240+#define ISPCCDC_COLPTN_CP2PLC2_SHIFT 20
15241+#define ISPCCDC_COLPTN_CP2PLC3_SHIFT 22
15242+#define ISPCCDC_COLPTN_CP3PLC0_SHIFT 24
15243+#define ISPCCDC_COLPTN_CP3PLC1_SHIFT 26
15244+#define ISPCCDC_COLPTN_CP3PLC2_SHIFT 28
15245+#define ISPCCDC_COLPTN_CP3PLC3_SHIFT 30
15246+
15247+#define ISPCCDC_BLKCMP_B_MG_SHIFT 0
15248+#define ISPCCDC_BLKCMP_GB_G_SHIFT 8
15249+#define ISPCCDC_BLKCMP_GR_CY_SHIFT 16
15250+#define ISPCCDC_BLKCMP_R_YE_SHIFT 24
15251+
15252+#define ISPCCDC_FPC_FPNUM_SHIFT 0
15253+#define ISPCCDC_FPC_FPCEN (1 << 15)
15254+#define ISPCCDC_FPC_FPERR (1 << 16)
15255+
15256+#define ISPCCDC_VDINT_1_SHIFT 0
15257+#define ISPCCDC_VDINT_0_SHIFT 16
15258+#define ISPCCDC_VDINT_0_MASK 0x7FFF
15259+#define ISPCCDC_VDINT_1_MASK 0x7FFF
15260+
15261+#define ISPCCDC_ALAW_GWDI_12_3 (0x3 << 0)
15262+#define ISPCCDC_ALAW_GWDI_11_2 (0x4 << 0)
15263+#define ISPCCDC_ALAW_GWDI_10_1 (0x5 << 0)
15264+#define ISPCCDC_ALAW_GWDI_9_0 (0x6 << 0)
15265+#define ISPCCDC_ALAW_CCDTBL (1 << 3)
15266+
15267+#define ISPCCDC_REC656IF_R656ON 1
15268+#define ISPCCDC_REC656IF_ECCFVH (1 << 1)
15269+
15270+#define ISPCCDC_CFG_BW656 (1 << 5)
15271+#define ISPCCDC_CFG_FIDMD_SHIFT 6
15272+#define ISPCCDC_CFG_WENLOG (1 << 8)
15273+#define ISPCCDC_CFG_WENLOG_AND (0 << 8)
15274+#define ISPCCDC_CFG_WENLOG_OR (1 << 8)
15275+#define ISPCCDC_CFG_Y8POS (1 << 11)
15276+#define ISPCCDC_CFG_BSWD (1 << 12)
15277+#define ISPCCDC_CFG_MSBINVI (1 << 13)
15278+#define ISPCCDC_CFG_VDLC (1 << 15)
15279+
15280+#define ISPCCDC_FMTCFG_FMTEN 0x1
15281+#define ISPCCDC_FMTCFG_LNALT (1 << 1)
15282+#define ISPCCDC_FMTCFG_LNUM_SHIFT 2
15283+#define ISPCCDC_FMTCFG_PLEN_ODD_SHIFT 4
15284+#define ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT 8
15285+#define ISPCCDC_FMTCFG_VPIN_MASK 0x00007000
15286+#define ISPCCDC_FMTCFG_VPIN_12_3 (0x3 << 12)
15287+#define ISPCCDC_FMTCFG_VPIN_11_2 (0x4 << 12)
15288+#define ISPCCDC_FMTCFG_VPIN_10_1 (0x5 << 12)
15289+#define ISPCCDC_FMTCFG_VPIN_9_0 (0x6 << 12)
15290+#define ISPCCDC_FMTCFG_VPEN (1 << 15)
15291+
15292+#define ISPCCDC_FMTCFG_VPIF_FRQ_MASK 0x003f0000
15293+#define ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT 16
15294+#define ISPCCDC_FMTCFG_VPIF_FRQ_BY2 (0x0 << 16)
15295+#define ISPCCDC_FMTCFG_VPIF_FRQ_BY3 (0x1 << 16)
15296+#define ISPCCDC_FMTCFG_VPIF_FRQ_BY4 (0x2 << 16)
15297+#define ISPCCDC_FMTCFG_VPIF_FRQ_BY5 (0x3 << 16)
15298+#define ISPCCDC_FMTCFG_VPIF_FRQ_BY6 (0x4 << 16)
15299+
15300+#define ISPCCDC_FMT_HORZ_FMTLNH_SHIFT 0
15301+#define ISPCCDC_FMT_HORZ_FMTSPH_SHIFT 16
15302+
15303+#define ISPCCDC_FMT_VERT_FMTLNV_SHIFT 0
15304+#define ISPCCDC_FMT_VERT_FMTSLV_SHIFT 16
15305+
15306+#define ISPCCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF0000
15307+#define ISPCCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF
15308+
15309+#define ISPCCDC_FMT_VERT_FMTSLV_MASK 0x1FFF0000
15310+#define ISPCCDC_FMT_VERT_FMTLNV_MASK 0x1FFF
15311+
15312+#define ISPCCDC_VP_OUT_HORZ_ST_SHIFT 0
15313+#define ISPCCDC_VP_OUT_HORZ_NUM_SHIFT 4
15314+#define ISPCCDC_VP_OUT_VERT_NUM_SHIFT 17
15315+
15316+#define ISPRSZ_PID_PREV_SHIFT 0
15317+#define ISPRSZ_PID_CID_SHIFT 8
15318+#define ISPRSZ_PID_TID_SHIFT 16
15319+
15320+#define ISPRSZ_PCR_ENABLE (1 << 0)
15321+#define ISPRSZ_PCR_BUSY (1 << 1)
15322+#define ISPRSZ_PCR_ONESHOT (1 << 2)
15323+
15324+#define ISPRSZ_CNT_HRSZ_SHIFT 0
15325+#define ISPRSZ_CNT_HRSZ_MASK \
15326+ (0x3FF << ISPRSZ_CNT_HRSZ_SHIFT)
15327+#define ISPRSZ_CNT_VRSZ_SHIFT 10
15328+#define ISPRSZ_CNT_VRSZ_MASK \
15329+ (0x3FF << ISPRSZ_CNT_VRSZ_SHIFT)
15330+#define ISPRSZ_CNT_HSTPH_SHIFT 20
15331+#define ISPRSZ_CNT_HSTPH_MASK (0x7 << ISPRSZ_CNT_HSTPH_SHIFT)
15332+#define ISPRSZ_CNT_VSTPH_SHIFT 23
15333+#define ISPRSZ_CNT_VSTPH_MASK (0x7 << ISPRSZ_CNT_VSTPH_SHIFT)
15334+#define ISPRSZ_CNT_YCPOS (1 << 26)
15335+#define ISPRSZ_CNT_INPTYP (1 << 27)
15336+#define ISPRSZ_CNT_INPSRC (1 << 28)
15337+#define ISPRSZ_CNT_CBILIN (1 << 29)
15338+
15339+#define ISPRSZ_OUT_SIZE_HORZ_SHIFT 0
15340+#define ISPRSZ_OUT_SIZE_HORZ_MASK \
15341+ (0xFFF << ISPRSZ_OUT_SIZE_HORZ_SHIFT)
15342+#define ISPRSZ_OUT_SIZE_VERT_SHIFT 16
15343+#define ISPRSZ_OUT_SIZE_VERT_MASK \
15344+ (0xFFF << ISPRSZ_OUT_SIZE_VERT_SHIFT)
15345+
15346+#define ISPRSZ_IN_START_HORZ_ST_SHIFT 0
15347+#define ISPRSZ_IN_START_HORZ_ST_MASK \
15348+ (0x1FFF << ISPRSZ_IN_START_HORZ_ST_SHIFT)
15349+#define ISPRSZ_IN_START_VERT_ST_SHIFT 16
15350+#define ISPRSZ_IN_START_VERT_ST_MASK \
15351+ (0x1FFF << ISPRSZ_IN_START_VERT_ST_SHIFT)
15352+
15353+#define ISPRSZ_IN_SIZE_HORZ_SHIFT 0
15354+#define ISPRSZ_IN_SIZE_HORZ_MASK \
15355+ (0x1FFF << ISPRSZ_IN_SIZE_HORZ_SHIFT)
15356+#define ISPRSZ_IN_SIZE_VERT_SHIFT 16
15357+#define ISPRSZ_IN_SIZE_VERT_MASK \
15358+ (0x1FFF << ISPRSZ_IN_SIZE_VERT_SHIFT)
15359+
15360+#define ISPRSZ_SDR_INADD_ADDR_SHIFT 0
15361+#define ISPRSZ_SDR_INADD_ADDR_MASK 0xFFFFFFFF
15362+
15363+#define ISPRSZ_SDR_INOFF_OFFSET_SHIFT 0
15364+#define ISPRSZ_SDR_INOFF_OFFSET_MASK \
15365+ (0xFFFF << ISPRSZ_SDR_INOFF_OFFSET_SHIFT)
15366+
15367+#define ISPRSZ_SDR_OUTADD_ADDR_SHIFT 0
15368+#define ISPRSZ_SDR_OUTADD_ADDR_MASK 0xFFFFFFFF
15369+
15370+
15371+#define ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT 0
15372+#define ISPRSZ_SDR_OUTOFF_OFFSET_MASK \
15373+ (0xFFFF << ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT)
15374+
15375+#define ISPRSZ_HFILT_COEF0_SHIFT 0
15376+#define ISPRSZ_HFILT_COEF0_MASK \
15377+ (0x3FF << ISPRSZ_HFILT_COEF0_SHIFT)
15378+#define ISPRSZ_HFILT_COEF1_SHIFT 16
15379+#define ISPRSZ_HFILT_COEF1_MASK \
15380+ (0x3FF << ISPRSZ_HFILT_COEF1_SHIFT)
15381+
15382+#define ISPRSZ_HFILT32_COEF2_SHIFT 0
15383+#define ISPRSZ_HFILT32_COEF2_MASK 0x3FF
15384+#define ISPRSZ_HFILT32_COEF3_SHIFT 16
15385+#define ISPRSZ_HFILT32_COEF3_MASK 0x3FF0000
15386+
15387+#define ISPRSZ_HFILT54_COEF4_SHIFT 0
15388+#define ISPRSZ_HFILT54_COEF4_MASK 0x3FF
15389+#define ISPRSZ_HFILT54_COEF5_SHIFT 16
15390+#define ISPRSZ_HFILT54_COEF5_MASK 0x3FF0000
15391+
15392+#define ISPRSZ_HFILT76_COEFF6_SHIFT 0
15393+#define ISPRSZ_HFILT76_COEFF6_MASK 0x3FF
15394+#define ISPRSZ_HFILT76_COEFF7_SHIFT 16
15395+#define ISPRSZ_HFILT76_COEFF7_MASK 0x3FF0000
15396+
15397+#define ISPRSZ_HFILT98_COEFF8_SHIFT 0
15398+#define ISPRSZ_HFILT98_COEFF8_MASK 0x3FF
15399+#define ISPRSZ_HFILT98_COEFF9_SHIFT 16
15400+#define ISPRSZ_HFILT98_COEFF9_MASK 0x3FF0000
15401+
15402+#define ISPRSZ_HFILT1110_COEF10_SHIFT 0
15403+#define ISPRSZ_HFILT1110_COEF10_MASK 0x3FF
15404+#define ISPRSZ_HFILT1110_COEF11_SHIFT 16
15405+#define ISPRSZ_HFILT1110_COEF11_MASK 0x3FF0000
15406+
15407+#define ISPRSZ_HFILT1312_COEFF12_SHIFT 0
15408+#define ISPRSZ_HFILT1312_COEFF12_MASK 0x3FF
15409+#define ISPRSZ_HFILT1312_COEFF13_SHIFT 16
15410+#define ISPRSZ_HFILT1312_COEFF13_MASK 0x3FF0000
15411+
15412+#define ISPRSZ_HFILT1514_COEFF14_SHIFT 0
15413+#define ISPRSZ_HFILT1514_COEFF14_MASK 0x3FF
15414+#define ISPRSZ_HFILT1514_COEFF15_SHIFT 16
15415+#define ISPRSZ_HFILT1514_COEFF15_MASK 0x3FF0000
15416+
15417+#define ISPRSZ_HFILT1716_COEF16_SHIFT 0
15418+#define ISPRSZ_HFILT1716_COEF16_MASK 0x3FF
15419+#define ISPRSZ_HFILT1716_COEF17_SHIFT 16
15420+#define ISPRSZ_HFILT1716_COEF17_MASK 0x3FF0000
15421+
15422+#define ISPRSZ_HFILT1918_COEF18_SHIFT 0
15423+#define ISPRSZ_HFILT1918_COEF18_MASK 0x3FF
15424+#define ISPRSZ_HFILT1918_COEF19_SHIFT 16
15425+#define ISPRSZ_HFILT1918_COEF19_MASK 0x3FF0000
15426+
15427+#define ISPRSZ_HFILT2120_COEF20_SHIFT 0
15428+#define ISPRSZ_HFILT2120_COEF20_MASK 0x3FF
15429+#define ISPRSZ_HFILT2120_COEF21_SHIFT 16
15430+#define ISPRSZ_HFILT2120_COEF21_MASK 0x3FF0000
15431+
15432+#define ISPRSZ_HFILT2322_COEF22_SHIFT 0
15433+#define ISPRSZ_HFILT2322_COEF22_MASK 0x3FF
15434+#define ISPRSZ_HFILT2322_COEF23_SHIFT 16
15435+#define ISPRSZ_HFILT2322_COEF23_MASK 0x3FF0000
15436+
15437+#define ISPRSZ_HFILT2524_COEF24_SHIFT 0
15438+#define ISPRSZ_HFILT2524_COEF24_MASK 0x3FF
15439+#define ISPRSZ_HFILT2524_COEF25_SHIFT 16
15440+#define ISPRSZ_HFILT2524_COEF25_MASK 0x3FF0000
15441+
15442+#define ISPRSZ_HFILT2726_COEF26_SHIFT 0
15443+#define ISPRSZ_HFILT2726_COEF26_MASK 0x3FF
15444+#define ISPRSZ_HFILT2726_COEF27_SHIFT 16
15445+#define ISPRSZ_HFILT2726_COEF27_MASK 0x3FF0000
15446+
15447+#define ISPRSZ_HFILT2928_COEF28_SHIFT 0
15448+#define ISPRSZ_HFILT2928_COEF28_MASK 0x3FF
15449+#define ISPRSZ_HFILT2928_COEF29_SHIFT 16
15450+#define ISPRSZ_HFILT2928_COEF29_MASK 0x3FF0000
15451+
15452+#define ISPRSZ_HFILT3130_COEF30_SHIFT 0
15453+#define ISPRSZ_HFILT3130_COEF30_MASK 0x3FF
15454+#define ISPRSZ_HFILT3130_COEF31_SHIFT 16
15455+#define ISPRSZ_HFILT3130_COEF31_MASK 0x3FF0000
15456+
15457+#define ISPRSZ_VFILT_COEF0_SHIFT 0
15458+#define ISPRSZ_VFILT_COEF0_MASK \
15459+ (0x3FF << ISPRSZ_VFILT_COEF0_SHIFT)
15460+#define ISPRSZ_VFILT_COEF1_SHIFT 16
15461+#define ISPRSZ_VFILT_COEF1_MASK \
15462+ (0x3FF << ISPRSZ_VFILT_COEF1_SHIFT)
15463+
15464+#define ISPRSZ_VFILT10_COEF0_SHIFT 0
15465+#define ISPRSZ_VFILT10_COEF0_MASK 0x3FF
15466+#define ISPRSZ_VFILT10_COEF1_SHIFT 16
15467+#define ISPRSZ_VFILT10_COEF1_MASK 0x3FF0000
15468+
15469+#define ISPRSZ_VFILT32_COEF2_SHIFT 0
15470+#define ISPRSZ_VFILT32_COEF2_MASK 0x3FF
15471+#define ISPRSZ_VFILT32_COEF3_SHIFT 16
15472+#define ISPRSZ_VFILT32_COEF3_MASK 0x3FF0000
15473+
15474+#define ISPRSZ_VFILT54_COEF4_SHIFT 0
15475+#define ISPRSZ_VFILT54_COEF4_MASK 0x3FF
15476+#define ISPRSZ_VFILT54_COEF5_SHIFT 16
15477+#define ISPRSZ_VFILT54_COEF5_MASK 0x3FF0000
15478+
15479+#define ISPRSZ_VFILT76_COEFF6_SHIFT 0
15480+#define ISPRSZ_VFILT76_COEFF6_MASK 0x3FF
15481+#define ISPRSZ_VFILT76_COEFF7_SHIFT 16
15482+#define ISPRSZ_VFILT76_COEFF7_MASK 0x3FF0000
15483+
15484+#define ISPRSZ_VFILT98_COEFF8_SHIFT 0
15485+#define ISPRSZ_VFILT98_COEFF8_MASK 0x3FF
15486+#define ISPRSZ_VFILT98_COEFF9_SHIFT 16
15487+#define ISPRSZ_VFILT98_COEFF9_MASK 0x3FF0000
15488+
15489+#define ISPRSZ_VFILT1110_COEF10_SHIFT 0
15490+#define ISPRSZ_VFILT1110_COEF10_MASK 0x3FF
15491+#define ISPRSZ_VFILT1110_COEF11_SHIFT 16
15492+#define ISPRSZ_VFILT1110_COEF11_MASK 0x3FF0000
15493+
15494+#define ISPRSZ_VFILT1312_COEFF12_SHIFT 0
15495+#define ISPRSZ_VFILT1312_COEFF12_MASK 0x3FF
15496+#define ISPRSZ_VFILT1312_COEFF13_SHIFT 16
15497+#define ISPRSZ_VFILT1312_COEFF13_MASK 0x3FF0000
15498+
15499+#define ISPRSZ_VFILT1514_COEFF14_SHIFT 0
15500+#define ISPRSZ_VFILT1514_COEFF14_MASK 0x3FF
15501+#define ISPRSZ_VFILT1514_COEFF15_SHIFT 16
15502+#define ISPRSZ_VFILT1514_COEFF15_MASK 0x3FF0000
15503+
15504+#define ISPRSZ_VFILT1716_COEF16_SHIFT 0
15505+#define ISPRSZ_VFILT1716_COEF16_MASK 0x3FF
15506+#define ISPRSZ_VFILT1716_COEF17_SHIFT 16
15507+#define ISPRSZ_VFILT1716_COEF17_MASK 0x3FF0000
15508+
15509+#define ISPRSZ_VFILT1918_COEF18_SHIFT 0
15510+#define ISPRSZ_VFILT1918_COEF18_MASK 0x3FF
15511+#define ISPRSZ_VFILT1918_COEF19_SHIFT 16
15512+#define ISPRSZ_VFILT1918_COEF19_MASK 0x3FF0000
15513+
15514+#define ISPRSZ_VFILT2120_COEF20_SHIFT 0
15515+#define ISPRSZ_VFILT2120_COEF20_MASK 0x3FF
15516+#define ISPRSZ_VFILT2120_COEF21_SHIFT 16
15517+#define ISPRSZ_VFILT2120_COEF21_MASK 0x3FF0000
15518+
15519+#define ISPRSZ_VFILT2322_COEF22_SHIFT 0
15520+#define ISPRSZ_VFILT2322_COEF22_MASK 0x3FF
15521+#define ISPRSZ_VFILT2322_COEF23_SHIFT 16
15522+#define ISPRSZ_VFILT2322_COEF23_MASK 0x3FF0000
15523+
15524+#define ISPRSZ_VFILT2524_COEF24_SHIFT 0
15525+#define ISPRSZ_VFILT2524_COEF24_MASK 0x3FF
15526+#define ISPRSZ_VFILT2524_COEF25_SHIFT 16
15527+#define ISPRSZ_VFILT2524_COEF25_MASK 0x3FF0000
15528+
15529+#define ISPRSZ_VFILT2726_COEF26_SHIFT 0
15530+#define ISPRSZ_VFILT2726_COEF26_MASK 0x3FF
15531+#define ISPRSZ_VFILT2726_COEF27_SHIFT 16
15532+#define ISPRSZ_VFILT2726_COEF27_MASK 0x3FF0000
15533+
15534+#define ISPRSZ_VFILT2928_COEF28_SHIFT 0
15535+#define ISPRSZ_VFILT2928_COEF28_MASK 0x3FF
15536+#define ISPRSZ_VFILT2928_COEF29_SHIFT 16
15537+#define ISPRSZ_VFILT2928_COEF29_MASK 0x3FF0000
15538+
15539+#define ISPRSZ_VFILT3130_COEF30_SHIFT 0
15540+#define ISPRSZ_VFILT3130_COEF30_MASK 0x3FF
15541+#define ISPRSZ_VFILT3130_COEF31_SHIFT 16
15542+#define ISPRSZ_VFILT3130_COEF31_MASK 0x3FF0000
15543+
15544+#define ISPRSZ_YENH_CORE_SHIFT 0
15545+#define ISPRSZ_YENH_CORE_MASK \
15546+ (0xFF << ISPRSZ_YENH_CORE_SHIFT)
15547+#define ISPRSZ_YENH_SLOP_SHIFT 8
15548+#define ISPRSZ_YENH_SLOP_MASK \
15549+ (0xF << ISPRSZ_YENH_SLOP_SHIFT)
15550+#define ISPRSZ_YENH_GAIN_SHIFT 12
15551+#define ISPRSZ_YENH_GAIN_MASK \
15552+ (0xF << ISPRSZ_YENH_GAIN_SHIFT)
15553+#define ISPRSZ_YENH_ALGO_SHIFT 16
15554+#define ISPRSZ_YENH_ALGO_MASK \
15555+ (0x3 << ISPRSZ_YENH_ALGO_SHIFT)
15556+
15557+#define ISPH3A_PCR_AEW_ALAW_EN_SHIFT 1
15558+#define ISPH3A_PCR_AF_MED_TH_SHIFT 3
15559+#define ISPH3A_PCR_AF_RGBPOS_SHIFT 11
15560+#define ISPH3A_PCR_AEW_AVE2LMT_SHIFT 22
15561+#define ISPH3A_PCR_AEW_AVE2LMT_MASK 0xFFC00000
15562+#define ISPH3A_PCR_BUSYAF (1 << 15)
15563+#define ISPH3A_PCR_BUSYAEAWB (1 << 18)
15564+
15565+#define ISPH3A_AEWWIN1_WINHC_SHIFT 0
15566+#define ISPH3A_AEWWIN1_WINHC_MASK 0x3F
15567+#define ISPH3A_AEWWIN1_WINVC_SHIFT 6
15568+#define ISPH3A_AEWWIN1_WINVC_MASK 0x1FC0
15569+#define ISPH3A_AEWWIN1_WINW_SHIFT 13
15570+#define ISPH3A_AEWWIN1_WINW_MASK 0xFE000
15571+#define ISPH3A_AEWWIN1_WINH_SHIFT 24
15572+#define ISPH3A_AEWWIN1_WINH_MASK 0x7F000000
15573+
15574+#define ISPH3A_AEWINSTART_WINSH_SHIFT 0
15575+#define ISPH3A_AEWINSTART_WINSH_MASK 0x0FFF
15576+#define ISPH3A_AEWINSTART_WINSV_SHIFT 16
15577+#define ISPH3A_AEWINSTART_WINSV_MASK 0x0FFF0000
15578+
15579+#define ISPH3A_AEWINBLK_WINH_SHIFT 0
15580+#define ISPH3A_AEWINBLK_WINH_MASK 0x7F
15581+#define ISPH3A_AEWINBLK_WINSV_SHIFT 16
15582+#define ISPH3A_AEWINBLK_WINSV_MASK 0x0FFF0000
15583+
15584+#define ISPH3A_AEWSUBWIN_AEWINCH_SHIFT 0
15585+#define ISPH3A_AEWSUBWIN_AEWINCH_MASK 0x0F
15586+#define ISPH3A_AEWSUBWIN_AEWINCV_SHIFT 8
15587+#define ISPH3A_AEWSUBWIN_AEWINCV_MASK 0x0F00
15588+
15589+#define ISPHIST_PCR_ENABLE_SHIFT 0
15590+#define ISPHIST_PCR_ENABLE_MASK 0x01
15591+#define ISPHIST_PCR_ENABLE (1 << ISPHIST_PCR_ENABLE_SHIFT)
15592+#define ISPHIST_PCR_BUSY 0x02
15593+
15594+#define ISPHIST_CNT_DATASIZE_SHIFT 8
15595+#define ISPHIST_CNT_DATASIZE_MASK 0x0100
15596+#define ISPHIST_CNT_CLEAR_SHIFT 7
15597+#define ISPHIST_CNT_CLEAR_MASK 0x080
15598+#define ISPHIST_CNT_CLEAR (1 << ISPHIST_CNT_CLEAR_SHIFT)
15599+#define ISPHIST_CNT_CFA_SHIFT 6
15600+#define ISPHIST_CNT_CFA_MASK 0x040
15601+#define ISPHIST_CNT_BINS_SHIFT 4
15602+#define ISPHIST_CNT_BINS_MASK 0x030
15603+#define ISPHIST_CNT_SOURCE_SHIFT 3
15604+#define ISPHIST_CNT_SOURCE_MASK 0x08
15605+#define ISPHIST_CNT_SHIFT_SHIFT 0
15606+#define ISPHIST_CNT_SHIFT_MASK 0x07
15607+
15608+#define ISPHIST_WB_GAIN_WG00_SHIFT 24
15609+#define ISPHIST_WB_GAIN_WG00_MASK 0xFF000000
15610+#define ISPHIST_WB_GAIN_WG01_SHIFT 16
15611+#define ISPHIST_WB_GAIN_WG01_MASK 0xFF0000
15612+#define ISPHIST_WB_GAIN_WG02_SHIFT 8
15613+#define ISPHIST_WB_GAIN_WG02_MASK 0xFF00
15614+#define ISPHIST_WB_GAIN_WG03_SHIFT 0
15615+#define ISPHIST_WB_GAIN_WG03_MASK 0xFF
15616+
15617+#define ISPHIST_REG_START_END_MASK 0x3FFF
15618+#define ISPHIST_REG_START_SHIFT 16
15619+#define ISPHIST_REG_END_SHIFT 0
15620+#define ISPHIST_REG_START_MASK (ISPHIST_REG_START_END_MASK << \
15621+ ISPHIST_REG_START_SHIFT)
15622+#define ISPHIST_REG_END_MASK (ISPHIST_REG_START_END_MASK << \
15623+ ISPHIST_REG_END_SHIFT)
15624+
15625+#define ISPHIST_REG_MASK (ISPHIST_REG_START_MASK | \
15626+ ISPHIST_REG_END_MASK)
15627+
15628+#define ISPHIST_ADDR_SHIFT 0
15629+#define ISPHIST_ADDR_MASK 0x3FF
15630+
15631+#define ISPHIST_DATA_SHIFT 0
15632+#define ISPHIST_DATA_MASK 0xFFFFF
15633+
15634+#define ISPHIST_RADD_SHIFT 0
15635+#define ISPHIST_RADD_MASK 0xFFFFFFFF
15636+
15637+#define ISPHIST_RADD_OFF_SHIFT 0
15638+#define ISPHIST_RADD_OFF_MASK 0xFFFF
15639+
15640+#define ISPHIST_HV_INFO_HSIZE_SHIFT 16
15641+#define ISPHIST_HV_INFO_HSIZE_MASK 0x3FFF0000
15642+#define ISPHIST_HV_INFO_VSIZE_SHIFT 0
15643+#define ISPHIST_HV_INFO_VSIZE_MASK 0x3FFF
15644+
15645+#define ISPHIST_HV_INFO_MASK 0x3FFF3FFF
15646+
15647+#define ISPCCDC_LSC_ENABLE 1
15648+#define ISPCCDC_LSC_BUSY (1 << 7)
15649+#define ISPCCDC_LSC_GAIN_MODE_N_MASK 0x700
15650+#define ISPCCDC_LSC_GAIN_MODE_N_SHIFT 8
15651+#define ISPCCDC_LSC_GAIN_MODE_M_MASK 0x3800
15652+#define ISPCCDC_LSC_GAIN_MODE_M_SHIFT 12
15653+#define ISPCCDC_LSC_GAIN_FORMAT_MASK 0xE
15654+#define ISPCCDC_LSC_GAIN_FORMAT_SHIFT 1
15655+#define ISPCCDC_LSC_AFTER_REFORMATTER_MASK (1<<6)
15656+
15657+#define ISPCCDC_LSC_INITIAL_X_MASK 0x3F
15658+#define ISPCCDC_LSC_INITIAL_X_SHIFT 0
15659+#define ISPCCDC_LSC_INITIAL_Y_MASK 0x3F0000
15660+#define ISPCCDC_LSC_INITIAL_Y_SHIFT 16
15661+
15662+/* -----------------------------------------------------------------------------
15663+ * CSI2 receiver registers (ES2.0)
15664+ */
15665+
15666+#define ISPCSI2_REVISION (0x000)
15667+#define ISPCSI2_SYSCONFIG (0x010)
15668+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT 12
15669+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK \
15670+ (0x3 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
15671+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_FORCE \
15672+ (0x0 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
15673+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO \
15674+ (0x1 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
15675+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART \
15676+ (0x2 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
15677+#define ISPCSI2_SYSCONFIG_SOFT_RESET (1 << 1)
15678+#define ISPCSI2_SYSCONFIG_AUTO_IDLE (1 << 0)
15679+
15680+#define ISPCSI2_SYSSTATUS (0x014)
15681+#define ISPCSI2_SYSSTATUS_RESET_DONE (1 << 0)
15682+
15683+#define ISPCSI2_IRQSTATUS (0x018)
15684+#define ISPCSI2_IRQSTATUS_OCP_ERR_IRQ (1 << 14)
15685+#define ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ (1 << 13)
15686+#define ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ (1 << 12)
15687+#define ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ (1 << 11)
15688+#define ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ (1 << 10)
15689+#define ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ (1 << 9)
15690+#define ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ (1 << 8)
15691+#define ISPCSI2_IRQSTATUS_CONTEXT(n) (1 << (n))
15692+
15693+#define ISPCSI2_IRQENABLE (0x01c)
15694+#define ISPCSI2_CTRL (0x040)
15695+#define ISPCSI2_CTRL_VP_CLK_EN (1 << 15)
15696+#define ISPCSI2_CTRL_VP_ONLY_EN (1 << 11)
15697+#define ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT 8
15698+#define ISPCSI2_CTRL_VP_OUT_CTRL_MASK \
15699+ (3 << ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
15700+#define ISPCSI2_CTRL_DBG_EN (1 << 7)
15701+#define ISPCSI2_CTRL_BURST_SIZE_SHIFT 5
15702+#define ISPCSI2_CTRL_BURST_SIZE_MASK \
15703+ (3 << ISPCSI2_CTRL_BURST_SIZE_SHIFT)
15704+#define ISPCSI2_CTRL_FRAME (1 << 3)
15705+#define ISPCSI2_CTRL_ECC_EN (1 << 2)
15706+#define ISPCSI2_CTRL_SECURE (1 << 1)
15707+#define ISPCSI2_CTRL_IF_EN (1 << 0)
15708+
15709+#define ISPCSI2_DBG_H (0x044)
15710+#define ISPCSI2_GNQ (0x048)
15711+#define ISPCSI2_PHY_CFG (0x050)
15712+#define ISPCSI2_PHY_CFG_RESET_CTRL (1 << 30)
15713+#define ISPCSI2_PHY_CFG_RESET_DONE (1 << 29)
15714+#define ISPCSI2_PHY_CFG_PWR_CMD_SHIFT 27
15715+#define ISPCSI2_PHY_CFG_PWR_CMD_MASK \
15716+ (0x3 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
15717+#define ISPCSI2_PHY_CFG_PWR_CMD_OFF \
15718+ (0x0 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
15719+#define ISPCSI2_PHY_CFG_PWR_CMD_ON \
15720+ (0x1 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
15721+#define ISPCSI2_PHY_CFG_PWR_CMD_ULPW \
15722+ (0x2 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
15723+#define ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT 25
15724+#define ISPCSI2_PHY_CFG_PWR_STATUS_MASK \
15725+ (0x3 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
15726+#define ISPCSI2_PHY_CFG_PWR_STATUS_OFF \
15727+ (0x0 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
15728+#define ISPCSI2_PHY_CFG_PWR_STATUS_ON \
15729+ (0x1 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
15730+#define ISPCSI2_PHY_CFG_PWR_STATUS_ULPW \
15731+ (0x2 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
15732+#define ISPCSI2_PHY_CFG_PWR_AUTO (1 << 24)
15733+
15734+#define ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n) (3 + ((n) * 4))
15735+#define ISPCSI2_PHY_CFG_DATA_POL_MASK(n) \
15736+ (0x1 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
15737+#define ISPCSI2_PHY_CFG_DATA_POL_PN(n) \
15738+ (0x0 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
15739+#define ISPCSI2_PHY_CFG_DATA_POL_NP(n) \
15740+ (0x1 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
15741+
15742+#define ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n) ((n) * 4)
15743+#define ISPCSI2_PHY_CFG_DATA_POSITION_MASK(n) \
15744+ (0x7 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
15745+#define ISPCSI2_PHY_CFG_DATA_POSITION_NC(n) \
15746+ (0x0 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
15747+#define ISPCSI2_PHY_CFG_DATA_POSITION_1(n) \
15748+ (0x1 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
15749+#define ISPCSI2_PHY_CFG_DATA_POSITION_2(n) \
15750+ (0x2 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
15751+#define ISPCSI2_PHY_CFG_DATA_POSITION_3(n) \
15752+ (0x3 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
15753+#define ISPCSI2_PHY_CFG_DATA_POSITION_4(n) \
15754+ (0x4 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
15755+#define ISPCSI2_PHY_CFG_DATA_POSITION_5(n) \
15756+ (0x5 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
15757+
15758+#define ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT 3
15759+#define ISPCSI2_PHY_CFG_CLOCK_POL_MASK \
15760+ (0x1 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
15761+#define ISPCSI2_PHY_CFG_CLOCK_POL_PN \
15762+ (0x0 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
15763+#define ISPCSI2_PHY_CFG_CLOCK_POL_NP \
15764+ (0x1 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
15765+
15766+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT 0
15767+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK \
15768+ (0x7 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
15769+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_1 \
15770+ (0x1 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
15771+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_2 \
15772+ (0x2 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
15773+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_3 \
15774+ (0x3 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
15775+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_4 \
15776+ (0x4 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
15777+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_5 \
15778+ (0x5 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
15779+
15780+#define ISPCSI2_PHY_IRQSTATUS (0x054)
15781+#define ISPCSI2_PHY_IRQSTATUS_STATEALLULPMEXIT (1 << 26)
15782+#define ISPCSI2_PHY_IRQSTATUS_STATEALLULPMENTER (1 << 25)
15783+#define ISPCSI2_PHY_IRQSTATUS_STATEULPM5 (1 << 24)
15784+#define ISPCSI2_PHY_IRQSTATUS_STATEULPM4 (1 << 23)
15785+#define ISPCSI2_PHY_IRQSTATUS_STATEULPM3 (1 << 22)
15786+#define ISPCSI2_PHY_IRQSTATUS_STATEULPM2 (1 << 21)
15787+#define ISPCSI2_PHY_IRQSTATUS_STATEULPM1 (1 << 20)
15788+#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL5 (1 << 19)
15789+#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL4 (1 << 18)
15790+#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL3 (1 << 17)
15791+#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL2 (1 << 16)
15792+#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL1 (1 << 15)
15793+#define ISPCSI2_PHY_IRQSTATUS_ERRESC5 (1 << 14)
15794+#define ISPCSI2_PHY_IRQSTATUS_ERRESC4 (1 << 13)
15795+#define ISPCSI2_PHY_IRQSTATUS_ERRESC3 (1 << 12)
15796+#define ISPCSI2_PHY_IRQSTATUS_ERRESC2 (1 << 11)
15797+#define ISPCSI2_PHY_IRQSTATUS_ERRESC1 (1 << 10)
15798+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS5 (1 << 9)
15799+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS4 (1 << 8)
15800+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS3 (1 << 7)
15801+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS2 (1 << 6)
15802+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS1 (1 << 5)
15803+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS5 (1 << 4)
15804+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS4 (1 << 3)
15805+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS3 (1 << 2)
15806+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS2 (1 << 1)
15807+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS1 1
15808+
15809+#define ISPCSI2_SHORT_PACKET (0x05c)
15810+#define ISPCSI2_PHY_IRQENABLE (0x060)
15811+#define ISPCSI2_PHY_IRQENABLE_STATEALLULPMEXIT (1 << 26)
15812+#define ISPCSI2_PHY_IRQENABLE_STATEALLULPMENTER (1 << 25)
15813+#define ISPCSI2_PHY_IRQENABLE_STATEULPM5 (1 << 24)
15814+#define ISPCSI2_PHY_IRQENABLE_STATEULPM4 (1 << 23)
15815+#define ISPCSI2_PHY_IRQENABLE_STATEULPM3 (1 << 22)
15816+#define ISPCSI2_PHY_IRQENABLE_STATEULPM2 (1 << 21)
15817+#define ISPCSI2_PHY_IRQENABLE_STATEULPM1 (1 << 20)
15818+#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL5 (1 << 19)
15819+#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL4 (1 << 18)
15820+#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL3 (1 << 17)
15821+#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL2 (1 << 16)
15822+#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL1 (1 << 15)
15823+#define ISPCSI2_PHY_IRQENABLE_ERRESC5 (1 << 14)
15824+#define ISPCSI2_PHY_IRQENABLE_ERRESC4 (1 << 13)
15825+#define ISPCSI2_PHY_IRQENABLE_ERRESC3 (1 << 12)
15826+#define ISPCSI2_PHY_IRQENABLE_ERRESC2 (1 << 11)
15827+#define ISPCSI2_PHY_IRQENABLE_ERRESC1 (1 << 10)
15828+#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS5 (1 << 9)
15829+#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS4 (1 << 8)
15830+#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS3 (1 << 7)
15831+#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS2 (1 << 6)
15832+#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS1 (1 << 5)
15833+#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS5 (1 << 4)
15834+#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS4 (1 << 3)
15835+#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS3 (1 << 2)
15836+#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS2 (1 << 1)
15837+#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS1 (1 << 0)
15838+
15839+#define ISPCSI2_DBG_P (0x068)
15840+#define ISPCSI2_TIMING (0x06c)
15841+#define ISPCSI2_TIMING_FORCE_RX_MODE_IO(n) (1 << ((16 * ((n) - 1)) + 15))
15842+#define ISPCSI2_TIMING_STOP_STATE_X16_IO(n) (1 << ((16 * ((n) - 1)) + 14))
15843+#define ISPCSI2_TIMING_STOP_STATE_X4_IO(n) (1 << ((16 * ((n) - 1)) + 13))
15844+#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n) (16 * ((n) - 1))
15845+#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(n) \
15846+ (0x1fff << ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n))
15847+
15848+#define ISPCSI2_CTX_CTRL1(n) ((0x070) + 0x20 * (n))
15849+#define ISPCSI2_CTX_CTRL1_COUNT_SHIFT 8
15850+#define ISPCSI2_CTX_CTRL1_COUNT_MASK \
15851+ (0xff << ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
15852+#define ISPCSI2_CTX_CTRL1_EOF_EN (1 << 7)
15853+#define ISPCSI2_CTX_CTRL1_EOL_EN (1 << 6)
15854+#define ISPCSI2_CTX_CTRL1_CS_EN (1 << 5)
15855+#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK (1 << 4)
15856+#define ISPCSI2_CTX_CTRL1_PING_PONG (1 << 3)
15857+#define ISPCSI2_CTX_CTRL1_CTX_EN (1 << 0)
15858+
15859+#define ISPCSI2_CTX_CTRL2(n) ((0x074) + 0x20 * (n))
15860+#define ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT 13
15861+#define ISPCSI2_CTX_CTRL2_USER_DEF_MAP_MASK \
15862+ (0x3 << ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT)
15863+#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT 11
15864+#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK \
15865+ (0x3 << ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT)
15866+#define ISPCSI2_CTX_CTRL2_DPCM_PRED (1 << 10)
15867+#define ISPCSI2_CTX_CTRL2_FORMAT_SHIFT 0
15868+#define ISPCSI2_CTX_CTRL2_FORMAT_MASK \
15869+ (0x3ff << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT)
15870+#define ISPCSI2_CTX_CTRL2_FRAME_SHIFT 16
15871+#define ISPCSI2_CTX_CTRL2_FRAME_MASK \
15872+ (0xffff << ISPCSI2_CTX_CTRL2_FRAME_SHIFT)
15873+
15874+#define ISPCSI2_CTX_DAT_OFST(n) ((0x078) + 0x20 * (n))
15875+#define ISPCSI2_CTX_DAT_OFST_OFST_SHIFT 0
15876+#define ISPCSI2_CTX_DAT_OFST_OFST_MASK \
15877+ (0x1ffe0 << ISPCSI2_CTX_DAT_OFST_OFST_SHIFT)
15878+
15879+#define ISPCSI2_CTX_DAT_PING_ADDR(n) ((0x07c) + 0x20 * (n))
15880+#define ISPCSI2_CTX_DAT_PONG_ADDR(n) ((0x080) + 0x20 * (n))
15881+#define ISPCSI2_CTX_IRQENABLE(n) ((0x084) + 0x20 * (n))
15882+#define ISPCSI2_CTX_IRQENABLE_ECC_CORRECTION_IRQ (1 << 8)
15883+#define ISPCSI2_CTX_IRQENABLE_LINE_NUMBER_IRQ (1 << 7)
15884+#define ISPCSI2_CTX_IRQENABLE_FRAME_NUMBER_IRQ (1 << 6)
15885+#define ISPCSI2_CTX_IRQENABLE_CS_IRQ (1 << 5)
15886+#define ISPCSI2_CTX_IRQENABLE_LE_IRQ (1 << 3)
15887+#define ISPCSI2_CTX_IRQENABLE_LS_IRQ (1 << 2)
15888+#define ISPCSI2_CTX_IRQENABLE_FE_IRQ (1 << 1)
15889+#define ISPCSI2_CTX_IRQENABLE_FS_IRQ (1 << 0)
15890+
15891+#define ISPCSI2_CTX_IRQSTATUS(n) ((0x088) + 0x20 * (n))
15892+#define ISPCSI2_CTX_IRQSTATUS_ECC_CORRECTION_IRQ (1 << 8)
15893+#define ISPCSI2_CTX_IRQSTATUS_LINE_NUMBER_IRQ (1 << 7)
15894+#define ISPCSI2_CTX_IRQSTATUS_FRAME_NUMBER_IRQ (1 << 6)
15895+#define ISPCSI2_CTX_IRQSTATUS_CS_IRQ (1 << 5)
15896+#define ISPCSI2_CTX_IRQSTATUS_LE_IRQ (1 << 3)
15897+#define ISPCSI2_CTX_IRQSTATUS_LS_IRQ (1 << 2)
15898+#define ISPCSI2_CTX_IRQSTATUS_FE_IRQ (1 << 1)
15899+#define ISPCSI2_CTX_IRQSTATUS_FS_IRQ (1 << 0)
15900+
15901+#define ISPCSI2_CTX_CTRL3(n) ((0x08c) + 0x20 * (n))
15902+#define ISPCSI2_CTX_CTRL3_ALPHA_SHIFT 5
15903+#define ISPCSI2_CTX_CTRL3_ALPHA_MASK \
15904+ (0x3fff << ISPCSI2_CTX_CTRL3_ALPHA_SHIFT)
15905+
15906+/* This instance is for OMAP3630 only */
15907+#define ISPCSI2_CTX_TRANSCODEH(n) (0x000 + 0x8 * (n))
15908+#define ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT 16
15909+#define ISPCSI2_CTX_TRANSCODEH_HCOUNT_MASK \
15910+ (0x1fff << ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT)
15911+#define ISPCSI2_CTX_TRANSCODEH_HSKIP_SHIFT 0
15912+#define ISPCSI2_CTX_TRANSCODEH_HSKIP_MASK \
15913+ (0x1fff << ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT)
15914+#define ISPCSI2_CTX_TRANSCODEV(n) (0x004 + 0x8 * (n))
15915+#define ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT 16
15916+#define ISPCSI2_CTX_TRANSCODEV_VCOUNT_MASK \
15917+ (0x1fff << ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT)
15918+#define ISPCSI2_CTX_TRANSCODEV_VSKIP_SHIFT 0
15919+#define ISPCSI2_CTX_TRANSCODEV_VSKIP_MASK \
15920+ (0x1fff << ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT)
15921+
15922+/* -----------------------------------------------------------------------------
15923+ * CSI PHY registers
15924+ */
15925+
15926+#define ISPCSIPHY_REG0 (0x000)
15927+#define ISPCSIPHY_REG0_THS_TERM_SHIFT 8
15928+#define ISPCSIPHY_REG0_THS_TERM_MASK \
15929+ (0xff << ISPCSIPHY_REG0_THS_TERM_SHIFT)
15930+#define ISPCSIPHY_REG0_THS_SETTLE_SHIFT 0
15931+#define ISPCSIPHY_REG0_THS_SETTLE_MASK \
15932+ (0xff << ISPCSIPHY_REG0_THS_SETTLE_SHIFT)
15933+
15934+#define ISPCSIPHY_REG1 (0x004)
15935+#define ISPCSIPHY_REG1_RESET_DONE_CTRLCLK (1 << 29)
15936+/* This field is for OMAP3630 only */
15937+#define ISPCSIPHY_REG1_CLOCK_MISS_DETECTOR_STATUS (1 << 25)
15938+#define ISPCSIPHY_REG1_TCLK_TERM_SHIFT 18
15939+#define ISPCSIPHY_REG1_TCLK_TERM_MASK \
15940+ (0x7f << ISPCSIPHY_REG1_TCLK_TERM_SHIFT)
15941+#define ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN_SHIFT 10
15942+#define ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN_MASK \
15943+ (0xff << ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN)
15944+/* This field is for OMAP3430 only */
15945+#define ISPCSIPHY_REG1_TCLK_MISS_SHIFT 8
15946+#define ISPCSIPHY_REG1_TCLK_MISS_MASK \
15947+ (0x3 << ISPCSIPHY_REG1_TCLK_MISS_SHIFT)
15948+/* This field is for OMAP3630 only */
15949+#define ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_SHIFT 8
15950+#define ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_MASK \
15951+ (0x3 << ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_SHIFT)
15952+#define ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT 0
15953+#define ISPCSIPHY_REG1_TCLK_SETTLE_MASK \
15954+ (0xff << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT)
15955+
15956+/* This register is for OMAP3630 only */
15957+#define ISPCSIPHY_REG2 (0x008)
15958+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_SHIFT 30
15959+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_MASK \
15960+ (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_SHIFT)
15961+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_SHIFT 28
15962+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_MASK \
15963+ (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_SHIFT)
15964+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_SHIFT 26
15965+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_MASK \
15966+ (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_SHIFT)
15967+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_SHIFT 24
15968+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_MASK \
15969+ (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_SHIFT)
15970+#define ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_SHIFT 0
15971+#define ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_MASK \
15972+ (0x7fffff << ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_SHIFT)
15973+
15974+#endif /* OMAP3_ISP_REG_H */
15975diff --git a/drivers/media/video/isp/ispresizer.c b/drivers/media/video/isp/ispresizer.c
15976new file mode 100644
15977index 0000000..a696450
15978--- /dev/null
15979+++ b/drivers/media/video/isp/ispresizer.c
15980@@ -0,0 +1,1710 @@
15981+/*
15982+ * ispresizer.c
15983+ *
15984+ * TI OMAP3 ISP - Resizer module
15985+ *
15986+ * Copyright (C) 2010 Nokia Corporation
15987+ * Copyright (C) 2009 Texas Instruments, Inc
15988+ *
15989+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
15990+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
15991+ *
15992+ * This program is free software; you can redistribute it and/or modify
15993+ * it under the terms of the GNU General Public License version 2 as
15994+ * published by the Free Software Foundation.
15995+ *
15996+ * This program is distributed in the hope that it will be useful, but
15997+ * WITHOUT ANY WARRANTY; without even the implied warranty of
15998+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15999+ * General Public License for more details.
16000+ *
16001+ * You should have received a copy of the GNU General Public License
16002+ * along with this program; if not, write to the Free Software
16003+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
16004+ * 02110-1301 USA
16005+ */
16006+
16007+#include <linux/device.h>
16008+#include <linux/mm.h>
16009+#include <linux/module.h>
16010+
16011+#include "isp.h"
16012+#include "ispreg.h"
16013+#include "ispresizer.h"
16014+
16015+/*
16016+ * Resizer Constants
16017+ */
16018+#define MIN_RESIZE_VALUE 64
16019+#define MID_RESIZE_VALUE 512
16020+#define MAX_RESIZE_VALUE 1024
16021+
16022+#define MIN_IN_WIDTH 32
16023+#define MIN_IN_HEIGHT 32
16024+#define MAX_IN_WIDTH_MEMORY_MODE 4095
16025+#define MAX_IN_WIDTH_ONTHEFLY_MODE_ES1 1280
16026+#define MAX_IN_WIDTH_ONTHEFLY_MODE_ES2 4095
16027+#define MAX_IN_HEIGHT 4095
16028+
16029+#define MIN_OUT_WIDTH 16
16030+#define MIN_OUT_HEIGHT 2
16031+#define MAX_OUT_HEIGHT 4095
16032+
16033+/*
16034+ * Resizer Use Constraints
16035+ * "TRM ES3.1, table 12-46"
16036+ */
16037+#define MAX_4TAP_OUT_WIDTH_ES1 1280
16038+#define MAX_7TAP_OUT_WIDTH_ES1 640
16039+#define MAX_4TAP_OUT_WIDTH_ES2 3312
16040+#define MAX_7TAP_OUT_WIDTH_ES2 1650
16041+#define MAX_4TAP_OUT_WIDTH_3630 4096
16042+#define MAX_7TAP_OUT_WIDTH_3630 2048
16043+
16044+/*
16045+ * Constants for ratio calculation
16046+ */
16047+#define RESIZE_DIVISOR 256
16048+#define DEFAULT_PHASE 1
16049+
16050+/*
16051+ * Default (and only) configuration of filter coefficients.
16052+ * 7-tap mode is for scale factors 0.25x to 0.5x.
16053+ * 4-tap mode is for scale factors 0.5x to 4.0x.
16054+ * There shouldn't be any reason to recalculate these, EVER.
16055+ */
16056+static const struct isprsz_coef filter_coefs = {
16057+ /* For 8-phase 4-tap horizontal filter: */
16058+ {
16059+ 0x0000, 0x0100, 0x0000, 0x0000,
16060+ 0x03FA, 0x00F6, 0x0010, 0x0000,
16061+ 0x03F9, 0x00DB, 0x002C, 0x0000,
16062+ 0x03FB, 0x00B3, 0x0053, 0x03FF,
16063+ 0x03FD, 0x0082, 0x0084, 0x03FD,
16064+ 0x03FF, 0x0053, 0x00B3, 0x03FB,
16065+ 0x0000, 0x002C, 0x00DB, 0x03F9,
16066+ 0x0000, 0x0010, 0x00F6, 0x03FA
16067+ },
16068+ /* For 8-phase 4-tap vertical filter: */
16069+ {
16070+ 0x0000, 0x0100, 0x0000, 0x0000,
16071+ 0x03FA, 0x00F6, 0x0010, 0x0000,
16072+ 0x03F9, 0x00DB, 0x002C, 0x0000,
16073+ 0x03FB, 0x00B3, 0x0053, 0x03FF,
16074+ 0x03FD, 0x0082, 0x0084, 0x03FD,
16075+ 0x03FF, 0x0053, 0x00B3, 0x03FB,
16076+ 0x0000, 0x002C, 0x00DB, 0x03F9,
16077+ 0x0000, 0x0010, 0x00F6, 0x03FA
16078+ },
16079+ /* For 4-phase 7-tap horizontal filter: */
16080+ #define DUMMY 0
16081+ {
16082+ 0x0004, 0x0023, 0x005A, 0x0058, 0x0023, 0x0004, 0x0000, DUMMY,
16083+ 0x0002, 0x0018, 0x004d, 0x0060, 0x0031, 0x0008, 0x0000, DUMMY,
16084+ 0x0001, 0x000f, 0x003f, 0x0062, 0x003f, 0x000f, 0x0001, DUMMY,
16085+ 0x0000, 0x0008, 0x0031, 0x0060, 0x004d, 0x0018, 0x0002, DUMMY
16086+ },
16087+ /* For 4-phase 7-tap vertical filter: */
16088+ {
16089+ 0x0004, 0x0023, 0x005A, 0x0058, 0x0023, 0x0004, 0x0000, DUMMY,
16090+ 0x0002, 0x0018, 0x004d, 0x0060, 0x0031, 0x0008, 0x0000, DUMMY,
16091+ 0x0001, 0x000f, 0x003f, 0x0062, 0x003f, 0x000f, 0x0001, DUMMY,
16092+ 0x0000, 0x0008, 0x0031, 0x0060, 0x004d, 0x0018, 0x0002, DUMMY
16093+ }
16094+ /*
16095+ * The dummy padding is required in 7-tap mode because of how the
16096+ * registers are arranged physically.
16097+ */
16098+ #undef DUMMY
16099+};
16100+
16101+/*
16102+ * __resizer_get_format - helper function for getting resizer format
16103+ * @res : pointer to resizer private structure
16104+ * @pad : pad number
16105+ * @fh : V4L2 subdev file handle
16106+ * @which : wanted subdev format
16107+ * return zero
16108+ */
16109+static struct v4l2_mbus_framefmt *
16110+__resizer_get_format(struct isp_res_device *res, struct v4l2_subdev_fh *fh,
16111+ unsigned int pad, enum v4l2_subdev_format_whence which)
16112+{
16113+ if (which == V4L2_SUBDEV_FORMAT_TRY)
16114+ return v4l2_subdev_get_try_format(fh, pad);
16115+ else
16116+ return &res->formats[pad];
16117+}
16118+
16119+/*
16120+ * __resizer_get_crop - helper function for getting resizer crop rectangle
16121+ * @res : pointer to resizer private structure
16122+ * @fh : V4L2 subdev file handle
16123+ * @which : wanted subdev crop rectangle
16124+ */
16125+static struct v4l2_rect *
16126+__resizer_get_crop(struct isp_res_device *res, struct v4l2_subdev_fh *fh,
16127+ enum v4l2_subdev_format_whence which)
16128+{
16129+ if (which == V4L2_SUBDEV_FORMAT_TRY)
16130+ return v4l2_subdev_get_try_crop(fh, RESZ_PAD_SINK);
16131+ else
16132+ return &res->crop.request;
16133+}
16134+
16135+/*
16136+ * resizer_set_filters - Set resizer filters
16137+ * @res: Device context.
16138+ * @h_coeff: horizontal coefficient
16139+ * @v_coeff: vertical coefficient
16140+ * Return none
16141+ */
16142+static void resizer_set_filters(struct isp_res_device *res, const u16 *h_coeff,
16143+ const u16 *v_coeff)
16144+{
16145+ struct isp_device *isp = to_isp_device(res);
16146+ u32 startaddr_h, startaddr_v, tmp_h, tmp_v;
16147+ int i;
16148+
16149+ startaddr_h = ISPRSZ_HFILT10;
16150+ startaddr_v = ISPRSZ_VFILT10;
16151+
16152+ for (i = 0; i < COEFF_CNT; i += 2) {
16153+ tmp_h = h_coeff[i] |
16154+ (h_coeff[i + 1] << ISPRSZ_HFILT_COEF1_SHIFT);
16155+ tmp_v = v_coeff[i] |
16156+ (v_coeff[i + 1] << ISPRSZ_VFILT_COEF1_SHIFT);
16157+ isp_reg_writel(isp, tmp_h, OMAP3_ISP_IOMEM_RESZ, startaddr_h);
16158+ isp_reg_writel(isp, tmp_v, OMAP3_ISP_IOMEM_RESZ, startaddr_v);
16159+ startaddr_h += 4;
16160+ startaddr_v += 4;
16161+ }
16162+}
16163+
16164+/*
16165+ * resizer_set_bilinear - Chrominance horizontal algorithm select
16166+ * @res: Device context.
16167+ * @type: Filtering interpolation type.
16168+ *
16169+ * Filtering that is same as luminance processing is
16170+ * intended only for downsampling, and bilinear interpolation
16171+ * is intended only for upsampling.
16172+ */
16173+static void resizer_set_bilinear(struct isp_res_device *res,
16174+ enum resizer_chroma_algo type)
16175+{
16176+ struct isp_device *isp = to_isp_device(res);
16177+
16178+ if (type == RSZ_BILINEAR)
16179+ isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
16180+ ISPRSZ_CNT_CBILIN);
16181+ else
16182+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
16183+ ISPRSZ_CNT_CBILIN);
16184+}
16185+
16186+/*
16187+ * resizer_set_ycpos - Luminance and chrominance order
16188+ * @res: Device context.
16189+ * @order: order type.
16190+ */
16191+static void resizer_set_ycpos(struct isp_res_device *res,
16192+ enum v4l2_mbus_pixelcode pixelcode)
16193+{
16194+ struct isp_device *isp = to_isp_device(res);
16195+
16196+ switch (pixelcode) {
16197+ case V4L2_MBUS_FMT_YUYV8_1X16:
16198+ isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
16199+ ISPRSZ_CNT_YCPOS);
16200+ break;
16201+ case V4L2_MBUS_FMT_UYVY8_1X16:
16202+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
16203+ ISPRSZ_CNT_YCPOS);
16204+ break;
16205+ default:
16206+ return;
16207+ }
16208+}
16209+
16210+/*
16211+ * resizer_set_phase - Setup horizontal and vertical starting phase
16212+ * @res: Device context.
16213+ * @h_phase: horizontal phase parameters.
16214+ * @v_phase: vertical phase parameters.
16215+ *
16216+ * Horizontal and vertical phase range is 0 to 7
16217+ */
16218+static void resizer_set_phase(struct isp_res_device *res, u32 h_phase,
16219+ u32 v_phase)
16220+{
16221+ struct isp_device *isp = to_isp_device(res);
16222+ u32 rgval = 0;
16223+
16224+ rgval = isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
16225+ ~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK);
16226+ rgval |= (h_phase << ISPRSZ_CNT_HSTPH_SHIFT) & ISPRSZ_CNT_HSTPH_MASK;
16227+ rgval |= (v_phase << ISPRSZ_CNT_VSTPH_SHIFT) & ISPRSZ_CNT_VSTPH_MASK;
16228+
16229+ isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT);
16230+}
16231+
16232+/*
16233+ * resizer_set_luma - Setup luminance enhancer parameters
16234+ * @res: Device context.
16235+ * @luma: Structure for luminance enhancer parameters.
16236+ *
16237+ * Algorithm select:
16238+ * 0x0: Disable
16239+ * 0x1: [-1 2 -1]/2 high-pass filter
16240+ * 0x2: [-1 -2 6 -2 -1]/4 high-pass filter
16241+ *
16242+ * Maximum gain:
16243+ * The data is coded in U4Q4 representation.
16244+ *
16245+ * Slope:
16246+ * The data is coded in U4Q4 representation.
16247+ *
16248+ * Coring offset:
16249+ * The data is coded in U8Q0 representation.
16250+ *
16251+ * The new luminance value is computed as:
16252+ * Y += HPF(Y) x max(GAIN, (HPF(Y) - CORE) x SLOP + 8) >> 4.
16253+ */
16254+static void resizer_set_luma(struct isp_res_device *res,
16255+ struct resizer_luma_yenh *luma)
16256+{
16257+ struct isp_device *isp = to_isp_device(res);
16258+ u32 rgval = 0;
16259+
16260+ rgval = (luma->algo << ISPRSZ_YENH_ALGO_SHIFT)
16261+ & ISPRSZ_YENH_ALGO_MASK;
16262+ rgval |= (luma->gain << ISPRSZ_YENH_GAIN_SHIFT)
16263+ & ISPRSZ_YENH_GAIN_MASK;
16264+ rgval |= (luma->slope << ISPRSZ_YENH_SLOP_SHIFT)
16265+ & ISPRSZ_YENH_SLOP_MASK;
16266+ rgval |= (luma->core << ISPRSZ_YENH_CORE_SHIFT)
16267+ & ISPRSZ_YENH_CORE_MASK;
16268+
16269+ isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH);
16270+}
16271+
16272+/*
16273+ * resizer_set_source - Input source select
16274+ * @res: Device context.
16275+ * @source: Input source type
16276+ *
16277+ * If this field is set to RESIZER_INPUT_VP, the resizer input is fed from
16278+ * Preview/CCDC engine, otherwise from memory.
16279+ */
16280+static void resizer_set_source(struct isp_res_device *res,
16281+ enum resizer_input_entity source)
16282+{
16283+ struct isp_device *isp = to_isp_device(res);
16284+
16285+ if (source == RESIZER_INPUT_MEMORY)
16286+ isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
16287+ ISPRSZ_CNT_INPSRC);
16288+ else
16289+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
16290+ ISPRSZ_CNT_INPSRC);
16291+}
16292+
16293+/*
16294+ * resizer_set_ratio - Setup horizontal and vertical resizing value
16295+ * @res: Device context.
16296+ * @ratio: Structure for ratio parameters.
16297+ *
16298+ * Resizing range from 64 to 1024
16299+ */
16300+static void resizer_set_ratio(struct isp_res_device *res,
16301+ const struct resizer_ratio *ratio)
16302+{
16303+ struct isp_device *isp = to_isp_device(res);
16304+ const u16 *h_filter, *v_filter;
16305+ u32 rgval = 0;
16306+
16307+ rgval = isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
16308+ ~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK);
16309+ rgval |= ((ratio->horz - 1) << ISPRSZ_CNT_HRSZ_SHIFT)
16310+ & ISPRSZ_CNT_HRSZ_MASK;
16311+ rgval |= ((ratio->vert - 1) << ISPRSZ_CNT_VRSZ_SHIFT)
16312+ & ISPRSZ_CNT_VRSZ_MASK;
16313+ isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT);
16314+
16315+ /* prepare horizontal filter coefficients */
16316+ if (ratio->horz > MID_RESIZE_VALUE)
16317+ h_filter = &filter_coefs.h_filter_coef_7tap[0];
16318+ else
16319+ h_filter = &filter_coefs.h_filter_coef_4tap[0];
16320+
16321+ /* prepare vertical filter coefficients */
16322+ if (ratio->vert > MID_RESIZE_VALUE)
16323+ v_filter = &filter_coefs.v_filter_coef_7tap[0];
16324+ else
16325+ v_filter = &filter_coefs.v_filter_coef_4tap[0];
16326+
16327+ resizer_set_filters(res, h_filter, v_filter);
16328+}
16329+
16330+/*
16331+ * resizer_set_dst_size - Setup the output height and width
16332+ * @res: Device context.
16333+ * @width: Output width.
16334+ * @height: Output height.
16335+ *
16336+ * Width :
16337+ * The value must be EVEN.
16338+ *
16339+ * Height:
16340+ * The number of bytes written to SDRAM must be
16341+ * a multiple of 16-bytes if the vertical resizing factor
16342+ * is greater than 1x (upsizing)
16343+ */
16344+static void resizer_set_output_size(struct isp_res_device *res,
16345+ u32 width, u32 height)
16346+{
16347+ struct isp_device *isp = to_isp_device(res);
16348+ u32 rgval = 0;
16349+
16350+ dev_dbg(isp->dev, "Output size[w/h]: %dx%d\n", width, height);
16351+ rgval = (width << ISPRSZ_OUT_SIZE_HORZ_SHIFT)
16352+ & ISPRSZ_OUT_SIZE_HORZ_MASK;
16353+ rgval |= (height << ISPRSZ_OUT_SIZE_VERT_SHIFT)
16354+ & ISPRSZ_OUT_SIZE_VERT_MASK;
16355+ isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE);
16356+}
16357+
16358+/*
16359+ * resizer_set_output_offset - Setup memory offset for the output lines.
16360+ * @res: Device context.
16361+ * @offset: Memory offset.
16362+ *
16363+ * The 5 LSBs are forced to be zeros by the hardware to align on a 32-byte
16364+ * boundary; the 5 LSBs are read-only. For optimal use of SDRAM bandwidth,
16365+ * the SDRAM line offset must be set on a 256-byte boundary
16366+ */
16367+static void resizer_set_output_offset(struct isp_res_device *res, u32 offset)
16368+{
16369+ struct isp_device *isp = to_isp_device(res);
16370+
16371+ isp_reg_writel(isp, offset, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF);
16372+}
16373+
16374+/*
16375+ * resizer_set_start - Setup vertical and horizontal start position
16376+ * @res: Device context.
16377+ * @left: Horizontal start position.
16378+ * @top: Vertical start position.
16379+ *
16380+ * Vertical start line:
16381+ * This field makes sense only when the resizer obtains its input
16382+ * from the preview engine/CCDC
16383+ *
16384+ * Horizontal start pixel:
16385+ * Pixels are coded on 16 bits for YUV and 8 bits for color separate data.
16386+ * When the resizer gets its input from SDRAM, this field must be set
16387+ * to <= 15 for YUV 16-bit data and <= 31 for 8-bit color separate data
16388+ */
16389+static void resizer_set_start(struct isp_res_device *res, u32 left, u32 top)
16390+{
16391+ struct isp_device *isp = to_isp_device(res);
16392+ u32 rgval = 0;
16393+
16394+ rgval = (left << ISPRSZ_IN_START_HORZ_ST_SHIFT)
16395+ & ISPRSZ_IN_START_HORZ_ST_MASK;
16396+ rgval |= (top << ISPRSZ_IN_START_VERT_ST_SHIFT)
16397+ & ISPRSZ_IN_START_VERT_ST_MASK;
16398+
16399+ isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START);
16400+}
16401+
16402+/*
16403+ * resizer_set_input_size - Setup the input size
16404+ * @res: Device context.
16405+ * @width: The range is 0 to 4095 pixels
16406+ * @height: The range is 0 to 4095 lines
16407+ */
16408+static void resizer_set_input_size(struct isp_res_device *res,
16409+ u32 width, u32 height)
16410+{
16411+ struct isp_device *isp = to_isp_device(res);
16412+ u32 rgval = 0;
16413+
16414+ dev_dbg(isp->dev, "Input size[w/h]: %dx%d\n", width, height);
16415+
16416+ rgval = (width << ISPRSZ_IN_SIZE_HORZ_SHIFT)
16417+ & ISPRSZ_IN_SIZE_HORZ_MASK;
16418+ rgval |= (height << ISPRSZ_IN_SIZE_VERT_SHIFT)
16419+ & ISPRSZ_IN_SIZE_VERT_MASK;
16420+
16421+ isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE);
16422+}
16423+
16424+/*
16425+ * resizer_set_src_offs - Setup the memory offset for the input lines
16426+ * @res: Device context.
16427+ * @offset: Memory offset.
16428+ *
16429+ * The 5 LSBs are forced to be zeros by the hardware to align on a 32-byte
16430+ * boundary; the 5 LSBs are read-only. This field must be programmed to be
16431+ * 0x0 if the resizer input is from preview engine/CCDC.
16432+ */
16433+static void resizer_set_input_offset(struct isp_res_device *res, u32 offset)
16434+{
16435+ struct isp_device *isp = to_isp_device(res);
16436+
16437+ isp_reg_writel(isp, offset, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF);
16438+}
16439+
16440+/*
16441+ * resizer_set_intype - Input type select
16442+ * @res: Device context.
16443+ * @type: Pixel format type.
16444+ */
16445+static void resizer_set_intype(struct isp_res_device *res,
16446+ enum resizer_colors_type type)
16447+{
16448+ struct isp_device *isp = to_isp_device(res);
16449+
16450+ if (type == RSZ_COLOR8)
16451+ isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
16452+ ISPRSZ_CNT_INPTYP);
16453+ else
16454+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
16455+ ISPRSZ_CNT_INPTYP);
16456+}
16457+
16458+/*
16459+ * __resizer_set_inaddr - Helper function for set input address
16460+ * @res : pointer to resizer private data structure
16461+ * @addr: input address
16462+ * return none
16463+ */
16464+static void __resizer_set_inaddr(struct isp_res_device *res, u32 addr)
16465+{
16466+ struct isp_device *isp = to_isp_device(res);
16467+
16468+ isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);
16469+}
16470+
16471+/*
16472+ * The data rate at the horizontal resizer output must not exceed half the
16473+ * functional clock or 100 MP/s, whichever is lower. According to the TRM
16474+ * there's no similar requirement for the vertical resizer output. However
16475+ * experience showed that vertical upscaling by 4 leads to SBL overflows (with
16476+ * data rates at the resizer output exceeding 300 MP/s). Limiting the resizer
16477+ * output data rate to the functional clock or 200 MP/s, whichever is lower,
16478+ * seems to get rid of SBL overflows.
16479+ *
16480+ * The maximum data rate at the output of the horizontal resizer can thus be
16481+ * computed with
16482+ *
16483+ * max intermediate rate <= L3 clock * input height / output height
16484+ * max intermediate rate <= L3 clock / 2
16485+ *
16486+ * The maximum data rate at the resizer input is then
16487+ *
16488+ * max input rate <= max intermediate rate * input width / output width
16489+ *
16490+ * where the input width and height are the resizer input crop rectangle size.
16491+ * The TRM doesn't clearly explain if that's a maximum instant data rate or a
16492+ * maximum average data rate.
16493+ */
16494+void omap3isp_resizer_max_rate(struct isp_res_device *res,
16495+ unsigned int *max_rate)
16496+{
16497+ struct isp_pipeline *pipe = to_isp_pipeline(&res->subdev.entity);
16498+ const struct v4l2_mbus_framefmt *ofmt = &res->formats[RESZ_PAD_SOURCE];
16499+ unsigned long limit = min(pipe->l3_ick, 200000000UL);
16500+ unsigned long clock;
16501+
16502+ clock = div_u64((u64)limit * res->crop.active.height, ofmt->height);
16503+ clock = min(clock, limit / 2);
16504+ *max_rate = div_u64((u64)clock * res->crop.active.width, ofmt->width);
16505+}
16506+
16507+/*
16508+ * When the resizer processes images from memory, the driver must slow down read
16509+ * requests on the input to at least comply with the internal data rate
16510+ * requirements. If the application real-time requirements can cope with slower
16511+ * processing, the resizer can be slowed down even more to put less pressure on
16512+ * the overall system.
16513+ *
16514+ * When the resizer processes images on the fly (either from the CCDC or the
16515+ * preview module), the same data rate requirements apply but they can't be
16516+ * enforced at the resizer level. The image input module (sensor, CCP2 or
16517+ * preview module) must not provide image data faster than the resizer can
16518+ * process.
16519+ *
16520+ * For live image pipelines, the data rate is set by the frame format, size and
16521+ * rate. The sensor output frame rate must not exceed the maximum resizer data
16522+ * rate.
16523+ *
16524+ * The resizer slows down read requests by inserting wait cycles in the SBL
16525+ * requests. The maximum number of 256-byte requests per second can be computed
16526+ * as (the data rate is multiplied by 2 to convert from pixels per second to
16527+ * bytes per second)
16528+ *
16529+ * request per second = data rate * 2 / 256
16530+ * cycles per request = cycles per second / requests per second
16531+ *
16532+ * The number of cycles per second is controlled by the L3 clock, leading to
16533+ *
16534+ * cycles per request = L3 frequency / 2 * 256 / data rate
16535+ */
16536+static void resizer_adjust_bandwidth(struct isp_res_device *res)
16537+{
16538+ struct isp_pipeline *pipe = to_isp_pipeline(&res->subdev.entity);
16539+ struct isp_device *isp = to_isp_device(res);
16540+ unsigned long l3_ick = pipe->l3_ick;
16541+ struct v4l2_fract *timeperframe;
16542+ unsigned int cycles_per_frame;
16543+ unsigned int requests_per_frame;
16544+ unsigned int cycles_per_request;
16545+ unsigned int granularity;
16546+ unsigned int minimum;
16547+ unsigned int maximum;
16548+ unsigned int value;
16549+
16550+ if (res->input != RESIZER_INPUT_MEMORY) {
16551+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
16552+ ISPSBL_SDR_REQ_RSZ_EXP_MASK);
16553+ return;
16554+ }
16555+
16556+ switch (isp->revision) {
16557+ case ISP_REVISION_1_0:
16558+ case ISP_REVISION_2_0:
16559+ default:
16560+ granularity = 1024;
16561+ break;
16562+
16563+ case ISP_REVISION_15_0:
16564+ granularity = 32;
16565+ break;
16566+ }
16567+
16568+ /* Compute the minimum number of cycles per request, based on the
16569+ * pipeline maximum data rate. This is an absolute lower bound if we
16570+ * don't want SBL overflows, so round the value up.
16571+ */
16572+ cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1,
16573+ pipe->max_rate);
16574+ minimum = DIV_ROUND_UP(cycles_per_request, granularity);
16575+
16576+ /* Compute the maximum number of cycles per request, based on the
16577+ * requested frame rate. This is a soft upper bound to achieve a frame
16578+ * rate equal or higher than the requested value, so round the value
16579+ * down.
16580+ */
16581+ timeperframe = &pipe->max_timeperframe;
16582+
16583+ requests_per_frame = DIV_ROUND_UP(res->crop.active.width * 2, 256)
16584+ * res->crop.active.height;
16585+ cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator,
16586+ timeperframe->denominator);
16587+ cycles_per_request = cycles_per_frame / requests_per_frame;
16588+
16589+ maximum = cycles_per_request / granularity;
16590+
16591+ value = max(minimum, maximum);
16592+
16593+ dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value);
16594+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
16595+ ISPSBL_SDR_REQ_RSZ_EXP_MASK,
16596+ value << ISPSBL_SDR_REQ_RSZ_EXP_SHIFT);
16597+}
16598+
16599+/*
16600+ * omap3isp_resizer_busy - Checks if ISP resizer is busy.
16601+ *
16602+ * Returns busy field from ISPRSZ_PCR register.
16603+ */
16604+int omap3isp_resizer_busy(struct isp_res_device *res)
16605+{
16606+ struct isp_device *isp = to_isp_device(res);
16607+
16608+ return isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) &
16609+ ISPRSZ_PCR_BUSY;
16610+}
16611+
16612+/*
16613+ * resizer_set_inaddr - Sets the memory address of the input frame.
16614+ * @addr: 32bit memory address aligned on 32byte boundary.
16615+ */
16616+static void resizer_set_inaddr(struct isp_res_device *res, u32 addr)
16617+{
16618+ res->addr_base = addr;
16619+
16620+ /* This will handle crop settings in stream off state */
16621+ if (res->crop_offset)
16622+ addr += res->crop_offset & ~0x1f;
16623+
16624+ __resizer_set_inaddr(res, addr);
16625+}
16626+
16627+/*
16628+ * Configures the memory address to which the output frame is written.
16629+ * @addr: 32bit memory address aligned on 32byte boundary.
16630+ * Note: For SBL efficiency reasons the address should be on a 256-byte
16631+ * boundary.
16632+ */
16633+static void resizer_set_outaddr(struct isp_res_device *res, u32 addr)
16634+{
16635+ struct isp_device *isp = to_isp_device(res);
16636+
16637+ /*
16638+ * Set output address. This needs to be in its own function
16639+ * because it changes often.
16640+ */
16641+ isp_reg_writel(isp, addr << ISPRSZ_SDR_OUTADD_ADDR_SHIFT,
16642+ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD);
16643+}
16644+
16645+/*
16646+ * resizer_print_status - Prints the values of the resizer module registers.
16647+ */
16648+#define RSZ_PRINT_REGISTER(isp, name)\
16649+ dev_dbg(isp->dev, "###RSZ " #name "=0x%08x\n", \
16650+ isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_##name))
16651+
16652+static void resizer_print_status(struct isp_res_device *res)
16653+{
16654+ struct isp_device *isp = to_isp_device(res);
16655+
16656+ dev_dbg(isp->dev, "-------------Resizer Register dump----------\n");
16657+
16658+ RSZ_PRINT_REGISTER(isp, PCR);
16659+ RSZ_PRINT_REGISTER(isp, CNT);
16660+ RSZ_PRINT_REGISTER(isp, OUT_SIZE);
16661+ RSZ_PRINT_REGISTER(isp, IN_START);
16662+ RSZ_PRINT_REGISTER(isp, IN_SIZE);
16663+ RSZ_PRINT_REGISTER(isp, SDR_INADD);
16664+ RSZ_PRINT_REGISTER(isp, SDR_INOFF);
16665+ RSZ_PRINT_REGISTER(isp, SDR_OUTADD);
16666+ RSZ_PRINT_REGISTER(isp, SDR_OUTOFF);
16667+ RSZ_PRINT_REGISTER(isp, YENH);
16668+
16669+ dev_dbg(isp->dev, "--------------------------------------------\n");
16670+}
16671+
16672+/*
16673+ * resizer_calc_ratios - Helper function for calculate resizer ratios
16674+ * @res: pointer to resizer private data structure
16675+ * @input: input frame size
16676+ * @output: output frame size
16677+ * @ratio : return calculated ratios
16678+ * return none
16679+ *
16680+ * The resizer uses a polyphase sample rate converter. The upsampling filter
16681+ * has a fixed number of phases that depend on the resizing ratio. As the ratio
16682+ * computation depends on the number of phases, we need to compute a first
16683+ * approximation and then refine it.
16684+ *
16685+ * The input/output/ratio relationship is given by the OMAP34xx TRM:
16686+ *
16687+ * - 8-phase, 4-tap mode (RSZ = 64 ~ 512)
16688+ * iw = (32 * sph + (ow - 1) * hrsz + 16) >> 8 + 7
16689+ * ih = (32 * spv + (oh - 1) * vrsz + 16) >> 8 + 4
16690+ * - 4-phase, 7-tap mode (RSZ = 513 ~ 1024)
16691+ * iw = (64 * sph + (ow - 1) * hrsz + 32) >> 8 + 7
16692+ * ih = (64 * spv + (oh - 1) * vrsz + 32) >> 8 + 7
16693+ *
16694+ * iw and ih are the input width and height after cropping. Those equations need
16695+ * to be satisfied exactly for the resizer to work correctly.
16696+ *
16697+ * Reverting the equations, we can compute the resizing ratios with
16698+ *
16699+ * - 8-phase, 4-tap mode
16700+ * hrsz = ((iw - 7) * 256 - 16 - 32 * sph) / (ow - 1)
16701+ * vrsz = ((ih - 4) * 256 - 16 - 32 * spv) / (oh - 1)
16702+ * - 4-phase, 7-tap mode
16703+ * hrsz = ((iw - 7) * 256 - 32 - 64 * sph) / (ow - 1)
16704+ * vrsz = ((ih - 7) * 256 - 32 - 64 * spv) / (oh - 1)
16705+ *
16706+ * The ratios are integer values, and must be rounded down to ensure that the
16707+ * cropped input size is not bigger than the uncropped input size. As the ratio
16708+ * in 7-tap mode is always smaller than the ratio in 4-tap mode, we can use the
16709+ * 7-tap mode equations to compute a ratio approximation.
16710+ *
16711+ * We first clamp the output size according to the hardware capabilitie to avoid
16712+ * auto-cropping the input more than required to satisfy the TRM equations. The
16713+ * minimum output size is achieved with a scaling factor of 1024. It is thus
16714+ * computed using the 7-tap equations.
16715+ *
16716+ * min ow = ((iw - 7) * 256 - 32 - 64 * sph) / 1024 + 1
16717+ * min oh = ((ih - 7) * 256 - 32 - 64 * spv) / 1024 + 1
16718+ *
16719+ * Similarly, the maximum output size is achieved with a scaling factor of 64
16720+ * and computed using the 4-tap equations.
16721+ *
16722+ * max ow = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / 64 + 1
16723+ * max oh = ((ih - 4) * 256 + 255 - 16 - 32 * spv) / 64 + 1
16724+ *
16725+ * The additional +255 term compensates for the round down operation performed
16726+ * by the TRM equations when shifting the value right by 8 bits.
16727+ *
16728+ * We then compute and clamp the ratios (x1/4 ~ x4). Clamping the output size to
16729+ * the maximum value guarantees that the ratio value will never be smaller than
16730+ * the minimum, but it could still slightly exceed the maximum. Clamping the
16731+ * ratio will thus result in a resizing factor slightly larger than the
16732+ * requested value.
16733+ *
16734+ * To accomodate that, and make sure the TRM equations are satisfied exactly, we
16735+ * compute the input crop rectangle as the last step.
16736+ *
16737+ * As if the situation wasn't complex enough, the maximum output width depends
16738+ * on the vertical resizing ratio. Fortunately, the output height doesn't
16739+ * depend on the horizontal resizing ratio. We can then start by computing the
16740+ * output height and the vertical ratio, and then move to computing the output
16741+ * width and the horizontal ratio.
16742+ */
16743+static void resizer_calc_ratios(struct isp_res_device *res,
16744+ struct v4l2_rect *input,
16745+ struct v4l2_mbus_framefmt *output,
16746+ struct resizer_ratio *ratio)
16747+{
16748+ struct isp_device *isp = to_isp_device(res);
16749+ const unsigned int spv = DEFAULT_PHASE;
16750+ const unsigned int sph = DEFAULT_PHASE;
16751+ unsigned int upscaled_width;
16752+ unsigned int upscaled_height;
16753+ unsigned int min_width;
16754+ unsigned int min_height;
16755+ unsigned int max_width;
16756+ unsigned int max_height;
16757+ unsigned int width_alignment;
16758+
16759+ /*
16760+ * Clamp the output height based on the hardware capabilities and
16761+ * compute the vertical resizing ratio.
16762+ */
16763+ min_height = ((input->height - 7) * 256 - 32 - 64 * spv) / 1024 + 1;
16764+ min_height = max_t(unsigned int, min_height, MIN_OUT_HEIGHT);
16765+ max_height = ((input->height - 4) * 256 + 255 - 16 - 32 * spv) / 64 + 1;
16766+ max_height = min_t(unsigned int, max_height, MAX_OUT_HEIGHT);
16767+ output->height = clamp(output->height, min_height, max_height);
16768+
16769+ ratio->vert = ((input->height - 7) * 256 - 32 - 64 * spv)
16770+ / (output->height - 1);
16771+ ratio->vert = clamp_t(unsigned int, ratio->vert,
16772+ MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
16773+
16774+ if (ratio->vert <= MID_RESIZE_VALUE) {
16775+ upscaled_height = (output->height - 1) * ratio->vert
16776+ + 32 * spv + 16;
16777+ input->height = (upscaled_height >> 8) + 4;
16778+ } else {
16779+ upscaled_height = (output->height - 1) * ratio->vert
16780+ + 64 * spv + 32;
16781+ input->height = (upscaled_height >> 8) + 7;
16782+ }
16783+
16784+ /*
16785+ * Compute the minimum and maximum output widths based on the hardware
16786+ * capabilities. The maximum depends on the vertical resizing ratio.
16787+ */
16788+ min_width = ((input->width - 7) * 256 - 32 - 64 * sph) / 1024 + 1;
16789+ min_width = max_t(unsigned int, min_width, MIN_OUT_WIDTH);
16790+
16791+ if (ratio->vert <= MID_RESIZE_VALUE) {
16792+ switch (isp->revision) {
16793+ case ISP_REVISION_1_0:
16794+ max_width = MAX_4TAP_OUT_WIDTH_ES1;
16795+ break;
16796+
16797+ case ISP_REVISION_2_0:
16798+ default:
16799+ max_width = MAX_4TAP_OUT_WIDTH_ES2;
16800+ break;
16801+
16802+ case ISP_REVISION_15_0:
16803+ max_width = MAX_4TAP_OUT_WIDTH_3630;
16804+ break;
16805+ }
16806+ } else {
16807+ switch (isp->revision) {
16808+ case ISP_REVISION_1_0:
16809+ max_width = MAX_7TAP_OUT_WIDTH_ES1;
16810+ break;
16811+
16812+ case ISP_REVISION_2_0:
16813+ default:
16814+ max_width = MAX_7TAP_OUT_WIDTH_ES2;
16815+ break;
16816+
16817+ case ISP_REVISION_15_0:
16818+ max_width = MAX_7TAP_OUT_WIDTH_3630;
16819+ break;
16820+ }
16821+ }
16822+ max_width = min(((input->width - 7) * 256 + 255 - 16 - 32 * sph) / 64
16823+ + 1, max_width);
16824+
16825+ /*
16826+ * The output width must be even, and must be a multiple of 16 bytes
16827+ * when upscaling vertically. Clamp the output width to the valid range.
16828+ * Take the alignment into account (the maximum width in 7-tap mode on
16829+ * ES2 isn't a multiple of 8) and align the result up to make sure it
16830+ * won't be smaller than the minimum.
16831+ */
16832+ width_alignment = ratio->vert < 256 ? 8 : 2;
16833+ output->width = clamp(output->width, min_width,
16834+ max_width & ~(width_alignment - 1));
16835+ output->width = ALIGN(output->width, width_alignment);
16836+
16837+ ratio->horz = ((input->width - 7) * 256 - 32 - 64 * sph)
16838+ / (output->width - 1);
16839+ ratio->horz = clamp_t(unsigned int, ratio->horz,
16840+ MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
16841+
16842+ if (ratio->horz <= MID_RESIZE_VALUE) {
16843+ upscaled_width = (output->width - 1) * ratio->horz
16844+ + 32 * sph + 16;
16845+ input->width = (upscaled_width >> 8) + 7;
16846+ } else {
16847+ upscaled_width = (output->width - 1) * ratio->horz
16848+ + 64 * sph + 32;
16849+ input->width = (upscaled_width >> 8) + 7;
16850+ }
16851+}
16852+
16853+/*
16854+ * resizer_set_crop_params - Setup hardware with cropping parameters
16855+ * @res : resizer private structure
16856+ * @crop_rect : current crop rectangle
16857+ * @ratio : resizer ratios
16858+ * return none
16859+ */
16860+static void resizer_set_crop_params(struct isp_res_device *res,
16861+ const struct v4l2_mbus_framefmt *input,
16862+ const struct v4l2_mbus_framefmt *output)
16863+{
16864+ resizer_set_ratio(res, &res->ratio);
16865+
16866+ /* Set chrominance horizontal algorithm */
16867+ if (res->ratio.horz >= RESIZE_DIVISOR)
16868+ resizer_set_bilinear(res, RSZ_THE_SAME);
16869+ else
16870+ resizer_set_bilinear(res, RSZ_BILINEAR);
16871+
16872+ resizer_adjust_bandwidth(res);
16873+
16874+ if (res->input == RESIZER_INPUT_MEMORY) {
16875+ /* Calculate additional offset for crop */
16876+ res->crop_offset = (res->crop.active.top * input->width +
16877+ res->crop.active.left) * 2;
16878+ /*
16879+ * Write lowest 4 bits of horizontal pixel offset (in pixels),
16880+ * vertical start must be 0.
16881+ */
16882+ resizer_set_start(res, (res->crop_offset / 2) & 0xf, 0);
16883+
16884+ /*
16885+ * Set start (read) address for cropping, in bytes.
16886+ * Lowest 5 bits must be zero.
16887+ */
16888+ __resizer_set_inaddr(res,
16889+ res->addr_base + (res->crop_offset & ~0x1f));
16890+ } else {
16891+ /*
16892+ * Set vertical start line and horizontal starting pixel.
16893+ * If the input is from CCDC/PREV, horizontal start field is
16894+ * in bytes (twice number of pixels).
16895+ */
16896+ resizer_set_start(res, res->crop.active.left * 2,
16897+ res->crop.active.top);
16898+ /* Input address and offset must be 0 for preview/ccdc input */
16899+ __resizer_set_inaddr(res, 0);
16900+ resizer_set_input_offset(res, 0);
16901+ }
16902+
16903+ /* Set the input size */
16904+ resizer_set_input_size(res, res->crop.active.width,
16905+ res->crop.active.height);
16906+}
16907+
16908+static void resizer_configure(struct isp_res_device *res)
16909+{
16910+ struct v4l2_mbus_framefmt *informat, *outformat;
16911+ struct resizer_luma_yenh luma = {0, 0, 0, 0};
16912+
16913+ resizer_set_source(res, res->input);
16914+
16915+ informat = &res->formats[RESZ_PAD_SINK];
16916+ outformat = &res->formats[RESZ_PAD_SOURCE];
16917+
16918+ /* RESZ_PAD_SINK */
16919+ if (res->input == RESIZER_INPUT_VP)
16920+ resizer_set_input_offset(res, 0);
16921+ else
16922+ resizer_set_input_offset(res, ALIGN(informat->width, 0x10) * 2);
16923+
16924+ /* YUV422 interleaved, default phase, no luma enhancement */
16925+ resizer_set_intype(res, RSZ_YUV422);
16926+ resizer_set_ycpos(res, informat->code);
16927+ resizer_set_phase(res, DEFAULT_PHASE, DEFAULT_PHASE);
16928+ resizer_set_luma(res, &luma);
16929+
16930+ /* RESZ_PAD_SOURCE */
16931+ resizer_set_output_offset(res, ALIGN(outformat->width * 2, 32));
16932+ resizer_set_output_size(res, outformat->width, outformat->height);
16933+
16934+ resizer_set_crop_params(res, informat, outformat);
16935+}
16936+
16937+/* -----------------------------------------------------------------------------
16938+ * Interrupt handling
16939+ */
16940+
16941+static void resizer_enable_oneshot(struct isp_res_device *res)
16942+{
16943+ struct isp_device *isp = to_isp_device(res);
16944+
16945+ isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR,
16946+ ISPRSZ_PCR_ENABLE | ISPRSZ_PCR_ONESHOT);
16947+}
16948+
16949+void omap3isp_resizer_isr_frame_sync(struct isp_res_device *res)
16950+{
16951+ /*
16952+ * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun
16953+ * condition, the module was paused and now we have a buffer queued
16954+ * on the output again. Restart the pipeline if running in continuous
16955+ * mode.
16956+ */
16957+ if (res->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
16958+ res->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
16959+ resizer_enable_oneshot(res);
16960+ isp_video_dmaqueue_flags_clr(&res->video_out);
16961+ }
16962+}
16963+
16964+static void resizer_isr_buffer(struct isp_res_device *res)
16965+{
16966+ struct isp_pipeline *pipe = to_isp_pipeline(&res->subdev.entity);
16967+ struct isp_buffer *buffer;
16968+ int restart = 0;
16969+
16970+ if (res->state == ISP_PIPELINE_STREAM_STOPPED)
16971+ return;
16972+
16973+ /* Complete the output buffer and, if reading from memory, the input
16974+ * buffer.
16975+ */
16976+ buffer = omap3isp_video_buffer_next(&res->video_out, res->error);
16977+ if (buffer != NULL) {
16978+ resizer_set_outaddr(res, buffer->isp_addr);
16979+ restart = 1;
16980+ }
16981+
16982+ pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
16983+
16984+ if (res->input == RESIZER_INPUT_MEMORY) {
16985+ buffer = omap3isp_video_buffer_next(&res->video_in, 0);
16986+ if (buffer != NULL)
16987+ resizer_set_inaddr(res, buffer->isp_addr);
16988+ pipe->state |= ISP_PIPELINE_IDLE_INPUT;
16989+ }
16990+
16991+ if (res->state == ISP_PIPELINE_STREAM_SINGLESHOT) {
16992+ if (isp_pipeline_ready(pipe))
16993+ omap3isp_pipeline_set_stream(pipe,
16994+ ISP_PIPELINE_STREAM_SINGLESHOT);
16995+ } else {
16996+ /* If an underrun occurs, the video queue operation handler will
16997+ * restart the resizer. Otherwise restart it immediately.
16998+ */
16999+ if (restart)
17000+ resizer_enable_oneshot(res);
17001+ }
17002+
17003+ res->error = 0;
17004+}
17005+
17006+/*
17007+ * omap3isp_resizer_isr - ISP resizer interrupt handler
17008+ *
17009+ * Manage the resizer video buffers and configure shadowed and busy-locked
17010+ * registers.
17011+ */
17012+void omap3isp_resizer_isr(struct isp_res_device *res)
17013+{
17014+ struct v4l2_mbus_framefmt *informat, *outformat;
17015+
17016+ if (omap3isp_module_sync_is_stopping(&res->wait, &res->stopping))
17017+ return;
17018+
17019+ if (res->applycrop) {
17020+ outformat = __resizer_get_format(res, NULL, RESZ_PAD_SOURCE,
17021+ V4L2_SUBDEV_FORMAT_ACTIVE);
17022+ informat = __resizer_get_format(res, NULL, RESZ_PAD_SINK,
17023+ V4L2_SUBDEV_FORMAT_ACTIVE);
17024+ resizer_set_crop_params(res, informat, outformat);
17025+ res->applycrop = 0;
17026+ }
17027+
17028+ resizer_isr_buffer(res);
17029+}
17030+
17031+/* -----------------------------------------------------------------------------
17032+ * ISP video operations
17033+ */
17034+
17035+static int resizer_video_queue(struct isp_video *video,
17036+ struct isp_buffer *buffer)
17037+{
17038+ struct isp_res_device *res = &video->isp->isp_res;
17039+
17040+ if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
17041+ resizer_set_inaddr(res, buffer->isp_addr);
17042+
17043+ /*
17044+ * We now have a buffer queued on the output. Despite what the
17045+ * TRM says, the resizer can't be restarted immediately.
17046+ * Enabling it in one shot mode in the middle of a frame (or at
17047+ * least asynchronously to the frame) results in the output
17048+ * being shifted randomly left/right and up/down, as if the
17049+ * hardware didn't synchronize itself to the beginning of the
17050+ * frame correctly.
17051+ *
17052+ * Restart the resizer on the next sync interrupt if running in
17053+ * continuous mode or when starting the stream.
17054+ */
17055+ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
17056+ resizer_set_outaddr(res, buffer->isp_addr);
17057+
17058+ return 0;
17059+}
17060+
17061+static const struct isp_video_operations resizer_video_ops = {
17062+ .queue = resizer_video_queue,
17063+};
17064+
17065+/* -----------------------------------------------------------------------------
17066+ * V4L2 subdev operations
17067+ */
17068+
17069+/*
17070+ * resizer_set_stream - Enable/Disable streaming on resizer subdev
17071+ * @sd: ISP resizer V4L2 subdev
17072+ * @enable: 1 == Enable, 0 == Disable
17073+ *
17074+ * The resizer hardware can't be enabled without a memory buffer to write to.
17075+ * As the s_stream operation is called in response to a STREAMON call without
17076+ * any buffer queued yet, just update the state field and return immediately.
17077+ * The resizer will be enabled in resizer_video_queue().
17078+ */
17079+static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
17080+{
17081+ struct isp_res_device *res = v4l2_get_subdevdata(sd);
17082+ struct isp_video *video_out = &res->video_out;
17083+ struct isp_device *isp = to_isp_device(res);
17084+ struct device *dev = to_device(res);
17085+
17086+ if (res->state == ISP_PIPELINE_STREAM_STOPPED) {
17087+ if (enable == ISP_PIPELINE_STREAM_STOPPED)
17088+ return 0;
17089+
17090+ omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER);
17091+ resizer_configure(res);
17092+ res->error = 0;
17093+ resizer_print_status(res);
17094+ }
17095+
17096+ switch (enable) {
17097+ case ISP_PIPELINE_STREAM_CONTINUOUS:
17098+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_WRITE);
17099+ if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
17100+ resizer_enable_oneshot(res);
17101+ isp_video_dmaqueue_flags_clr(video_out);
17102+ }
17103+ break;
17104+
17105+ case ISP_PIPELINE_STREAM_SINGLESHOT:
17106+ if (res->input == RESIZER_INPUT_MEMORY)
17107+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_READ);
17108+ omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_WRITE);
17109+
17110+ resizer_enable_oneshot(res);
17111+ break;
17112+
17113+ case ISP_PIPELINE_STREAM_STOPPED:
17114+ if (omap3isp_module_sync_idle(&sd->entity, &res->wait,
17115+ &res->stopping))
17116+ dev_dbg(dev, "%s: module stop timeout.\n", sd->name);
17117+ omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_RESIZER_READ |
17118+ OMAP3_ISP_SBL_RESIZER_WRITE);
17119+ omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_RESIZER);
17120+ isp_video_dmaqueue_flags_clr(video_out);
17121+ break;
17122+ }
17123+
17124+ res->state = enable;
17125+ return 0;
17126+}
17127+
17128+/*
17129+ * resizer_g_crop - handle get crop subdev operation
17130+ * @sd : pointer to v4l2 subdev structure
17131+ * @pad : subdev pad
17132+ * @crop : pointer to crop structure
17133+ * @which : active or try format
17134+ * return zero
17135+ */
17136+static int resizer_g_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
17137+ struct v4l2_subdev_crop *crop)
17138+{
17139+ struct isp_res_device *res = v4l2_get_subdevdata(sd);
17140+ struct v4l2_mbus_framefmt *format;
17141+ struct resizer_ratio ratio;
17142+
17143+ /* Only sink pad has crop capability */
17144+ if (crop->pad != RESZ_PAD_SINK)
17145+ return -EINVAL;
17146+
17147+ format = __resizer_get_format(res, fh, RESZ_PAD_SOURCE, crop->which);
17148+ crop->rect = *__resizer_get_crop(res, fh, crop->which);
17149+ resizer_calc_ratios(res, &crop->rect, format, &ratio);
17150+
17151+ return 0;
17152+}
17153+
17154+/*
17155+ * resizer_try_crop - mangles crop parameters.
17156+ */
17157+static void resizer_try_crop(const struct v4l2_mbus_framefmt *sink,
17158+ const struct v4l2_mbus_framefmt *source,
17159+ struct v4l2_rect *crop)
17160+{
17161+ const unsigned int spv = DEFAULT_PHASE;
17162+ const unsigned int sph = DEFAULT_PHASE;
17163+
17164+ /* Crop rectangle is constrained to the output size so that zoom ratio
17165+ * cannot exceed +/-4.0.
17166+ */
17167+ unsigned int min_width =
17168+ ((32 * sph + (source->width - 1) * 64 + 16) >> 8) + 7;
17169+ unsigned int min_height =
17170+ ((32 * spv + (source->height - 1) * 64 + 16) >> 8) + 4;
17171+ unsigned int max_width =
17172+ ((64 * sph + (source->width - 1) * 1024 + 32) >> 8) + 7;
17173+ unsigned int max_height =
17174+ ((64 * spv + (source->height - 1) * 1024 + 32) >> 8) + 7;
17175+
17176+ crop->width = clamp_t(u32, crop->width, min_width, max_width);
17177+ crop->height = clamp_t(u32, crop->height, min_height, max_height);
17178+
17179+ /* Crop can not go beyond of the input rectangle */
17180+ crop->left = clamp_t(u32, crop->left, 0, sink->width - MIN_IN_WIDTH);
17181+ crop->width = clamp_t(u32, crop->width, MIN_IN_WIDTH,
17182+ sink->width - crop->left);
17183+ crop->top = clamp_t(u32, crop->top, 0, sink->height - MIN_IN_HEIGHT);
17184+ crop->height = clamp_t(u32, crop->height, MIN_IN_HEIGHT,
17185+ sink->height - crop->top);
17186+}
17187+
17188+/*
17189+ * resizer_s_crop - handle set crop subdev operation
17190+ * @sd : pointer to v4l2 subdev structure
17191+ * @pad : subdev pad
17192+ * @crop : pointer to crop structure
17193+ * @which : active or try format
17194+ * return -EINVAL or zero when succeed
17195+ */
17196+static int resizer_s_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
17197+ struct v4l2_subdev_crop *crop)
17198+{
17199+ struct isp_res_device *res = v4l2_get_subdevdata(sd);
17200+ struct isp_device *isp = to_isp_device(res);
17201+ struct v4l2_mbus_framefmt *format_sink, *format_source;
17202+ struct resizer_ratio ratio;
17203+
17204+ /* Only sink pad has crop capability */
17205+ if (crop->pad != RESZ_PAD_SINK)
17206+ return -EINVAL;
17207+
17208+ format_sink = __resizer_get_format(res, fh, RESZ_PAD_SINK,
17209+ crop->which);
17210+ format_source = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
17211+ crop->which);
17212+
17213+ dev_dbg(isp->dev, "%s: L=%d,T=%d,W=%d,H=%d,which=%d\n", __func__,
17214+ crop->rect.left, crop->rect.top, crop->rect.width,
17215+ crop->rect.height, crop->which);
17216+
17217+ dev_dbg(isp->dev, "%s: input=%dx%d, output=%dx%d\n", __func__,
17218+ format_sink->width, format_sink->height,
17219+ format_source->width, format_source->height);
17220+
17221+ resizer_try_crop(format_sink, format_source, &crop->rect);
17222+ *__resizer_get_crop(res, fh, crop->which) = crop->rect;
17223+ resizer_calc_ratios(res, &crop->rect, format_source, &ratio);
17224+
17225+ if (crop->which == V4L2_SUBDEV_FORMAT_TRY)
17226+ return 0;
17227+
17228+ res->ratio = ratio;
17229+ res->crop.active = crop->rect;
17230+
17231+ /*
17232+ * s_crop can be called while streaming is on. In this case
17233+ * the crop values will be set in the next IRQ.
17234+ */
17235+ if (res->state != ISP_PIPELINE_STREAM_STOPPED)
17236+ res->applycrop = 1;
17237+
17238+ return 0;
17239+}
17240+
17241+/* resizer pixel formats */
17242+static const unsigned int resizer_formats[] = {
17243+ V4L2_MBUS_FMT_UYVY8_1X16,
17244+ V4L2_MBUS_FMT_YUYV8_1X16,
17245+};
17246+
17247+static unsigned int resizer_max_in_width(struct isp_res_device *res)
17248+{
17249+ struct isp_device *isp = to_isp_device(res);
17250+
17251+ if (res->input == RESIZER_INPUT_MEMORY) {
17252+ return MAX_IN_WIDTH_MEMORY_MODE;
17253+ } else {
17254+ if (isp->revision == ISP_REVISION_1_0)
17255+ return MAX_IN_WIDTH_ONTHEFLY_MODE_ES1;
17256+ else
17257+ return MAX_IN_WIDTH_ONTHEFLY_MODE_ES2;
17258+ }
17259+}
17260+
17261+/*
17262+ * resizer_try_format - Handle try format by pad subdev method
17263+ * @res : ISP resizer device
17264+ * @fh : V4L2 subdev file handle
17265+ * @pad : pad num
17266+ * @fmt : pointer to v4l2 format structure
17267+ * @which : wanted subdev format
17268+ */
17269+static void resizer_try_format(struct isp_res_device *res,
17270+ struct v4l2_subdev_fh *fh, unsigned int pad,
17271+ struct v4l2_mbus_framefmt *fmt,
17272+ enum v4l2_subdev_format_whence which)
17273+{
17274+ struct v4l2_mbus_framefmt *format;
17275+ struct resizer_ratio ratio;
17276+ struct v4l2_rect crop;
17277+
17278+ switch (pad) {
17279+ case RESZ_PAD_SINK:
17280+ if (fmt->code != V4L2_MBUS_FMT_YUYV8_1X16 &&
17281+ fmt->code != V4L2_MBUS_FMT_UYVY8_1X16)
17282+ fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
17283+
17284+ fmt->width = clamp_t(u32, fmt->width, MIN_IN_WIDTH,
17285+ resizer_max_in_width(res));
17286+ fmt->height = clamp_t(u32, fmt->height, MIN_IN_HEIGHT,
17287+ MAX_IN_HEIGHT);
17288+ break;
17289+
17290+ case RESZ_PAD_SOURCE:
17291+ format = __resizer_get_format(res, fh, RESZ_PAD_SINK, which);
17292+ fmt->code = format->code;
17293+
17294+ crop = *__resizer_get_crop(res, fh, which);
17295+ resizer_calc_ratios(res, &crop, fmt, &ratio);
17296+ break;
17297+ }
17298+
17299+ fmt->colorspace = V4L2_COLORSPACE_JPEG;
17300+ fmt->field = V4L2_FIELD_NONE;
17301+}
17302+
17303+/*
17304+ * resizer_enum_mbus_code - Handle pixel format enumeration
17305+ * @sd : pointer to v4l2 subdev structure
17306+ * @fh : V4L2 subdev file handle
17307+ * @code : pointer to v4l2_subdev_mbus_code_enum structure
17308+ * return -EINVAL or zero on success
17309+ */
17310+static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
17311+ struct v4l2_subdev_fh *fh,
17312+ struct v4l2_subdev_mbus_code_enum *code)
17313+{
17314+ struct isp_res_device *res = v4l2_get_subdevdata(sd);
17315+ struct v4l2_mbus_framefmt *format;
17316+
17317+ if (code->pad == RESZ_PAD_SINK) {
17318+ if (code->index >= ARRAY_SIZE(resizer_formats))
17319+ return -EINVAL;
17320+
17321+ code->code = resizer_formats[code->index];
17322+ } else {
17323+ if (code->index != 0)
17324+ return -EINVAL;
17325+
17326+ format = __resizer_get_format(res, fh, RESZ_PAD_SINK,
17327+ V4L2_SUBDEV_FORMAT_TRY);
17328+ code->code = format->code;
17329+ }
17330+
17331+ return 0;
17332+}
17333+
17334+static int resizer_enum_frame_size(struct v4l2_subdev *sd,
17335+ struct v4l2_subdev_fh *fh,
17336+ struct v4l2_subdev_frame_size_enum *fse)
17337+{
17338+ struct isp_res_device *res = v4l2_get_subdevdata(sd);
17339+ struct v4l2_mbus_framefmt format;
17340+
17341+ if (fse->index != 0)
17342+ return -EINVAL;
17343+
17344+ format.code = fse->code;
17345+ format.width = 1;
17346+ format.height = 1;
17347+ resizer_try_format(res, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
17348+ fse->min_width = format.width;
17349+ fse->min_height = format.height;
17350+
17351+ if (format.code != fse->code)
17352+ return -EINVAL;
17353+
17354+ format.code = fse->code;
17355+ format.width = -1;
17356+ format.height = -1;
17357+ resizer_try_format(res, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
17358+ fse->max_width = format.width;
17359+ fse->max_height = format.height;
17360+
17361+ return 0;
17362+}
17363+
17364+/*
17365+ * resizer_get_format - Handle get format by pads subdev method
17366+ * @sd : pointer to v4l2 subdev structure
17367+ * @fh : V4L2 subdev file handle
17368+ * @fmt : pointer to v4l2 subdev format structure
17369+ * return -EINVAL or zero on sucess
17370+ */
17371+static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
17372+ struct v4l2_subdev_format *fmt)
17373+{
17374+ struct isp_res_device *res = v4l2_get_subdevdata(sd);
17375+ struct v4l2_mbus_framefmt *format;
17376+
17377+ format = __resizer_get_format(res, fh, fmt->pad, fmt->which);
17378+ if (format == NULL)
17379+ return -EINVAL;
17380+
17381+ fmt->format = *format;
17382+ return 0;
17383+}
17384+
17385+/*
17386+ * resizer_set_format - Handle set format by pads subdev method
17387+ * @sd : pointer to v4l2 subdev structure
17388+ * @fh : V4L2 subdev file handle
17389+ * @fmt : pointer to v4l2 subdev format structure
17390+ * return -EINVAL or zero on success
17391+ */
17392+static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
17393+ struct v4l2_subdev_format *fmt)
17394+{
17395+ struct isp_res_device *res = v4l2_get_subdevdata(sd);
17396+ struct v4l2_mbus_framefmt *format;
17397+ struct v4l2_rect *crop;
17398+
17399+ format = __resizer_get_format(res, fh, fmt->pad, fmt->which);
17400+ if (format == NULL)
17401+ return -EINVAL;
17402+
17403+ resizer_try_format(res, fh, fmt->pad, &fmt->format, fmt->which);
17404+ *format = fmt->format;
17405+
17406+ if (fmt->pad == RESZ_PAD_SINK) {
17407+ /* reset crop rectangle */
17408+ crop = __resizer_get_crop(res, fh, fmt->which);
17409+ crop->left = 0;
17410+ crop->top = 0;
17411+ crop->width = fmt->format.width;
17412+ crop->height = fmt->format.height;
17413+
17414+ /* Propagate the format from sink to source */
17415+ format = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
17416+ fmt->which);
17417+ *format = fmt->format;
17418+ resizer_try_format(res, fh, RESZ_PAD_SOURCE, format,
17419+ fmt->which);
17420+ }
17421+
17422+ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
17423+ /* Compute and store the active crop rectangle and resizer
17424+ * ratios. format already points to the source pad active
17425+ * format.
17426+ */
17427+ res->crop.active = res->crop.request;
17428+ resizer_calc_ratios(res, &res->crop.active, format,
17429+ &res->ratio);
17430+ }
17431+
17432+ return 0;
17433+}
17434+
17435+/*
17436+ * resizer_init_formats - Initialize formats on all pads
17437+ * @sd: ISP resizer V4L2 subdevice
17438+ * @fh: V4L2 subdev file handle
17439+ *
17440+ * Initialize all pad formats with default values. If fh is not NULL, try
17441+ * formats are initialized on the file handle. Otherwise active formats are
17442+ * initialized on the device.
17443+ */
17444+static int resizer_init_formats(struct v4l2_subdev *sd,
17445+ struct v4l2_subdev_fh *fh)
17446+{
17447+ struct v4l2_subdev_format format;
17448+
17449+ memset(&format, 0, sizeof(format));
17450+ format.pad = RESZ_PAD_SINK;
17451+ format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
17452+ format.format.code = V4L2_MBUS_FMT_YUYV8_1X16;
17453+ format.format.width = 4096;
17454+ format.format.height = 4096;
17455+ resizer_set_format(sd, fh, &format);
17456+
17457+ return 0;
17458+}
17459+
17460+/* subdev core operations */
17461+static const struct v4l2_subdev_core_ops resizer_v4l2_core_ops = {
17462+ .queryctrl = v4l2_subdev_queryctrl,
17463+ .querymenu = v4l2_subdev_querymenu,
17464+ .g_ctrl = v4l2_subdev_g_ctrl,
17465+ .s_ctrl = v4l2_subdev_s_ctrl,
17466+ .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
17467+ .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
17468+ .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
17469+};
17470+
17471+/* subdev file operations */
17472+static const struct v4l2_subdev_file_ops resizer_v4l2_file_ops = {
17473+ .open = resizer_init_formats,
17474+};
17475+
17476+/* subdev video operations */
17477+static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = {
17478+ .s_stream = resizer_set_stream,
17479+};
17480+
17481+/* subdev pad operations */
17482+static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = {
17483+ .enum_mbus_code = resizer_enum_mbus_code,
17484+ .enum_frame_size = resizer_enum_frame_size,
17485+ .get_fmt = resizer_get_format,
17486+ .set_fmt = resizer_set_format,
17487+ .get_crop = resizer_g_crop,
17488+ .set_crop = resizer_s_crop,
17489+};
17490+
17491+/* subdev operations */
17492+static const struct v4l2_subdev_ops resizer_v4l2_ops = {
17493+ .core = &resizer_v4l2_core_ops,
17494+ .file = &resizer_v4l2_file_ops,
17495+ .video = &resizer_v4l2_video_ops,
17496+ .pad = &resizer_v4l2_pad_ops,
17497+};
17498+
17499+
17500+/* -----------------------------------------------------------------------------
17501+ * Media entity operations
17502+ */
17503+
17504+/*
17505+ * resizer_link_setup - Setup resizer connections.
17506+ * @entity : Pointer to media entity structure
17507+ * @local : Pointer to local pad array
17508+ * @remote : Pointer to remote pad array
17509+ * @flags : Link flags
17510+ * return -EINVAL or zero on success
17511+ */
17512+static int resizer_link_setup(struct media_entity *entity,
17513+ const struct media_pad *local,
17514+ const struct media_pad *remote, u32 flags)
17515+{
17516+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
17517+ struct isp_res_device *res = v4l2_get_subdevdata(sd);
17518+
17519+ switch (local->index | media_entity_type(remote->entity)) {
17520+ case RESZ_PAD_SINK | MEDIA_ENT_T_DEVNODE:
17521+ /* read from memory */
17522+ if (flags & MEDIA_LNK_FL_ENABLED) {
17523+ if (res->input == RESIZER_INPUT_VP)
17524+ return -EBUSY;
17525+ res->input = RESIZER_INPUT_MEMORY;
17526+ } else {
17527+ if (res->input == RESIZER_INPUT_MEMORY)
17528+ res->input = RESIZER_INPUT_NONE;
17529+ }
17530+ break;
17531+
17532+ case RESZ_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
17533+ /* read from ccdc or previewer */
17534+ if (flags & MEDIA_LNK_FL_ENABLED) {
17535+ if (res->input == RESIZER_INPUT_MEMORY)
17536+ return -EBUSY;
17537+ res->input = RESIZER_INPUT_VP;
17538+ } else {
17539+ if (res->input == RESIZER_INPUT_VP)
17540+ res->input = RESIZER_INPUT_NONE;
17541+ }
17542+ break;
17543+
17544+ case RESZ_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
17545+ /* resizer always write to memory */
17546+ break;
17547+
17548+ default:
17549+ return -EINVAL;
17550+ }
17551+
17552+ return 0;
17553+}
17554+
17555+/* media operations */
17556+static const struct media_entity_operations resizer_media_ops = {
17557+ .link_setup = resizer_link_setup,
17558+};
17559+
17560+/*
17561+ * resizer_init_entities - Initialize resizer subdev and media entity.
17562+ * @res : Pointer to resizer device structure
17563+ * return -ENOMEM or zero on success
17564+ */
17565+static int resizer_init_entities(struct isp_res_device *res)
17566+{
17567+ struct v4l2_subdev *sd = &res->subdev;
17568+ struct media_pad *pads = res->pads;
17569+ struct media_entity *me = &sd->entity;
17570+ int ret;
17571+
17572+ res->input = RESIZER_INPUT_NONE;
17573+
17574+ v4l2_subdev_init(sd, &resizer_v4l2_ops);
17575+ strlcpy(sd->name, "OMAP3 ISP resizer", sizeof(sd->name));
17576+ sd->grp_id = 1 << 16; /* group ID for isp subdevs */
17577+ v4l2_set_subdevdata(sd, res);
17578+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
17579+
17580+ v4l2_ctrl_handler_init(&res->ctrls, 1);
17581+ sd->ctrl_handler = &res->ctrls;
17582+
17583+ pads[RESZ_PAD_SINK].flags = MEDIA_PAD_FL_INPUT;
17584+ pads[RESZ_PAD_SOURCE].flags = MEDIA_PAD_FL_OUTPUT;
17585+
17586+ me->ops = &resizer_media_ops;
17587+ ret = media_entity_init(me, RESZ_PADS_NUM, pads, 0);
17588+ if (ret < 0)
17589+ return ret;
17590+
17591+ resizer_init_formats(sd, NULL);
17592+
17593+ res->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
17594+ res->video_in.ops = &resizer_video_ops;
17595+ res->video_in.isp = to_isp_device(res);
17596+ res->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
17597+ res->video_in.bpl_alignment = 32;
17598+ res->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
17599+ res->video_out.ops = &resizer_video_ops;
17600+ res->video_out.isp = to_isp_device(res);
17601+ res->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
17602+ res->video_out.bpl_alignment = 32;
17603+
17604+ ret = omap3isp_video_init(&res->video_in, "resizer");
17605+ if (ret < 0)
17606+ return ret;
17607+
17608+ ret = omap3isp_video_init(&res->video_out, "resizer");
17609+ if (ret < 0)
17610+ return ret;
17611+
17612+ /* Connect the video nodes to the resizer subdev. */
17613+ ret = media_entity_create_link(&res->video_in.video.entity, 0,
17614+ &res->subdev.entity, RESZ_PAD_SINK, 0);
17615+ if (ret < 0)
17616+ return ret;
17617+
17618+ ret = media_entity_create_link(&res->subdev.entity, RESZ_PAD_SOURCE,
17619+ &res->video_out.video.entity, 0, 0);
17620+ if (ret < 0)
17621+ return ret;
17622+
17623+ return 0;
17624+}
17625+
17626+void omap3isp_resizer_unregister_entities(struct isp_res_device *res)
17627+{
17628+ media_entity_cleanup(&res->subdev.entity);
17629+
17630+ v4l2_device_unregister_subdev(&res->subdev);
17631+ v4l2_ctrl_handler_free(&res->ctrls);
17632+ omap3isp_video_unregister(&res->video_in);
17633+ omap3isp_video_unregister(&res->video_out);
17634+}
17635+
17636+int omap3isp_resizer_register_entities(struct isp_res_device *res,
17637+ struct v4l2_device *vdev)
17638+{
17639+ int ret;
17640+
17641+ /* Register the subdev and video nodes. */
17642+ ret = v4l2_device_register_subdev(vdev, &res->subdev);
17643+ if (ret < 0)
17644+ goto error;
17645+
17646+ ret = omap3isp_video_register(&res->video_in, vdev);
17647+ if (ret < 0)
17648+ goto error;
17649+
17650+ ret = omap3isp_video_register(&res->video_out, vdev);
17651+ if (ret < 0)
17652+ goto error;
17653+
17654+ return 0;
17655+
17656+error:
17657+ omap3isp_resizer_unregister_entities(res);
17658+ return ret;
17659+}
17660+
17661+/* -----------------------------------------------------------------------------
17662+ * ISP resizer initialization and cleanup
17663+ */
17664+
17665+void omap3isp_resizer_cleanup(struct isp_device *isp)
17666+{
17667+}
17668+
17669+/*
17670+ * isp_resizer_init - Resizer initialization.
17671+ * @isp : Pointer to ISP device
17672+ * return -ENOMEM or zero on success
17673+ */
17674+int omap3isp_resizer_init(struct isp_device *isp)
17675+{
17676+ struct isp_res_device *res = &isp->isp_res;
17677+ int ret;
17678+
17679+ init_waitqueue_head(&res->wait);
17680+ atomic_set(&res->stopping, 0);
17681+ ret = resizer_init_entities(res);
17682+ if (ret < 0)
17683+ goto out;
17684+
17685+out:
17686+ if (ret)
17687+ omap3isp_resizer_cleanup(isp);
17688+
17689+ return ret;
17690+}
17691diff --git a/drivers/media/video/isp/ispresizer.h b/drivers/media/video/isp/ispresizer.h
17692new file mode 100644
17693index 0000000..39d188f
17694--- /dev/null
17695+++ b/drivers/media/video/isp/ispresizer.h
17696@@ -0,0 +1,150 @@
17697+/*
17698+ * ispresizer.h
17699+ *
17700+ * TI OMAP3 ISP - Resizer module
17701+ *
17702+ * Copyright (C) 2010 Nokia Corporation
17703+ * Copyright (C) 2009 Texas Instruments, Inc
17704+ *
17705+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
17706+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
17707+ *
17708+ * This program is free software; you can redistribute it and/or modify
17709+ * it under the terms of the GNU General Public License version 2 as
17710+ * published by the Free Software Foundation.
17711+ *
17712+ * This program is distributed in the hope that it will be useful, but
17713+ * WITHOUT ANY WARRANTY; without even the implied warranty of
17714+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17715+ * General Public License for more details.
17716+ *
17717+ * You should have received a copy of the GNU General Public License
17718+ * along with this program; if not, write to the Free Software
17719+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17720+ * 02110-1301 USA
17721+ */
17722+
17723+#ifndef OMAP3_ISP_RESIZER_H
17724+#define OMAP3_ISP_RESIZER_H
17725+
17726+#include <linux/types.h>
17727+#include <media/v4l2-ctrls.h>
17728+
17729+/*
17730+ * Constants for filter coefficents count
17731+ */
17732+#define COEFF_CNT 32
17733+
17734+/*
17735+ * struct isprsz_coef - Structure for resizer filter coeffcients.
17736+ * @h_filter_coef_4tap: Horizontal filter coefficients for 8-phase/4-tap
17737+ * mode (.5x-4x)
17738+ * @v_filter_coef_4tap: Vertical filter coefficients for 8-phase/4-tap
17739+ * mode (.5x-4x)
17740+ * @h_filter_coef_7tap: Horizontal filter coefficients for 4-phase/7-tap
17741+ * mode (.25x-.5x)
17742+ * @v_filter_coef_7tap: Vertical filter coefficients for 4-phase/7-tap
17743+ * mode (.25x-.5x)
17744+ */
17745+struct isprsz_coef {
17746+ u16 h_filter_coef_4tap[32];
17747+ u16 v_filter_coef_4tap[32];
17748+ /* Every 8th value is a dummy value in the following arrays: */
17749+ u16 h_filter_coef_7tap[32];
17750+ u16 v_filter_coef_7tap[32];
17751+};
17752+
17753+/* Chrominance horizontal algorithm */
17754+enum resizer_chroma_algo {
17755+ RSZ_THE_SAME = 0, /* Chrominance the same as Luminance */
17756+ RSZ_BILINEAR = 1, /* Chrominance uses bilinear interpolation */
17757+};
17758+
17759+/* Resizer input type select */
17760+enum resizer_colors_type {
17761+ RSZ_YUV422 = 0, /* YUV422 color is interleaved */
17762+ RSZ_COLOR8 = 1, /* Color separate data on 8 bits */
17763+};
17764+
17765+/*
17766+ * Structure for horizontal and vertical resizing value
17767+ */
17768+struct resizer_ratio {
17769+ u32 horz;
17770+ u32 vert;
17771+};
17772+
17773+/*
17774+ * Structure for luminance enhancer parameters.
17775+ */
17776+struct resizer_luma_yenh {
17777+ u8 algo; /* algorithm select. */
17778+ u8 gain; /* maximum gain. */
17779+ u8 slope; /* slope. */
17780+ u8 core; /* core offset. */
17781+};
17782+
17783+enum resizer_input_entity {
17784+ RESIZER_INPUT_NONE,
17785+ RESIZER_INPUT_VP, /* input video port - prev or ccdc */
17786+ RESIZER_INPUT_MEMORY,
17787+};
17788+
17789+/* Sink and source resizer pads */
17790+#define RESZ_PAD_SINK 0
17791+#define RESZ_PAD_SOURCE 1
17792+#define RESZ_PADS_NUM 2
17793+
17794+/*
17795+ * struct isp_res_device - OMAP3 ISP resizer module
17796+ * @crop.request: Crop rectangle requested by the user
17797+ * @crop.active: Active crop rectangle (based on hardware requirements)
17798+ */
17799+struct isp_res_device {
17800+ struct v4l2_subdev subdev;
17801+ struct media_pad pads[RESZ_PADS_NUM];
17802+ struct v4l2_mbus_framefmt formats[RESZ_PADS_NUM];
17803+
17804+ struct v4l2_ctrl_handler ctrls;
17805+
17806+ enum resizer_input_entity input;
17807+ struct isp_video video_in;
17808+ struct isp_video video_out;
17809+ unsigned int error;
17810+
17811+ u32 addr_base; /* stored source buffer address in memory mode */
17812+ u32 crop_offset; /* additional offset for crop in memory mode */
17813+ struct resizer_ratio ratio;
17814+ int pm_state;
17815+ unsigned int applycrop:1;
17816+ enum isp_pipeline_stream_state state;
17817+ wait_queue_head_t wait;
17818+ atomic_t stopping;
17819+
17820+ struct {
17821+ struct v4l2_rect request;
17822+ struct v4l2_rect active;
17823+ } crop;
17824+};
17825+
17826+struct isp_device;
17827+
17828+int omap3isp_resizer_init(struct isp_device *isp);
17829+void omap3isp_resizer_cleanup(struct isp_device *isp);
17830+
17831+int omap3isp_resizer_register_entities(struct isp_res_device *res,
17832+ struct v4l2_device *vdev);
17833+void omap3isp_resizer_unregister_entities(struct isp_res_device *res);
17834+void omap3isp_resizer_isr_frame_sync(struct isp_res_device *res);
17835+void omap3isp_resizer_isr(struct isp_res_device *isp_res);
17836+
17837+void omap3isp_resizer_max_rate(struct isp_res_device *res,
17838+ unsigned int *max_rate);
17839+
17840+void omap3isp_resizer_suspend(struct isp_res_device *isp_res);
17841+
17842+void omap3isp_resizer_resume(struct isp_res_device *isp_res);
17843+
17844+int omap3isp_resizer_busy(struct isp_res_device *isp_res);
17845+
17846+#endif /* OMAP3_ISP_RESIZER_H */
17847diff --git a/drivers/media/video/isp/ispstat.c b/drivers/media/video/isp/ispstat.c
17848new file mode 100644
17849index 0000000..3406572
17850--- /dev/null
17851+++ b/drivers/media/video/isp/ispstat.c
17852@@ -0,0 +1,1100 @@
17853+/*
17854+ * ispstat.c
17855+ *
17856+ * TI OMAP3 ISP - Statistics core
17857+ *
17858+ * Copyright (C) 2010 Nokia Corporation
17859+ * Copyright (C) 2009 Texas Instruments, Inc
17860+ *
17861+ * Contacts: David Cohen <david.cohen@nokia.com>
17862+ * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
17863+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
17864+ *
17865+ * This program is free software; you can redistribute it and/or modify
17866+ * it under the terms of the GNU General Public License version 2 as
17867+ * published by the Free Software Foundation.
17868+ *
17869+ * This program is distributed in the hope that it will be useful, but
17870+ * WITHOUT ANY WARRANTY; without even the implied warranty of
17871+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17872+ * General Public License for more details.
17873+ *
17874+ * You should have received a copy of the GNU General Public License
17875+ * along with this program; if not, write to the Free Software
17876+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17877+ * 02110-1301 USA
17878+ */
17879+
17880+#include <linux/dma-mapping.h>
17881+#include <linux/slab.h>
17882+#include <linux/uaccess.h>
17883+
17884+#include "isp.h"
17885+
17886+#define IS_COHERENT_BUF(stat) ((stat)->dma_ch >= 0)
17887+
17888+/*
17889+ * MAGIC_SIZE must always be the greatest common divisor of
17890+ * AEWB_PACKET_SIZE and AF_PAXEL_SIZE.
17891+ */
17892+#define MAGIC_SIZE 16
17893+#define MAGIC_NUM 0x55
17894+
17895+/* HACK: AF module seems to be writing one more paxel data than it should. */
17896+#define AF_EXTRA_DATA OMAP3ISP_AF_PAXEL_SIZE
17897+
17898+/*
17899+ * HACK: H3A modules go to an invalid state after have a SBL overflow. It makes
17900+ * the next buffer to start to be written in the same point where the overflow
17901+ * occurred instead of the configured address. The only known way to make it to
17902+ * go back to a valid state is having a valid buffer processing. Of course it
17903+ * requires at least a doubled buffer size to avoid an access to invalid memory
17904+ * region. But it does not fix everything. It may happen more than one
17905+ * consecutive SBL overflows. In that case, it might be unpredictable how many
17906+ * buffers the allocated memory should fit. For that case, a recover
17907+ * configuration was created. It produces the minimum buffer size for each H3A
17908+ * module and decrease the change for more SBL overflows. This recover state
17909+ * will be enabled every time a SBL overflow occur. As the output buffer size
17910+ * isn't big, it's possible to have an extra size able to fit many recover
17911+ * buffers making it extreamily unlikely to have an access to invalid memory
17912+ * region.
17913+ */
17914+#define NUM_H3A_RECOVER_BUFS 10
17915+
17916+/*
17917+ * HACK: Because of HW issues the generic layer sometimes need to have
17918+ * different behaviour for different statistic modules.
17919+ */
17920+#define IS_H3A_AF(stat) ((stat) == &(stat)->isp->isp_af)
17921+#define IS_H3A_AEWB(stat) ((stat) == &(stat)->isp->isp_aewb)
17922+#define IS_H3A(stat) (IS_H3A_AF(stat) || IS_H3A_AEWB(stat))
17923+
17924+static void __isp_stat_buf_sync_magic(struct ispstat *stat,
17925+ struct ispstat_buffer *buf,
17926+ u32 buf_size, enum dma_data_direction dir,
17927+ void (*dma_sync)(struct device *,
17928+ dma_addr_t, unsigned long, size_t,
17929+ enum dma_data_direction))
17930+{
17931+ struct device *dev = stat->isp->dev;
17932+ struct page *pg;
17933+ dma_addr_t dma_addr;
17934+ u32 offset;
17935+
17936+ /* Initial magic words */
17937+ pg = vmalloc_to_page(buf->virt_addr);
17938+ dma_addr = page_to_dma(dev, pg);
17939+ dma_sync(dev, dma_addr, 0, MAGIC_SIZE, dir);
17940+
17941+ /* Final magic words */
17942+ pg = vmalloc_to_page(buf->virt_addr + buf_size);
17943+ dma_addr = page_to_dma(dev, pg);
17944+ offset = ((u32)buf->virt_addr + buf_size) & ~PAGE_MASK;
17945+ dma_sync(dev, dma_addr, offset, MAGIC_SIZE, dir);
17946+}
17947+
17948+static void isp_stat_buf_sync_magic_for_device(struct ispstat *stat,
17949+ struct ispstat_buffer *buf,
17950+ u32 buf_size,
17951+ enum dma_data_direction dir)
17952+{
17953+ if (IS_COHERENT_BUF(stat))
17954+ return;
17955+
17956+ __isp_stat_buf_sync_magic(stat, buf, buf_size, dir,
17957+ dma_sync_single_range_for_device);
17958+}
17959+
17960+static void isp_stat_buf_sync_magic_for_cpu(struct ispstat *stat,
17961+ struct ispstat_buffer *buf,
17962+ u32 buf_size,
17963+ enum dma_data_direction dir)
17964+{
17965+ if (IS_COHERENT_BUF(stat))
17966+ return;
17967+
17968+ __isp_stat_buf_sync_magic(stat, buf, buf_size, dir,
17969+ dma_sync_single_range_for_cpu);
17970+}
17971+
17972+static int isp_stat_buf_check_magic(struct ispstat *stat,
17973+ struct ispstat_buffer *buf)
17974+{
17975+ const u32 buf_size = IS_H3A_AF(stat) ?
17976+ buf->buf_size + AF_EXTRA_DATA : buf->buf_size;
17977+ u8 *w;
17978+ u8 *end;
17979+ int ret = -EINVAL;
17980+
17981+ isp_stat_buf_sync_magic_for_cpu(stat, buf, buf_size, DMA_FROM_DEVICE);
17982+
17983+ /* Checking initial magic numbers. They shouldn't be here anymore. */
17984+ for (w = buf->virt_addr, end = w + MAGIC_SIZE; w < end; w++)
17985+ if (likely(*w != MAGIC_NUM))
17986+ ret = 0;
17987+
17988+ if (ret) {
17989+ dev_dbg(stat->isp->dev, "%s: beginning magic check does not "
17990+ "match.\n", stat->subdev.name);
17991+ return ret;
17992+ }
17993+
17994+ /* Checking magic numbers at the end. They must be still here. */
17995+ for (w = buf->virt_addr + buf_size, end = w + MAGIC_SIZE;
17996+ w < end; w++) {
17997+ if (unlikely(*w != MAGIC_NUM)) {
17998+ dev_dbg(stat->isp->dev, "%s: endding magic check does "
17999+ "not match.\n", stat->subdev.name);
18000+ return -EINVAL;
18001+ }
18002+ }
18003+
18004+ isp_stat_buf_sync_magic_for_device(stat, buf, buf_size,
18005+ DMA_FROM_DEVICE);
18006+
18007+ return 0;
18008+}
18009+
18010+static void isp_stat_buf_insert_magic(struct ispstat *stat,
18011+ struct ispstat_buffer *buf)
18012+{
18013+ const u32 buf_size = IS_H3A_AF(stat) ?
18014+ stat->buf_size + AF_EXTRA_DATA : stat->buf_size;
18015+
18016+ isp_stat_buf_sync_magic_for_cpu(stat, buf, buf_size, DMA_FROM_DEVICE);
18017+
18018+ /*
18019+ * Inserting MAGIC_NUM at the beginning and end of the buffer.
18020+ * buf->buf_size is set only after the buffer is queued. For now the
18021+ * right buf_size for the current configuration is pointed by
18022+ * stat->buf_size.
18023+ */
18024+ memset(buf->virt_addr, MAGIC_NUM, MAGIC_SIZE);
18025+ memset(buf->virt_addr + buf_size, MAGIC_NUM, MAGIC_SIZE);
18026+
18027+ isp_stat_buf_sync_magic_for_device(stat, buf, buf_size,
18028+ DMA_BIDIRECTIONAL);
18029+}
18030+
18031+static void isp_stat_buf_sync_for_device(struct ispstat *stat,
18032+ struct ispstat_buffer *buf)
18033+{
18034+ if (IS_COHERENT_BUF(stat))
18035+ return;
18036+
18037+ dma_sync_sg_for_device(stat->isp->dev, buf->iovm->sgt->sgl,
18038+ buf->iovm->sgt->nents, DMA_FROM_DEVICE);
18039+}
18040+
18041+static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
18042+ struct ispstat_buffer *buf)
18043+{
18044+ if (IS_COHERENT_BUF(stat))
18045+ return;
18046+
18047+ dma_sync_sg_for_cpu(stat->isp->dev, buf->iovm->sgt->sgl,
18048+ buf->iovm->sgt->nents, DMA_FROM_DEVICE);
18049+}
18050+
18051+static void isp_stat_buf_clear(struct ispstat *stat)
18052+{
18053+ int i;
18054+
18055+ for (i = 0; i < STAT_MAX_BUFS; i++)
18056+ stat->buf[i].empty = 1;
18057+}
18058+
18059+static struct ispstat_buffer *
18060+__isp_stat_buf_find(struct ispstat *stat, int look_empty)
18061+{
18062+ struct ispstat_buffer *found = NULL;
18063+ int i;
18064+
18065+ for (i = 0; i < STAT_MAX_BUFS; i++) {
18066+ struct ispstat_buffer *curr = &stat->buf[i];
18067+
18068+ /*
18069+ * Don't select the buffer which is being copied to
18070+ * userspace or used by the module.
18071+ */
18072+ if (curr == stat->locked_buf || curr == stat->active_buf)
18073+ continue;
18074+
18075+ /* Don't select uninitialised buffers if it's not required */
18076+ if (!look_empty && curr->empty)
18077+ continue;
18078+
18079+ /* Pick uninitialised buffer over anything else if look_empty */
18080+ if (curr->empty) {
18081+ found = curr;
18082+ break;
18083+ }
18084+
18085+ /* Choose the oldest buffer */
18086+ if (!found ||
18087+ (s32)curr->frame_number - (s32)found->frame_number < 0)
18088+ found = curr;
18089+ }
18090+
18091+ return found;
18092+}
18093+
18094+static inline struct ispstat_buffer *
18095+isp_stat_buf_find_oldest(struct ispstat *stat)
18096+{
18097+ return __isp_stat_buf_find(stat, 0);
18098+}
18099+
18100+static inline struct ispstat_buffer *
18101+isp_stat_buf_find_oldest_or_empty(struct ispstat *stat)
18102+{
18103+ return __isp_stat_buf_find(stat, 1);
18104+}
18105+
18106+static int isp_stat_buf_queue(struct ispstat *stat)
18107+{
18108+ if (!stat->active_buf)
18109+ return STAT_NO_BUF;
18110+
18111+ do_gettimeofday(&stat->active_buf->ts);
18112+
18113+ stat->active_buf->buf_size = stat->buf_size;
18114+ if (isp_stat_buf_check_magic(stat, stat->active_buf)) {
18115+ dev_dbg(stat->isp->dev, "%s: data wasn't properly written.\n",
18116+ stat->subdev.name);
18117+ return STAT_NO_BUF;
18118+ }
18119+ stat->active_buf->config_counter = stat->config_counter;
18120+ stat->active_buf->frame_number = stat->frame_number;
18121+ stat->active_buf->empty = 0;
18122+ stat->active_buf = NULL;
18123+
18124+ return STAT_BUF_DONE;
18125+}
18126+
18127+/* Get next free buffer to write the statistics to and mark it active. */
18128+static void isp_stat_buf_next(struct ispstat *stat)
18129+{
18130+ if (unlikely(stat->active_buf))
18131+ /* Overwriting unused active buffer */
18132+ dev_dbg(stat->isp->dev, "%s: new buffer requested without "
18133+ "queuing active one.\n",
18134+ stat->subdev.name);
18135+ else
18136+ stat->active_buf = isp_stat_buf_find_oldest_or_empty(stat);
18137+}
18138+
18139+static void isp_stat_buf_release(struct ispstat *stat)
18140+{
18141+ unsigned long flags;
18142+
18143+ isp_stat_buf_sync_for_device(stat, stat->locked_buf);
18144+ spin_lock_irqsave(&stat->isp->stat_lock, flags);
18145+ stat->locked_buf = NULL;
18146+ spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
18147+}
18148+
18149+/* Get buffer to userspace. */
18150+static struct ispstat_buffer *isp_stat_buf_get(struct ispstat *stat,
18151+ struct omap3isp_stat_data *data)
18152+{
18153+ int rval = 0;
18154+ unsigned long flags;
18155+ struct ispstat_buffer *buf;
18156+
18157+ spin_lock_irqsave(&stat->isp->stat_lock, flags);
18158+
18159+ while (1) {
18160+ buf = isp_stat_buf_find_oldest(stat);
18161+ if (!buf) {
18162+ spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
18163+ dev_dbg(stat->isp->dev, "%s: cannot find a buffer.\n",
18164+ stat->subdev.name);
18165+ return ERR_PTR(-EBUSY);
18166+ }
18167+ if (isp_stat_buf_check_magic(stat, buf)) {
18168+ dev_dbg(stat->isp->dev, "%s: current buffer has "
18169+ "corrupted data\n.", stat->subdev.name);
18170+ /* Mark empty because it doesn't have valid data. */
18171+ buf->empty = 1;
18172+ } else {
18173+ /* Buffer isn't corrupted. */
18174+ break;
18175+ }
18176+ }
18177+
18178+ stat->locked_buf = buf;
18179+
18180+ spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
18181+
18182+ if (buf->buf_size > data->buf_size) {
18183+ dev_warn(stat->isp->dev, "%s: userspace's buffer size is "
18184+ "not enough.\n", stat->subdev.name);
18185+ isp_stat_buf_release(stat);
18186+ return ERR_PTR(-EINVAL);
18187+ }
18188+
18189+ isp_stat_buf_sync_for_cpu(stat, buf);
18190+
18191+ rval = copy_to_user(data->buf,
18192+ buf->virt_addr,
18193+ buf->buf_size);
18194+
18195+ if (rval) {
18196+ dev_info(stat->isp->dev,
18197+ "%s: failed copying %d bytes of stat data\n",
18198+ stat->subdev.name, rval);
18199+ buf = ERR_PTR(-EFAULT);
18200+ isp_stat_buf_release(stat);
18201+ }
18202+
18203+ return buf;
18204+}
18205+
18206+static void isp_stat_bufs_free(struct ispstat *stat)
18207+{
18208+ struct isp_device *isp = stat->isp;
18209+ int i;
18210+
18211+ for (i = 0; i < STAT_MAX_BUFS; i++) {
18212+ struct ispstat_buffer *buf = &stat->buf[i];
18213+
18214+ if (!IS_COHERENT_BUF(stat)) {
18215+ if (IS_ERR_OR_NULL((void *)buf->iommu_addr))
18216+ continue;
18217+ if (buf->iovm)
18218+ dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
18219+ buf->iovm->sgt->nents,
18220+ DMA_FROM_DEVICE);
18221+ iommu_vfree(isp->iommu, buf->iommu_addr);
18222+ } else {
18223+ if (!buf->virt_addr)
18224+ continue;
18225+ dma_free_coherent(stat->isp->dev, stat->buf_alloc_size,
18226+ buf->virt_addr, buf->dma_addr);
18227+ }
18228+ buf->iommu_addr = 0;
18229+ buf->iovm = NULL;
18230+ buf->dma_addr = 0;
18231+ buf->virt_addr = NULL;
18232+ buf->empty = 1;
18233+ }
18234+
18235+ dev_dbg(stat->isp->dev, "%s: all buffers were freed.\n",
18236+ stat->subdev.name);
18237+
18238+ stat->buf_alloc_size = 0;
18239+ stat->active_buf = NULL;
18240+}
18241+
18242+static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
18243+{
18244+ struct isp_device *isp = stat->isp;
18245+ int i;
18246+
18247+ stat->buf_alloc_size = size;
18248+
18249+ for (i = 0; i < STAT_MAX_BUFS; i++) {
18250+ struct ispstat_buffer *buf = &stat->buf[i];
18251+ struct iovm_struct *iovm;
18252+
18253+ WARN_ON(buf->dma_addr);
18254+ buf->iommu_addr = iommu_vmalloc(isp->iommu, 0, size,
18255+ IOMMU_FLAG);
18256+ if (IS_ERR((void *)buf->iommu_addr)) {
18257+ dev_err(stat->isp->dev,
18258+ "%s: Can't acquire memory for "
18259+ "buffer %d\n", stat->subdev.name, i);
18260+ isp_stat_bufs_free(stat);
18261+ return -ENOMEM;
18262+ }
18263+
18264+ iovm = find_iovm_area(isp->iommu, buf->iommu_addr);
18265+ if (!iovm ||
18266+ !dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
18267+ DMA_FROM_DEVICE)) {
18268+ isp_stat_bufs_free(stat);
18269+ return -ENOMEM;
18270+ }
18271+ buf->iovm = iovm;
18272+
18273+ buf->virt_addr = da_to_va(stat->isp->iommu,
18274+ (u32)buf->iommu_addr);
18275+ buf->empty = 1;
18276+ dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
18277+ "iommu_addr=0x%08lx virt_addr=0x%08lx",
18278+ stat->subdev.name, i, buf->iommu_addr,
18279+ (unsigned long)buf->virt_addr);
18280+ }
18281+
18282+ return 0;
18283+}
18284+
18285+static int isp_stat_bufs_alloc_dma(struct ispstat *stat, unsigned int size)
18286+{
18287+ int i;
18288+
18289+ stat->buf_alloc_size = size;
18290+
18291+ for (i = 0; i < STAT_MAX_BUFS; i++) {
18292+ struct ispstat_buffer *buf = &stat->buf[i];
18293+
18294+ WARN_ON(buf->iommu_addr);
18295+ buf->virt_addr = dma_alloc_coherent(stat->isp->dev, size,
18296+ &buf->dma_addr, GFP_KERNEL | GFP_DMA);
18297+
18298+ if (!buf->virt_addr || !buf->dma_addr) {
18299+ dev_info(stat->isp->dev,
18300+ "%s: Can't acquire memory for "
18301+ "DMA buffer %d\n", stat->subdev.name, i);
18302+ isp_stat_bufs_free(stat);
18303+ return -ENOMEM;
18304+ }
18305+ buf->empty = 1;
18306+
18307+ dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
18308+ "dma_addr=0x%08lx virt_addr=0x%08lx\n",
18309+ stat->subdev.name, i, (unsigned long)buf->dma_addr,
18310+ (unsigned long)buf->virt_addr);
18311+ }
18312+
18313+ return 0;
18314+}
18315+
18316+static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
18317+{
18318+ unsigned long flags;
18319+
18320+ spin_lock_irqsave(&stat->isp->stat_lock, flags);
18321+
18322+ BUG_ON(stat->locked_buf != NULL);
18323+
18324+ /* Are the old buffers big enough? */
18325+ if (stat->buf_alloc_size >= size) {
18326+ spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
18327+ return 0;
18328+ }
18329+
18330+ if (stat->state != ISPSTAT_DISABLED || stat->buf_processing) {
18331+ dev_info(stat->isp->dev,
18332+ "%s: trying to allocate memory when busy\n",
18333+ stat->subdev.name);
18334+ spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
18335+ return -EBUSY;
18336+ }
18337+
18338+ spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
18339+
18340+ isp_stat_bufs_free(stat);
18341+
18342+ if (IS_COHERENT_BUF(stat))
18343+ return isp_stat_bufs_alloc_dma(stat, size);
18344+ else
18345+ return isp_stat_bufs_alloc_iommu(stat, size);
18346+}
18347+
18348+static void isp_stat_queue_event(struct ispstat *stat, int err)
18349+{
18350+ struct video_device *vdev = &stat->subdev.devnode;
18351+ struct v4l2_event event;
18352+ struct omap3isp_stat_event_status *status = (void *)event.u.data;
18353+
18354+ memset(&event, 0, sizeof(event));
18355+ if (!err) {
18356+ status->frame_number = stat->frame_number;
18357+ status->config_counter = stat->config_counter;
18358+ } else {
18359+ status->buf_err = 1;
18360+ }
18361+ event.type = stat->event_type;
18362+ v4l2_event_queue(vdev, &event);
18363+}
18364+
18365+
18366+/*
18367+ * omap3isp_stat_request_statistics - Request statistics.
18368+ * @data: Pointer to return statistics data.
18369+ *
18370+ * Returns 0 if successful.
18371+ */
18372+int omap3isp_stat_request_statistics(struct ispstat *stat,
18373+ struct omap3isp_stat_data *data)
18374+{
18375+ struct ispstat_buffer *buf;
18376+
18377+ if (stat->state != ISPSTAT_ENABLED) {
18378+ dev_dbg(stat->isp->dev, "%s: engine not enabled.\n",
18379+ stat->subdev.name);
18380+ return -EINVAL;
18381+ }
18382+
18383+ mutex_lock(&stat->ioctl_lock);
18384+ buf = isp_stat_buf_get(stat, data);
18385+ if (IS_ERR(buf)) {
18386+ mutex_unlock(&stat->ioctl_lock);
18387+ return PTR_ERR(buf);
18388+ }
18389+
18390+ data->ts = buf->ts;
18391+ data->config_counter = buf->config_counter;
18392+ data->frame_number = buf->frame_number;
18393+ data->buf_size = buf->buf_size;
18394+
18395+ /*
18396+ * Deprecated. Number of new buffers is always equal to number of
18397+ * queued events without error flag. By setting it to 0, userspace
18398+ * won't try to request new buffer without receiving new event.
18399+ * This field must go away in future.
18400+ */
18401+ data->new_bufs = 0;
18402+
18403+ buf->empty = 1;
18404+ isp_stat_buf_release(stat);
18405+ mutex_unlock(&stat->ioctl_lock);
18406+
18407+ return 0;
18408+}
18409+
18410+/*
18411+ * omap3isp_stat_config - Receives new statistic engine configuration.
18412+ * @new_conf: Pointer to config structure.
18413+ *
18414+ * Returns 0 if successful, -EINVAL if new_conf pointer is NULL, -ENOMEM if
18415+ * was unable to allocate memory for the buffer, or other errors if parameters
18416+ * are invalid.
18417+ */
18418+int omap3isp_stat_config(struct ispstat *stat, void *new_conf)
18419+{
18420+ int ret;
18421+ unsigned long irqflags;
18422+ struct ispstat_generic_config *user_cfg = new_conf;
18423+ u32 buf_size = user_cfg->buf_size;
18424+
18425+ if (!new_conf) {
18426+ dev_dbg(stat->isp->dev, "%s: configuration is NULL\n",
18427+ stat->subdev.name);
18428+ return -EINVAL;
18429+ }
18430+
18431+ mutex_lock(&stat->ioctl_lock);
18432+
18433+ dev_dbg(stat->isp->dev, "%s: configuring module with buffer "
18434+ "size=0x%08lx\n", stat->subdev.name, (unsigned long)buf_size);
18435+
18436+ ret = stat->ops->validate_params(stat, new_conf);
18437+ if (ret) {
18438+ mutex_unlock(&stat->ioctl_lock);
18439+ dev_dbg(stat->isp->dev, "%s: configuration values are "
18440+ "invalid.\n", stat->subdev.name);
18441+ return ret;
18442+ }
18443+
18444+ if (buf_size != user_cfg->buf_size)
18445+ dev_dbg(stat->isp->dev, "%s: driver has corrected buffer size "
18446+ "request to 0x%08lx\n", stat->subdev.name,
18447+ (unsigned long)user_cfg->buf_size);
18448+
18449+ /*
18450+ * Hack: H3A modules may need a doubled buffer size to avoid access
18451+ * to a invalid memory address after a SBL overflow.
18452+ * The buffer size is always PAGE_ALIGNED.
18453+ * Hack 2: MAGIC_SIZE is added to buf_size so a magic word can be
18454+ * inserted at the end to data integrity check purpose.
18455+ * Hack 3: AF module writes one paxel data more than it should, so
18456+ * the buffer allocation must consider it to avoid invalid memory
18457+ * access.
18458+ * Hack 4: H3A need to allocate extra space for the recover state.
18459+ */
18460+ if (IS_H3A(stat)) {
18461+ buf_size = user_cfg->buf_size * 2 + MAGIC_SIZE;
18462+ if (IS_H3A_AF(stat))
18463+ /*
18464+ * Adding one extra paxel data size for each recover
18465+ * buffer + 2 regular ones.
18466+ */
18467+ buf_size += AF_EXTRA_DATA * (NUM_H3A_RECOVER_BUFS + 2);
18468+ if (stat->recover_priv) {
18469+ struct ispstat_generic_config *recover_cfg =
18470+ stat->recover_priv;
18471+ buf_size += recover_cfg->buf_size *
18472+ NUM_H3A_RECOVER_BUFS;
18473+ }
18474+ buf_size = PAGE_ALIGN(buf_size);
18475+ } else { /* Histogram */
18476+ buf_size = PAGE_ALIGN(user_cfg->buf_size + MAGIC_SIZE);
18477+ }
18478+
18479+ ret = isp_stat_bufs_alloc(stat, buf_size);
18480+ if (ret) {
18481+ mutex_unlock(&stat->ioctl_lock);
18482+ return ret;
18483+ }
18484+
18485+ spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
18486+ stat->ops->set_params(stat, new_conf);
18487+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18488+
18489+ /*
18490+ * Returning the right future config_counter for this setup, so
18491+ * userspace can *know* when it has been applied.
18492+ */
18493+ user_cfg->config_counter = stat->config_counter + stat->inc_config;
18494+
18495+ /* Module has a valid configuration. */
18496+ stat->configured = 1;
18497+ dev_dbg(stat->isp->dev, "%s: module has been successfully "
18498+ "configured.\n", stat->subdev.name);
18499+
18500+ mutex_unlock(&stat->ioctl_lock);
18501+
18502+ return 0;
18503+}
18504+
18505+/*
18506+ * isp_stat_buf_process - Process statistic buffers.
18507+ * @buf_state: points out if buffer is ready to be processed. It's necessary
18508+ * because histogram needs to copy the data from internal memory
18509+ * before be able to process the buffer.
18510+ */
18511+static int isp_stat_buf_process(struct ispstat *stat, int buf_state)
18512+{
18513+ int ret = STAT_NO_BUF;
18514+
18515+ if (!atomic_add_unless(&stat->buf_err, -1, 0) &&
18516+ buf_state == STAT_BUF_DONE && stat->state == ISPSTAT_ENABLED) {
18517+ ret = isp_stat_buf_queue(stat);
18518+ isp_stat_buf_next(stat);
18519+ }
18520+
18521+ return ret;
18522+}
18523+
18524+int omap3isp_stat_pcr_busy(struct ispstat *stat)
18525+{
18526+ return stat->ops->busy(stat);
18527+}
18528+
18529+int omap3isp_stat_busy(struct ispstat *stat)
18530+{
18531+ return omap3isp_stat_pcr_busy(stat) | stat->buf_processing |
18532+ (stat->state != ISPSTAT_DISABLED);
18533+}
18534+
18535+/*
18536+ * isp_stat_pcr_enable - Disables/Enables statistic engines.
18537+ * @pcr_enable: 0/1 - Disables/Enables the engine.
18538+ *
18539+ * Must be called from ISP driver when the module is idle and synchronized
18540+ * with CCDC.
18541+ */
18542+static void isp_stat_pcr_enable(struct ispstat *stat, u8 pcr_enable)
18543+{
18544+ if ((stat->state != ISPSTAT_ENABLING &&
18545+ stat->state != ISPSTAT_ENABLED) && pcr_enable)
18546+ /* Userspace has disabled the module. Aborting. */
18547+ return;
18548+
18549+ stat->ops->enable(stat, pcr_enable);
18550+ if (stat->state == ISPSTAT_DISABLING && !pcr_enable)
18551+ stat->state = ISPSTAT_DISABLED;
18552+ else if (stat->state == ISPSTAT_ENABLING && pcr_enable)
18553+ stat->state = ISPSTAT_ENABLED;
18554+}
18555+
18556+void omap3isp_stat_suspend(struct ispstat *stat)
18557+{
18558+ unsigned long flags;
18559+
18560+ spin_lock_irqsave(&stat->isp->stat_lock, flags);
18561+
18562+ if (stat->state != ISPSTAT_DISABLED)
18563+ stat->ops->enable(stat, 0);
18564+ if (stat->state == ISPSTAT_ENABLED)
18565+ stat->state = ISPSTAT_SUSPENDED;
18566+
18567+ spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
18568+}
18569+
18570+void omap3isp_stat_resume(struct ispstat *stat)
18571+{
18572+ /* Module will be re-enabled with its pipeline */
18573+ if (stat->state == ISPSTAT_SUSPENDED)
18574+ stat->state = ISPSTAT_ENABLING;
18575+}
18576+
18577+static void isp_stat_try_enable(struct ispstat *stat)
18578+{
18579+ unsigned long irqflags;
18580+
18581+ if (stat->priv == NULL)
18582+ /* driver wasn't initialised */
18583+ return;
18584+
18585+ spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
18586+ if (stat->state == ISPSTAT_ENABLING && !stat->buf_processing &&
18587+ stat->buf_alloc_size) {
18588+ /*
18589+ * Userspace's requested to enable the engine but it wasn't yet.
18590+ * Let's do that now.
18591+ */
18592+ stat->update = 1;
18593+ isp_stat_buf_next(stat);
18594+ stat->ops->setup_regs(stat, stat->priv);
18595+ isp_stat_buf_insert_magic(stat, stat->active_buf);
18596+
18597+ /*
18598+ * H3A module has some hw issues which forces the driver to
18599+ * ignore next buffers even if it was disabled in the meantime.
18600+ * On the other hand, Histogram shouldn't ignore buffers anymore
18601+ * if it's being enabled.
18602+ */
18603+ if (!IS_H3A(stat))
18604+ atomic_set(&stat->buf_err, 0);
18605+
18606+ isp_stat_pcr_enable(stat, 1);
18607+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18608+ dev_dbg(stat->isp->dev, "%s: module is enabled.\n",
18609+ stat->subdev.name);
18610+ } else {
18611+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18612+ }
18613+}
18614+
18615+void omap3isp_stat_isr_frame_sync(struct ispstat *stat)
18616+{
18617+ isp_stat_try_enable(stat);
18618+}
18619+
18620+void omap3isp_stat_sbl_overflow(struct ispstat *stat)
18621+{
18622+ unsigned long irqflags;
18623+
18624+ spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
18625+ /*
18626+ * Due to a H3A hw issue which prevents the next buffer to start from
18627+ * the correct memory address, 2 buffers must be ignored.
18628+ */
18629+ atomic_set(&stat->buf_err, 2);
18630+
18631+ /*
18632+ * If more than one SBL overflow happen in a row, H3A module may access
18633+ * invalid memory region.
18634+ * stat->sbl_ovl_recover is set to tell to the driver to temporarily use
18635+ * a soft configuration which helps to avoid consecutive overflows.
18636+ */
18637+ if (stat->recover_priv)
18638+ stat->sbl_ovl_recover = 1;
18639+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18640+}
18641+
18642+/*
18643+ * omap3isp_stat_enable - Disable/Enable statistic engine as soon as possible
18644+ * @enable: 0/1 - Disables/Enables the engine.
18645+ *
18646+ * Client should configure all the module registers before this.
18647+ * This function can be called from a userspace request.
18648+ */
18649+int omap3isp_stat_enable(struct ispstat *stat, u8 enable)
18650+{
18651+ unsigned long irqflags;
18652+
18653+ dev_dbg(stat->isp->dev, "%s: user wants to %s module.\n",
18654+ stat->subdev.name, enable ? "enable" : "disable");
18655+
18656+ /* Prevent enabling while configuring */
18657+ mutex_lock(&stat->ioctl_lock);
18658+
18659+ spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
18660+
18661+ if (!stat->configured && enable) {
18662+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18663+ mutex_unlock(&stat->ioctl_lock);
18664+ dev_dbg(stat->isp->dev, "%s: cannot enable module as it's "
18665+ "never been successfully configured so far.\n",
18666+ stat->subdev.name);
18667+ return -EINVAL;
18668+ }
18669+
18670+ if (enable) {
18671+ if (stat->state == ISPSTAT_DISABLING)
18672+ /* Previous disabling request wasn't done yet */
18673+ stat->state = ISPSTAT_ENABLED;
18674+ else if (stat->state == ISPSTAT_DISABLED)
18675+ /* Module is now being enabled */
18676+ stat->state = ISPSTAT_ENABLING;
18677+ } else {
18678+ if (stat->state == ISPSTAT_ENABLING) {
18679+ /* Previous enabling request wasn't done yet */
18680+ stat->state = ISPSTAT_DISABLED;
18681+ } else if (stat->state == ISPSTAT_ENABLED) {
18682+ /* Module is now being disabled */
18683+ stat->state = ISPSTAT_DISABLING;
18684+ isp_stat_buf_clear(stat);
18685+ }
18686+ }
18687+
18688+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18689+ mutex_unlock(&stat->ioctl_lock);
18690+
18691+ return 0;
18692+}
18693+
18694+int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable)
18695+{
18696+ struct ispstat *stat = v4l2_get_subdevdata(subdev);
18697+
18698+ if (enable) {
18699+ /*
18700+ * Only set enable PCR bit if the module was previously
18701+ * enabled through ioct.
18702+ */
18703+ isp_stat_try_enable(stat);
18704+ } else {
18705+ unsigned long flags;
18706+ /* Disable PCR bit and config enable field */
18707+ omap3isp_stat_enable(stat, 0);
18708+ spin_lock_irqsave(&stat->isp->stat_lock, flags);
18709+ stat->ops->enable(stat, 0);
18710+ spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
18711+
18712+ /*
18713+ * If module isn't busy, a new interrupt may come or not to
18714+ * set the state to DISABLED. As Histogram needs to read its
18715+ * internal memory to clear it, let interrupt handler
18716+ * responsible of changing state to DISABLED. If the last
18717+ * interrupt is coming, it's still safe as the handler will
18718+ * ignore the second time when state is already set to DISABLED.
18719+ * It's necessary to synchronize Histogram with streamoff, once
18720+ * the module may be considered idle before last SDMA transfer
18721+ * starts if we return here.
18722+ */
18723+ if (!omap3isp_stat_pcr_busy(stat))
18724+ omap3isp_stat_isr(stat);
18725+
18726+ dev_dbg(stat->isp->dev, "%s: module is being disabled\n",
18727+ stat->subdev.name);
18728+ }
18729+
18730+ return 0;
18731+}
18732+
18733+/*
18734+ * __stat_isr - Interrupt handler for statistic drivers
18735+ */
18736+static void __stat_isr(struct ispstat *stat, int from_dma)
18737+{
18738+ int ret = STAT_BUF_DONE;
18739+ int buf_processing;
18740+ unsigned long irqflags;
18741+ struct isp_pipeline *pipe;
18742+
18743+ /*
18744+ * stat->buf_processing must be set before disable module. It's
18745+ * necessary to not inform too early the buffers aren't busy in case
18746+ * of SDMA is going to be used.
18747+ */
18748+ spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
18749+ if (stat->state == ISPSTAT_DISABLED) {
18750+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18751+ return;
18752+ }
18753+ buf_processing = stat->buf_processing;
18754+ stat->buf_processing = 1;
18755+ stat->ops->enable(stat, 0);
18756+
18757+ if (buf_processing && !from_dma) {
18758+ if (stat->state == ISPSTAT_ENABLED) {
18759+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18760+ dev_err(stat->isp->dev,
18761+ "%s: interrupt occurred when module was still "
18762+ "processing a buffer.\n", stat->subdev.name);
18763+ ret = STAT_NO_BUF;
18764+ goto out;
18765+ } else {
18766+ /*
18767+ * Interrupt handler was called from streamoff when
18768+ * the module wasn't busy anymore to ensure it is being
18769+ * disabled after process last buffer. If such buffer
18770+ * processing has already started, no need to do
18771+ * anything else.
18772+ */
18773+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18774+ return;
18775+ }
18776+ }
18777+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18778+
18779+ /* If it's busy we can't process this buffer anymore */
18780+ if (!omap3isp_stat_pcr_busy(stat)) {
18781+ if (!from_dma && stat->ops->buf_process)
18782+ /* Module still need to copy data to buffer. */
18783+ ret = stat->ops->buf_process(stat);
18784+ if (ret == STAT_BUF_WAITING_DMA)
18785+ /* Buffer is not ready yet */
18786+ return;
18787+
18788+ spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
18789+
18790+ /*
18791+ * Histogram needs to read its internal memory to clear it
18792+ * before be disabled. For that reason, common statistic layer
18793+ * can return only after call stat's buf_process() operator.
18794+ */
18795+ if (stat->state == ISPSTAT_DISABLING) {
18796+ stat->state = ISPSTAT_DISABLED;
18797+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18798+ stat->buf_processing = 0;
18799+ return;
18800+ }
18801+ pipe = to_isp_pipeline(&stat->subdev.entity);
18802+ stat->frame_number = atomic_read(&pipe->frame_number);
18803+
18804+ /*
18805+ * Before this point, 'ret' stores the buffer's status if it's
18806+ * ready to be processed. Afterwards, it holds the status if
18807+ * it was processed successfully.
18808+ */
18809+ ret = isp_stat_buf_process(stat, ret);
18810+
18811+ if (likely(!stat->sbl_ovl_recover)) {
18812+ stat->ops->setup_regs(stat, stat->priv);
18813+ } else {
18814+ /*
18815+ * Using recover config to increase the chance to have
18816+ * a good buffer processing and make the H3A module to
18817+ * go back to a valid state.
18818+ */
18819+ stat->update = 1;
18820+ stat->ops->setup_regs(stat, stat->recover_priv);
18821+ stat->sbl_ovl_recover = 0;
18822+
18823+ /*
18824+ * Set 'update' in case of the module needs to use
18825+ * regular configuration after next buffer.
18826+ */
18827+ stat->update = 1;
18828+ }
18829+
18830+ isp_stat_buf_insert_magic(stat, stat->active_buf);
18831+
18832+ /*
18833+ * Hack: H3A modules may access invalid memory address or send
18834+ * corrupted data to userspace if more than 1 SBL overflow
18835+ * happens in a row without re-writing its buffer's start memory
18836+ * address in the meantime. Such situation is avoided if the
18837+ * module is not immediately re-enabled when the ISR misses the
18838+ * timing to process the buffer and to setup the registers.
18839+ * Because of that, pcr_enable(1) was moved to inside this 'if'
18840+ * block. But the next interruption will still happen as during
18841+ * pcr_enable(0) the module was busy.
18842+ */
18843+ isp_stat_pcr_enable(stat, 1);
18844+ spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
18845+ } else {
18846+ /*
18847+ * If a SBL overflow occurs and the H3A driver misses the timing
18848+ * to process the buffer, stat->buf_err is set and won't be
18849+ * cleared now. So the next buffer will be correctly ignored.
18850+ * It's necessary due to a hw issue which makes the next H3A
18851+ * buffer to start from the memory address where the previous
18852+ * one stopped, instead of start where it was configured to.
18853+ * Do not "stat->buf_err = 0" here.
18854+ */
18855+
18856+ if (stat->ops->buf_process)
18857+ /*
18858+ * Driver may need to erase current data prior to
18859+ * process a new buffer. If it misses the timing, the
18860+ * next buffer might be wrong. So should be ignored.
18861+ * It happens only for Histogram.
18862+ */
18863+ atomic_set(&stat->buf_err, 1);
18864+
18865+ ret = STAT_NO_BUF;
18866+ dev_dbg(stat->isp->dev, "%s: cannot process buffer, "
18867+ "device is busy.\n", stat->subdev.name);
18868+ }
18869+
18870+out:
18871+ stat->buf_processing = 0;
18872+ isp_stat_queue_event(stat, ret != STAT_BUF_DONE);
18873+}
18874+
18875+void omap3isp_stat_isr(struct ispstat *stat)
18876+{
18877+ __stat_isr(stat, 0);
18878+}
18879+
18880+void omap3isp_stat_dma_isr(struct ispstat *stat)
18881+{
18882+ __stat_isr(stat, 1);
18883+}
18884+
18885+static int isp_stat_init_entities(struct ispstat *stat, const char *name,
18886+ const struct v4l2_subdev_ops *sd_ops)
18887+{
18888+ struct v4l2_subdev *subdev = &stat->subdev;
18889+ struct media_entity *me = &subdev->entity;
18890+
18891+ v4l2_subdev_init(subdev, sd_ops);
18892+ snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name);
18893+ subdev->grp_id = 1 << 16; /* group ID for isp subdevs */
18894+ subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
18895+ subdev->nevents = STAT_NEVENTS;
18896+ v4l2_set_subdevdata(subdev, stat);
18897+
18898+ stat->pad.flags = MEDIA_PAD_FL_INPUT;
18899+ me->ops = NULL;
18900+
18901+ return media_entity_init(me, 1, &stat->pad, 0);
18902+}
18903+
18904+int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
18905+ struct v4l2_fh *fh,
18906+ struct v4l2_event_subscription *sub)
18907+{
18908+ struct ispstat *stat = v4l2_get_subdevdata(subdev);
18909+
18910+ if (sub->type != stat->event_type)
18911+ return -EINVAL;
18912+
18913+ return v4l2_event_subscribe(fh, sub);
18914+}
18915+
18916+int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
18917+ struct v4l2_fh *fh,
18918+ struct v4l2_event_subscription *sub)
18919+{
18920+ return v4l2_event_unsubscribe(fh, sub);
18921+}
18922+
18923+void omap3isp_stat_unregister_entities(struct ispstat *stat)
18924+{
18925+ media_entity_cleanup(&stat->subdev.entity);
18926+ v4l2_device_unregister_subdev(&stat->subdev);
18927+}
18928+
18929+int omap3isp_stat_register_entities(struct ispstat *stat,
18930+ struct v4l2_device *vdev)
18931+{
18932+ return v4l2_device_register_subdev(vdev, &stat->subdev);
18933+}
18934+
18935+int omap3isp_stat_init(struct ispstat *stat, const char *name,
18936+ const struct v4l2_subdev_ops *sd_ops)
18937+{
18938+ stat->buf = kcalloc(STAT_MAX_BUFS, sizeof(*stat->buf), GFP_KERNEL);
18939+ if (!stat->buf)
18940+ return -ENOMEM;
18941+ isp_stat_buf_clear(stat);
18942+ mutex_init(&stat->ioctl_lock);
18943+ atomic_set(&stat->buf_err, 0);
18944+
18945+ return isp_stat_init_entities(stat, name, sd_ops);
18946+}
18947+
18948+void omap3isp_stat_free(struct ispstat *stat)
18949+{
18950+ isp_stat_bufs_free(stat);
18951+ kfree(stat->buf);
18952+}
18953diff --git a/drivers/media/video/isp/ispstat.h b/drivers/media/video/isp/ispstat.h
18954new file mode 100644
18955index 0000000..5298d33
18956--- /dev/null
18957+++ b/drivers/media/video/isp/ispstat.h
18958@@ -0,0 +1,169 @@
18959+/*
18960+ * ispstat.h
18961+ *
18962+ * TI OMAP3 ISP - Statistics core
18963+ *
18964+ * Copyright (C) 2010 Nokia Corporation
18965+ * Copyright (C) 2009 Texas Instruments, Inc
18966+ *
18967+ * Contacts: David Cohen <david.cohen@nokia.com>
18968+ * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
18969+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
18970+ *
18971+ * This program is free software; you can redistribute it and/or modify
18972+ * it under the terms of the GNU General Public License version 2 as
18973+ * published by the Free Software Foundation.
18974+ *
18975+ * This program is distributed in the hope that it will be useful, but
18976+ * WITHOUT ANY WARRANTY; without even the implied warranty of
18977+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18978+ * General Public License for more details.
18979+ *
18980+ * You should have received a copy of the GNU General Public License
18981+ * along with this program; if not, write to the Free Software
18982+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18983+ * 02110-1301 USA
18984+ */
18985+
18986+#ifndef OMAP3_ISP_STAT_H
18987+#define OMAP3_ISP_STAT_H
18988+
18989+#include <linux/types.h>
18990+#include <linux/omap3isp.h>
18991+#include <plat/dma.h>
18992+#include <media/v4l2-event.h>
18993+
18994+#include "isp.h"
18995+#include "ispvideo.h"
18996+
18997+#define STAT_MAX_BUFS 5
18998+#define STAT_NEVENTS 8
18999+
19000+#define STAT_BUF_DONE 0 /* Buffer is ready */
19001+#define STAT_NO_BUF 1 /* An error has occurred */
19002+#define STAT_BUF_WAITING_DMA 2 /* Histogram only: DMA is running */
19003+
19004+struct ispstat;
19005+
19006+struct ispstat_buffer {
19007+ unsigned long iommu_addr;
19008+ struct iovm_struct *iovm;
19009+ void *virt_addr;
19010+ dma_addr_t dma_addr;
19011+ struct timeval ts;
19012+ u32 buf_size;
19013+ u32 frame_number;
19014+ u16 config_counter;
19015+ u8 empty;
19016+};
19017+
19018+struct ispstat_ops {
19019+ /*
19020+ * Validate new params configuration.
19021+ * new_conf->buf_size value must be changed to the exact buffer size
19022+ * necessary for the new configuration if it's smaller.
19023+ */
19024+ int (*validate_params)(struct ispstat *stat, void *new_conf);
19025+
19026+ /*
19027+ * Save new params configuration.
19028+ * stat->priv->buf_size value must be set to the exact buffer size for
19029+ * the new configuration.
19030+ * stat->update is set to 1 if new configuration is different than
19031+ * current one.
19032+ */
19033+ void (*set_params)(struct ispstat *stat, void *new_conf);
19034+
19035+ /* Apply stored configuration. */
19036+ void (*setup_regs)(struct ispstat *stat, void *priv);
19037+
19038+ /* Enable/Disable module. */
19039+ void (*enable)(struct ispstat *stat, int enable);
19040+
19041+ /* Verify is module is busy. */
19042+ int (*busy)(struct ispstat *stat);
19043+
19044+ /* Used for specific operations during generic buf process task. */
19045+ int (*buf_process)(struct ispstat *stat);
19046+};
19047+
19048+enum ispstat_state_t {
19049+ ISPSTAT_DISABLED = 0,
19050+ ISPSTAT_DISABLING,
19051+ ISPSTAT_ENABLED,
19052+ ISPSTAT_ENABLING,
19053+ ISPSTAT_SUSPENDED,
19054+};
19055+
19056+struct ispstat {
19057+ struct v4l2_subdev subdev;
19058+ struct media_pad pad; /* sink pad */
19059+
19060+ /* Control */
19061+ unsigned configured:1;
19062+ unsigned update:1;
19063+ unsigned buf_processing:1;
19064+ unsigned sbl_ovl_recover:1;
19065+ u8 inc_config;
19066+ atomic_t buf_err;
19067+ enum ispstat_state_t state; /* enabling/disabling state */
19068+ struct omap_dma_channel_params dma_config;
19069+ struct isp_device *isp;
19070+ void *priv; /* pointer to priv config struct */
19071+ void *recover_priv; /* pointer to recover priv configuration */
19072+ struct mutex ioctl_lock; /* serialize private ioctl */
19073+
19074+ const struct ispstat_ops *ops;
19075+
19076+ /* Buffer */
19077+ u8 wait_acc_frames;
19078+ u16 config_counter;
19079+ u32 frame_number;
19080+ u32 buf_size;
19081+ u32 buf_alloc_size;
19082+ int dma_ch;
19083+ unsigned long event_type;
19084+ struct ispstat_buffer *buf;
19085+ struct ispstat_buffer *active_buf;
19086+ struct ispstat_buffer *locked_buf;
19087+};
19088+
19089+struct ispstat_generic_config {
19090+ /*
19091+ * Fields must be in the same order as in:
19092+ * - isph3a_aewb_config
19093+ * - isph3a_af_config
19094+ * - isphist_config
19095+ */
19096+ u32 buf_size;
19097+ u16 config_counter;
19098+};
19099+
19100+int omap3isp_stat_config(struct ispstat *stat, void *new_conf);
19101+int omap3isp_stat_request_statistics(struct ispstat *stat,
19102+ struct omap3isp_stat_data *data);
19103+int omap3isp_stat_init(struct ispstat *stat, const char *name,
19104+ const struct v4l2_subdev_ops *sd_ops);
19105+void omap3isp_stat_free(struct ispstat *stat);
19106+int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
19107+ struct v4l2_fh *fh,
19108+ struct v4l2_event_subscription *sub);
19109+int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
19110+ struct v4l2_fh *fh,
19111+ struct v4l2_event_subscription *sub);
19112+int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable);
19113+
19114+int omap3isp_stat_busy(struct ispstat *stat);
19115+int omap3isp_stat_pcr_busy(struct ispstat *stat);
19116+void omap3isp_stat_suspend(struct ispstat *stat);
19117+void omap3isp_stat_resume(struct ispstat *stat);
19118+int omap3isp_stat_enable(struct ispstat *stat, u8 enable);
19119+void omap3isp_stat_sbl_overflow(struct ispstat *stat);
19120+void omap3isp_stat_isr(struct ispstat *stat);
19121+void omap3isp_stat_isr_frame_sync(struct ispstat *stat);
19122+void omap3isp_stat_dma_isr(struct ispstat *stat);
19123+int omap3isp_stat_register_entities(struct ispstat *stat,
19124+ struct v4l2_device *vdev);
19125+void omap3isp_stat_unregister_entities(struct ispstat *stat);
19126+
19127+#endif /* OMAP3_ISP_STAT_H */
19128diff --git a/drivers/media/video/isp/ispvideo.c b/drivers/media/video/isp/ispvideo.c
19129new file mode 100644
19130index 0000000..ef0adb0
19131--- /dev/null
19132+++ b/drivers/media/video/isp/ispvideo.c
19133@@ -0,0 +1,1264 @@
19134+/*
19135+ * ispvideo.c
19136+ *
19137+ * TI OMAP3 ISP - Generic video node
19138+ *
19139+ * Copyright (C) 2009-2010 Nokia Corporation
19140+ *
19141+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
19142+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
19143+ *
19144+ * This program is free software; you can redistribute it and/or modify
19145+ * it under the terms of the GNU General Public License version 2 as
19146+ * published by the Free Software Foundation.
19147+ *
19148+ * This program is distributed in the hope that it will be useful, but
19149+ * WITHOUT ANY WARRANTY; without even the implied warranty of
19150+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19151+ * General Public License for more details.
19152+ *
19153+ * You should have received a copy of the GNU General Public License
19154+ * along with this program; if not, write to the Free Software
19155+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19156+ * 02110-1301 USA
19157+ */
19158+
19159+#include <asm/cacheflush.h>
19160+#include <linux/clk.h>
19161+#include <linux/mm.h>
19162+#include <linux/pagemap.h>
19163+#include <linux/scatterlist.h>
19164+#include <linux/sched.h>
19165+#include <linux/slab.h>
19166+#include <linux/vmalloc.h>
19167+#include <media/v4l2-dev.h>
19168+#include <media/v4l2-ioctl.h>
19169+#include <plat/iommu.h>
19170+#include <plat/iovmm.h>
19171+#include <plat/omap-pm.h>
19172+
19173+#include "ispvideo.h"
19174+#include "isp.h"
19175+
19176+
19177+/* -----------------------------------------------------------------------------
19178+ * Helper functions
19179+ */
19180+
19181+static struct isp_format_info formats[] = {
19182+ { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
19183+ V4L2_MBUS_FMT_Y8_1X8, V4L2_PIX_FMT_GREY, 8, },
19184+ { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
19185+ V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
19186+ { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
19187+ V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 10, },
19188+ { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
19189+ V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 10, },
19190+ { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
19191+ V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 10, },
19192+ { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
19193+ V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 10, },
19194+ { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
19195+ V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 12, },
19196+ { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
19197+ V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 12, },
19198+ { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
19199+ V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 12, },
19200+ { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
19201+ V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 12, },
19202+ { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
19203+ V4L2_MBUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 16, },
19204+ { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
19205+ V4L2_MBUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 16, },
19206+};
19207+
19208+const struct isp_format_info *
19209+omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
19210+{
19211+ unsigned int i;
19212+
19213+ for (i = 0; i < ARRAY_SIZE(formats); ++i) {
19214+ if (formats[i].code == code)
19215+ return &formats[i];
19216+ }
19217+
19218+ return NULL;
19219+}
19220+
19221+/*
19222+ * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
19223+ * @video: ISP video instance
19224+ * @mbus: v4l2_mbus_framefmt format (input)
19225+ * @pix: v4l2_pix_format format (output)
19226+ *
19227+ * Fill the output pix structure with information from the input mbus format.
19228+ * The bytesperline and sizeimage fields are computed from the requested bytes
19229+ * per line value in the pix format and information from the video instance.
19230+ *
19231+ * Return the number of padding bytes at end of line.
19232+ */
19233+static unsigned int isp_video_mbus_to_pix(const struct isp_video *video,
19234+ const struct v4l2_mbus_framefmt *mbus,
19235+ struct v4l2_pix_format *pix)
19236+{
19237+ unsigned int bpl = pix->bytesperline;
19238+ unsigned int min_bpl;
19239+ unsigned int i;
19240+
19241+ memset(pix, 0, sizeof(*pix));
19242+ pix->width = mbus->width;
19243+ pix->height = mbus->height;
19244+
19245+ for (i = 0; i < ARRAY_SIZE(formats); ++i) {
19246+ if (formats[i].code == mbus->code)
19247+ break;
19248+ }
19249+
19250+ if (WARN_ON(i == ARRAY_SIZE(formats)))
19251+ return 0;
19252+
19253+ min_bpl = pix->width * ALIGN(formats[i].bpp, 8) / 8;
19254+
19255+ /* Clamp the requested bytes per line value. If the maximum bytes per
19256+ * line value is zero, the module doesn't support user configurable line
19257+ * sizes. Override the requested value with the minimum in that case.
19258+ */
19259+ if (video->bpl_max)
19260+ bpl = clamp(bpl, min_bpl, video->bpl_max);
19261+ else
19262+ bpl = min_bpl;
19263+
19264+ if (!video->bpl_zero_padding || bpl != min_bpl)
19265+ bpl = ALIGN(bpl, video->bpl_alignment);
19266+
19267+ pix->pixelformat = formats[i].pixelformat;
19268+ pix->bytesperline = bpl;
19269+ pix->sizeimage = pix->bytesperline * pix->height;
19270+ pix->colorspace = mbus->colorspace;
19271+ pix->field = mbus->field;
19272+
19273+ return bpl - min_bpl;
19274+}
19275+
19276+static void isp_video_pix_to_mbus(const struct v4l2_pix_format *pix,
19277+ struct v4l2_mbus_framefmt *mbus)
19278+{
19279+ unsigned int i;
19280+
19281+ memset(mbus, 0, sizeof(*mbus));
19282+ mbus->width = pix->width;
19283+ mbus->height = pix->height;
19284+
19285+ for (i = 0; i < ARRAY_SIZE(formats); ++i) {
19286+ if (formats[i].pixelformat == pix->pixelformat)
19287+ break;
19288+ }
19289+
19290+ if (WARN_ON(i == ARRAY_SIZE(formats)))
19291+ return;
19292+
19293+ mbus->code = formats[i].code;
19294+ mbus->colorspace = pix->colorspace;
19295+ mbus->field = pix->field;
19296+}
19297+
19298+static struct v4l2_subdev *
19299+isp_video_remote_subdev(struct isp_video *video, u32 *pad)
19300+{
19301+ struct media_pad *remote;
19302+
19303+ remote = media_entity_remote_source(&video->pad);
19304+
19305+ if (remote == NULL ||
19306+ media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
19307+ return NULL;
19308+
19309+ if (pad)
19310+ *pad = remote->index;
19311+
19312+ return media_entity_to_v4l2_subdev(remote->entity);
19313+}
19314+
19315+/* Return a pointer to the ISP video instance at the far end of the pipeline. */
19316+static struct isp_video *
19317+isp_video_far_end(struct isp_video *video)
19318+{
19319+ struct media_entity_graph graph;
19320+ struct media_entity *entity = &video->video.entity;
19321+ struct media_device *mdev = entity->parent;
19322+ struct isp_video *far_end = NULL;
19323+
19324+ mutex_lock(&mdev->graph_mutex);
19325+ media_entity_graph_walk_start(&graph, entity);
19326+
19327+ while ((entity = media_entity_graph_walk_next(&graph))) {
19328+ if (entity == &video->video.entity)
19329+ continue;
19330+
19331+ if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
19332+ continue;
19333+
19334+ far_end = to_isp_video(media_entity_to_video_device(entity));
19335+ if (far_end->type != video->type)
19336+ break;
19337+
19338+ far_end = NULL;
19339+ }
19340+
19341+ mutex_unlock(&mdev->graph_mutex);
19342+ return far_end;
19343+}
19344+
19345+/*
19346+ * Validate a pipeline by checking both ends of all links for format
19347+ * discrepancies.
19348+ *
19349+ * Compute the minimum time per frame value as the maximum of time per frame
19350+ * limits reported by every block in the pipeline.
19351+ *
19352+ * Return 0 if all formats match, or -EPIPE if at least one link is found with
19353+ * different formats on its two ends.
19354+ */
19355+static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
19356+{
19357+ struct isp_device *isp = pipe->output->isp;
19358+ struct v4l2_subdev_format fmt_source;
19359+ struct v4l2_subdev_format fmt_sink;
19360+ struct media_pad *pad;
19361+ struct v4l2_subdev *subdev;
19362+ int ret;
19363+
19364+ pipe->max_rate = pipe->l3_ick;
19365+
19366+ subdev = isp_video_remote_subdev(pipe->output, NULL);
19367+ if (subdev == NULL)
19368+ return -EPIPE;
19369+
19370+ while (1) {
19371+ /* Retrieve the sink format */
19372+ pad = &subdev->entity.pads[0];
19373+ if (!(pad->flags & MEDIA_PAD_FL_INPUT))
19374+ break;
19375+
19376+ fmt_sink.pad = pad->index;
19377+ fmt_sink.which = V4L2_SUBDEV_FORMAT_ACTIVE;
19378+ ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_sink);
19379+ if (ret < 0 && ret != -ENOIOCTLCMD)
19380+ return -EPIPE;
19381+
19382+ /* Update the maximum frame rate */
19383+ if (subdev == &isp->isp_res.subdev)
19384+ omap3isp_resizer_max_rate(&isp->isp_res,
19385+ &pipe->max_rate);
19386+
19387+ /* Check ccdc maximum data rate when data comes from sensor
19388+ * TODO: Include ccdc rate in pipe->max_rate and compare the
19389+ * total pipe rate with the input data rate from sensor.
19390+ */
19391+ if (subdev == &isp->isp_ccdc.subdev && pipe->input == NULL) {
19392+ unsigned int rate = UINT_MAX;
19393+
19394+ omap3isp_ccdc_max_rate(&isp->isp_ccdc, &rate);
19395+ if (isp->isp_ccdc.vpcfg.pixelclk > rate)
19396+ return -ENOSPC;
19397+ }
19398+
19399+ /* Retrieve the source format */
19400+ pad = media_entity_remote_source(pad);
19401+ if (pad == NULL ||
19402+ media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
19403+ break;
19404+
19405+ subdev = media_entity_to_v4l2_subdev(pad->entity);
19406+
19407+ fmt_source.pad = pad->index;
19408+ fmt_source.which = V4L2_SUBDEV_FORMAT_ACTIVE;
19409+ ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_source);
19410+ if (ret < 0 && ret != -ENOIOCTLCMD)
19411+ return -EPIPE;
19412+
19413+ /* Check if the two ends match */
19414+ if (fmt_source.format.code != fmt_sink.format.code ||
19415+ fmt_source.format.width != fmt_sink.format.width ||
19416+ fmt_source.format.height != fmt_sink.format.height)
19417+ return -EPIPE;
19418+ }
19419+
19420+ return 0;
19421+}
19422+
19423+static int
19424+__isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
19425+{
19426+ struct v4l2_subdev_format fmt;
19427+ struct v4l2_subdev *subdev;
19428+ u32 pad;
19429+ int ret;
19430+
19431+ subdev = isp_video_remote_subdev(video, &pad);
19432+ if (subdev == NULL)
19433+ return -EINVAL;
19434+
19435+ mutex_lock(&video->mutex);
19436+
19437+ fmt.pad = pad;
19438+ fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
19439+ ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
19440+ if (ret == -ENOIOCTLCMD)
19441+ ret = -EINVAL;
19442+
19443+ mutex_unlock(&video->mutex);
19444+
19445+ if (ret)
19446+ return ret;
19447+
19448+ format->type = video->type;
19449+ return isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
19450+}
19451+
19452+static int
19453+isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
19454+{
19455+ struct v4l2_format format;
19456+ int ret;
19457+
19458+ memcpy(&format, &vfh->format, sizeof(format));
19459+ ret = __isp_video_get_format(video, &format);
19460+ if (ret < 0)
19461+ return ret;
19462+
19463+ if (vfh->format.fmt.pix.pixelformat != format.fmt.pix.pixelformat ||
19464+ vfh->format.fmt.pix.height != format.fmt.pix.height ||
19465+ vfh->format.fmt.pix.width != format.fmt.pix.width ||
19466+ vfh->format.fmt.pix.bytesperline != format.fmt.pix.bytesperline ||
19467+ vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage)
19468+ return -EINVAL;
19469+
19470+ return ret;
19471+}
19472+
19473+/* -----------------------------------------------------------------------------
19474+ * IOMMU management
19475+ */
19476+
19477+#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
19478+
19479+/*
19480+ * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list
19481+ * @dev: Device pointer specific to the OMAP3 ISP.
19482+ * @sglist: Pointer to source Scatter gather list to allocate.
19483+ * @sglen: Number of elements of the scatter-gatter list.
19484+ *
19485+ * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
19486+ * we ran out of memory.
19487+ */
19488+static dma_addr_t
19489+ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
19490+{
19491+ struct sg_table *sgt;
19492+ u32 da;
19493+
19494+ sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
19495+ if (sgt == NULL)
19496+ return -ENOMEM;
19497+
19498+ sgt->sgl = (struct scatterlist *)sglist;
19499+ sgt->nents = sglen;
19500+ sgt->orig_nents = sglen;
19501+
19502+ da = iommu_vmap(isp->iommu, 0, sgt, IOMMU_FLAG);
19503+ if (IS_ERR_VALUE(da))
19504+ kfree(sgt);
19505+
19506+ return da;
19507+}
19508+
19509+/*
19510+ * ispmmu_vunmap - Unmap a device address from the ISP MMU
19511+ * @dev: Device pointer specific to the OMAP3 ISP.
19512+ * @da: Device address generated from a ispmmu_vmap call.
19513+ */
19514+static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
19515+{
19516+ struct sg_table *sgt;
19517+
19518+ sgt = iommu_vunmap(isp->iommu, (u32)da);
19519+ kfree(sgt);
19520+}
19521+
19522+/* -----------------------------------------------------------------------------
19523+ * Video queue operations
19524+ */
19525+
19526+static void isp_video_queue_prepare(struct isp_video_queue *queue,
19527+ unsigned int *nbuffers, unsigned int *size)
19528+{
19529+ struct isp_video_fh *vfh =
19530+ container_of(queue, struct isp_video_fh, queue);
19531+ struct isp_video *video = vfh->video;
19532+
19533+ *size = vfh->format.fmt.pix.sizeimage;
19534+ if (*size == 0)
19535+ return;
19536+
19537+ *nbuffers = min(*nbuffers, video->capture_mem / PAGE_ALIGN(*size));
19538+}
19539+
19540+static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
19541+{
19542+ struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
19543+ struct isp_buffer *buffer = to_isp_buffer(buf);
19544+ struct isp_video *video = vfh->video;
19545+
19546+ if (buffer->isp_addr) {
19547+ ispmmu_vunmap(video->isp, buffer->isp_addr);
19548+ buffer->isp_addr = 0;
19549+ }
19550+}
19551+
19552+static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
19553+{
19554+ struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
19555+ struct isp_buffer *buffer = to_isp_buffer(buf);
19556+ struct isp_video *video = vfh->video;
19557+ unsigned long addr;
19558+
19559+ addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen);
19560+ if (IS_ERR_VALUE(addr))
19561+ return -EIO;
19562+
19563+ if (!IS_ALIGNED(addr, 32)) {
19564+ dev_dbg(video->isp->dev, "Buffer address must be "
19565+ "aligned to 32 bytes boundary.\n");
19566+ ispmmu_vunmap(video->isp, buffer->isp_addr);
19567+ return -EINVAL;
19568+ }
19569+
19570+ buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
19571+ buffer->isp_addr = addr;
19572+ return 0;
19573+}
19574+
19575+/*
19576+ * isp_video_buffer_queue - Add buffer to streaming queue
19577+ * @buf: Video buffer
19578+ *
19579+ * In memory-to-memory mode, start streaming on the pipeline if buffers are
19580+ * queued on both the input and the output, if the pipeline isn't already busy.
19581+ * If the pipeline is busy, it will be restarted in the output module interrupt
19582+ * handler.
19583+ */
19584+static void isp_video_buffer_queue(struct isp_video_buffer *buf)
19585+{
19586+ struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
19587+ struct isp_buffer *buffer = to_isp_buffer(buf);
19588+ struct isp_video *video = vfh->video;
19589+ struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
19590+ enum isp_pipeline_state state;
19591+ unsigned long flags;
19592+ unsigned int empty;
19593+ unsigned int start;
19594+
19595+ empty = list_empty(&video->dmaqueue);
19596+ list_add_tail(&buffer->buffer.irqlist, &video->dmaqueue);
19597+
19598+ if (empty) {
19599+ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
19600+ state = ISP_PIPELINE_QUEUE_OUTPUT;
19601+ else
19602+ state = ISP_PIPELINE_QUEUE_INPUT;
19603+
19604+ spin_lock_irqsave(&pipe->lock, flags);
19605+ pipe->state |= state;
19606+ video->ops->queue(video, buffer);
19607+ video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
19608+
19609+ start = isp_pipeline_ready(pipe);
19610+ if (start)
19611+ pipe->state |= ISP_PIPELINE_STREAM;
19612+ spin_unlock_irqrestore(&pipe->lock, flags);
19613+
19614+ if (start)
19615+ omap3isp_pipeline_set_stream(pipe,
19616+ ISP_PIPELINE_STREAM_SINGLESHOT);
19617+ }
19618+}
19619+
19620+static const struct isp_video_queue_operations isp_video_queue_ops = {
19621+ .queue_prepare = &isp_video_queue_prepare,
19622+ .buffer_prepare = &isp_video_buffer_prepare,
19623+ .buffer_queue = &isp_video_buffer_queue,
19624+ .buffer_cleanup = &isp_video_buffer_cleanup,
19625+};
19626+
19627+/*
19628+ * omap3isp_video_buffer_next - Complete the current buffer and return the next
19629+ * @video: ISP video object
19630+ * @error: Whether an error occured during capture
19631+ *
19632+ * Remove the current video buffer from the DMA queue and fill its timestamp,
19633+ * field count and state fields before waking up its completion handler.
19634+ *
19635+ * The buffer state is set to VIDEOBUF_DONE if no error occured (@error is 0)
19636+ * or VIDEOBUF_ERROR otherwise (@error is non-zero).
19637+ *
19638+ * The DMA queue is expected to contain at least one buffer.
19639+ *
19640+ * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is
19641+ * empty.
19642+ */
19643+struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
19644+ unsigned int error)
19645+{
19646+ struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
19647+ struct isp_video_queue *queue = video->queue;
19648+ enum isp_pipeline_state state;
19649+ struct isp_video_buffer *buf;
19650+ unsigned long flags;
19651+ struct timespec ts;
19652+
19653+ spin_lock_irqsave(&queue->irqlock, flags);
19654+ if (WARN_ON(list_empty(&video->dmaqueue))) {
19655+ spin_unlock_irqrestore(&queue->irqlock, flags);
19656+ return NULL;
19657+ }
19658+
19659+ buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
19660+ irqlist);
19661+ list_del(&buf->irqlist);
19662+ spin_unlock_irqrestore(&queue->irqlock, flags);
19663+
19664+ ktime_get_ts(&ts);
19665+ buf->vbuf.timestamp.tv_sec = ts.tv_sec;
19666+ buf->vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
19667+
19668+ /* Do frame number propagation only if this is the output video node.
19669+ * Frame number either comes from the CSI receivers or it gets
19670+ * incremented here if H3A is not active.
19671+ * Note: There is no guarantee that the output buffer will finish
19672+ * first, so the input number might lag behind by 1 in some cases.
19673+ */
19674+ if (video == pipe->output && !pipe->do_propagation)
19675+ buf->vbuf.sequence = atomic_inc_return(&pipe->frame_number);
19676+ else
19677+ buf->vbuf.sequence = atomic_read(&pipe->frame_number);
19678+
19679+ buf->state = error ? ISP_BUF_STATE_ERROR : ISP_BUF_STATE_DONE;
19680+
19681+ wake_up(&buf->wait);
19682+
19683+ if (list_empty(&video->dmaqueue)) {
19684+ if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
19685+ state = ISP_PIPELINE_QUEUE_OUTPUT
19686+ | ISP_PIPELINE_STREAM;
19687+ else
19688+ state = ISP_PIPELINE_QUEUE_INPUT
19689+ | ISP_PIPELINE_STREAM;
19690+
19691+ spin_lock_irqsave(&pipe->lock, flags);
19692+ pipe->state &= ~state;
19693+ if (video->pipe.stream_state == ISP_PIPELINE_STREAM_CONTINUOUS)
19694+ video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
19695+ spin_unlock_irqrestore(&pipe->lock, flags);
19696+ return NULL;
19697+ }
19698+
19699+ if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) {
19700+ spin_lock_irqsave(&pipe->lock, flags);
19701+ pipe->state &= ~ISP_PIPELINE_STREAM;
19702+ spin_unlock_irqrestore(&pipe->lock, flags);
19703+ }
19704+
19705+ buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
19706+ irqlist);
19707+ buf->state = ISP_BUF_STATE_ACTIVE;
19708+ return to_isp_buffer(buf);
19709+}
19710+
19711+/*
19712+ * omap3isp_video_resume - Perform resume operation on the buffers
19713+ * @video: ISP video object
19714+ * @continuous: Pipeline is in single shot mode if 0 or continous mode otherwise
19715+ *
19716+ * This function is intended to be used on suspend/resume scenario. It
19717+ * requests video queue layer to discard buffers marked as DONE if it's in
19718+ * continuous mode and requests ISP modules to queue again the ACTIVE buffer
19719+ * if there's any.
19720+ */
19721+void omap3isp_video_resume(struct isp_video *video, int continuous)
19722+{
19723+ struct isp_buffer *buf = NULL;
19724+
19725+ if (continuous && video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
19726+ omap3isp_video_queue_discard_done(video->queue);
19727+
19728+ if (!list_empty(&video->dmaqueue)) {
19729+ buf = list_first_entry(&video->dmaqueue,
19730+ struct isp_buffer, buffer.irqlist);
19731+ video->ops->queue(video, buf);
19732+ video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
19733+ } else {
19734+ if (continuous)
19735+ video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
19736+ }
19737+}
19738+
19739+/* -----------------------------------------------------------------------------
19740+ * V4L2 ioctls
19741+ */
19742+
19743+static int
19744+isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
19745+{
19746+ struct isp_video *video = video_drvdata(file);
19747+
19748+ strlcpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver));
19749+ strlcpy(cap->card, video->video.name, sizeof(cap->card));
19750+ strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
19751+ cap->version = ISP_VIDEO_DRIVER_VERSION;
19752+
19753+ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
19754+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
19755+ else
19756+ cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
19757+
19758+ return 0;
19759+}
19760+
19761+static int
19762+isp_video_get_format(struct file *file, void *fh, struct v4l2_format *format)
19763+{
19764+ struct isp_video_fh *vfh = to_isp_video_fh(fh);
19765+ struct isp_video *video = video_drvdata(file);
19766+
19767+ if (format->type != video->type)
19768+ return -EINVAL;
19769+
19770+ mutex_lock(&video->mutex);
19771+ *format = vfh->format;
19772+ mutex_unlock(&video->mutex);
19773+
19774+ return 0;
19775+}
19776+
19777+static int
19778+isp_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
19779+{
19780+ struct isp_video_fh *vfh = to_isp_video_fh(fh);
19781+ struct isp_video *video = video_drvdata(file);
19782+ struct v4l2_mbus_framefmt fmt;
19783+
19784+ if (format->type != video->type)
19785+ return -EINVAL;
19786+
19787+ mutex_lock(&video->mutex);
19788+
19789+ /* Fill the bytesperline and sizeimage fields by converting to media bus
19790+ * format and back to pixel format.
19791+ */
19792+ isp_video_pix_to_mbus(&format->fmt.pix, &fmt);
19793+ isp_video_mbus_to_pix(video, &fmt, &format->fmt.pix);
19794+
19795+ vfh->format = *format;
19796+
19797+ mutex_unlock(&video->mutex);
19798+ return 0;
19799+}
19800+
19801+static int
19802+isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
19803+{
19804+ struct isp_video *video = video_drvdata(file);
19805+ struct v4l2_subdev_format fmt;
19806+ struct v4l2_subdev *subdev;
19807+ u32 pad;
19808+ int ret;
19809+
19810+ if (format->type != video->type)
19811+ return -EINVAL;
19812+
19813+ subdev = isp_video_remote_subdev(video, &pad);
19814+ if (subdev == NULL)
19815+ return -EINVAL;
19816+
19817+ isp_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
19818+
19819+ fmt.pad = pad;
19820+ fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
19821+ ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
19822+ if (ret)
19823+ return ret == -ENOIOCTLCMD ? -EINVAL : ret;
19824+
19825+ isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
19826+ return 0;
19827+}
19828+
19829+static int
19830+isp_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
19831+{
19832+ struct isp_video *video = video_drvdata(file);
19833+ struct v4l2_subdev *subdev;
19834+ int ret;
19835+
19836+ subdev = isp_video_remote_subdev(video, NULL);
19837+ if (subdev == NULL)
19838+ return -EINVAL;
19839+
19840+ mutex_lock(&video->mutex);
19841+ ret = v4l2_subdev_call(subdev, video, cropcap, cropcap);
19842+ mutex_unlock(&video->mutex);
19843+
19844+ return ret == -ENOIOCTLCMD ? -EINVAL : ret;
19845+}
19846+
19847+static int
19848+isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
19849+{
19850+ struct isp_video *video = video_drvdata(file);
19851+ struct v4l2_subdev_format format;
19852+ struct v4l2_subdev *subdev;
19853+ u32 pad;
19854+ int ret;
19855+
19856+ subdev = isp_video_remote_subdev(video, &pad);
19857+ if (subdev == NULL)
19858+ return -EINVAL;
19859+
19860+ /* Try the get crop operation first and fallback to get format if not
19861+ * implemented.
19862+ */
19863+ ret = v4l2_subdev_call(subdev, video, g_crop, crop);
19864+ if (ret != -ENOIOCTLCMD)
19865+ return ret;
19866+
19867+ format.pad = pad;
19868+ format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
19869+ ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
19870+ if (ret < 0)
19871+ return ret == -ENOIOCTLCMD ? -EINVAL : ret;
19872+
19873+ crop->c.left = 0;
19874+ crop->c.top = 0;
19875+ crop->c.width = format.format.width;
19876+ crop->c.height = format.format.height;
19877+
19878+ return 0;
19879+}
19880+
19881+static int
19882+isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop)
19883+{
19884+ struct isp_video *video = video_drvdata(file);
19885+ struct v4l2_subdev *subdev;
19886+ int ret;
19887+
19888+ subdev = isp_video_remote_subdev(video, NULL);
19889+ if (subdev == NULL)
19890+ return -EINVAL;
19891+
19892+ mutex_lock(&video->mutex);
19893+ ret = v4l2_subdev_call(subdev, video, s_crop, crop);
19894+ mutex_unlock(&video->mutex);
19895+
19896+ return ret == -ENOIOCTLCMD ? -EINVAL : ret;
19897+}
19898+
19899+static int
19900+isp_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a)
19901+{
19902+ struct isp_video_fh *vfh = to_isp_video_fh(fh);
19903+ struct isp_video *video = video_drvdata(file);
19904+
19905+ if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
19906+ video->type != a->type)
19907+ return -EINVAL;
19908+
19909+ memset(a, 0, sizeof(*a));
19910+ a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
19911+ a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
19912+ a->parm.output.timeperframe = vfh->timeperframe;
19913+
19914+ return 0;
19915+}
19916+
19917+static int
19918+isp_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a)
19919+{
19920+ struct isp_video_fh *vfh = to_isp_video_fh(fh);
19921+ struct isp_video *video = video_drvdata(file);
19922+
19923+ if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
19924+ video->type != a->type)
19925+ return -EINVAL;
19926+
19927+ if (a->parm.output.timeperframe.denominator == 0)
19928+ a->parm.output.timeperframe.denominator = 1;
19929+
19930+ vfh->timeperframe = a->parm.output.timeperframe;
19931+
19932+ return 0;
19933+}
19934+
19935+static int
19936+isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
19937+{
19938+ struct isp_video_fh *vfh = to_isp_video_fh(fh);
19939+
19940+ return omap3isp_video_queue_reqbufs(&vfh->queue, rb);
19941+}
19942+
19943+static int
19944+isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
19945+{
19946+ struct isp_video_fh *vfh = to_isp_video_fh(fh);
19947+
19948+ return omap3isp_video_queue_querybuf(&vfh->queue, b);
19949+}
19950+
19951+static int
19952+isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
19953+{
19954+ struct isp_video_fh *vfh = to_isp_video_fh(fh);
19955+
19956+ return omap3isp_video_queue_qbuf(&vfh->queue, b);
19957+}
19958+
19959+static int
19960+isp_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
19961+{
19962+ struct isp_video_fh *vfh = to_isp_video_fh(fh);
19963+
19964+ return omap3isp_video_queue_dqbuf(&vfh->queue, b,
19965+ file->f_flags & O_NONBLOCK);
19966+}
19967+
19968+/*
19969+ * Stream management
19970+ *
19971+ * Every ISP pipeline has a single input and a single output. The input can be
19972+ * either a sensor or a video node. The output is always a video node.
19973+ *
19974+ * As every pipeline has an output video node, the ISP video objects at the
19975+ * pipeline output stores the pipeline state. It tracks the streaming state of
19976+ * both the input and output, as well as the availability of buffers.
19977+ *
19978+ * In sensor-to-memory mode, frames are always available at the pipeline input.
19979+ * Starting the sensor usually requires I2C transfers and must be done in
19980+ * interruptible context. The pipeline is started and stopped synchronously
19981+ * to the stream on/off commands. All modules in the pipeline will get their
19982+ * subdev set stream handler called. The module at the end of the pipeline must
19983+ * delay starting the hardware until buffers are available at its output.
19984+ *
19985+ * In memory-to-memory mode, starting/stopping the stream requires
19986+ * synchronization between the input and output. ISP modules can't be stopped
19987+ * in the middle of a frame, and at least some of the modules seem to become
19988+ * busy as soon as they're started, even if they don't receive a frame start
19989+ * event. For that reason frames need to be processed in single-shot mode. The
19990+ * driver needs to wait until a frame is completely processed and written to
19991+ * memory before restarting the pipeline for the next frame. Pipelined
19992+ * processing might be possible but requires more testing.
19993+ *
19994+ * Stream start must be delayed until buffers are available at both the input
19995+ * and output. The pipeline must be started in the videobuf queue callback with
19996+ * the buffers queue spinlock held. The modules subdev set stream operation must
19997+ * not sleep.
19998+ */
19999+static int
20000+isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
20001+{
20002+ struct isp_video_fh *vfh = to_isp_video_fh(fh);
20003+ struct isp_video *video = video_drvdata(file);
20004+ enum isp_pipeline_state state;
20005+ struct isp_pipeline *pipe;
20006+ struct isp_video *far_end;
20007+ unsigned long flags;
20008+ int ret;
20009+
20010+ if (type != video->type)
20011+ return -EINVAL;
20012+
20013+ mutex_lock(&video->stream_lock);
20014+
20015+ if (video->streaming) {
20016+ mutex_unlock(&video->stream_lock);
20017+ return -EBUSY;
20018+ }
20019+
20020+ /* Start streaming on the pipeline. No link touching an entity in the
20021+ * pipeline can be activated or deactivated once streaming is started.
20022+ */
20023+ pipe = video->video.entity.pipe
20024+ ? to_isp_pipeline(&video->video.entity) : &video->pipe;
20025+ media_entity_pipeline_start(&video->video.entity, &pipe->pipe);
20026+
20027+ /* Verify that the currently configured format matches the output of
20028+ * the connected subdev.
20029+ */
20030+ ret = isp_video_check_format(video, vfh);
20031+ if (ret < 0)
20032+ goto error;
20033+
20034+ video->bpl_padding = ret;
20035+ video->bpl_value = vfh->format.fmt.pix.bytesperline;
20036+
20037+ /* Find the ISP video node connected at the far end of the pipeline and
20038+ * update the pipeline.
20039+ */
20040+ far_end = isp_video_far_end(video);
20041+
20042+ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
20043+ state = ISP_PIPELINE_STREAM_OUTPUT | ISP_PIPELINE_IDLE_OUTPUT;
20044+ pipe->input = far_end;
20045+ pipe->output = video;
20046+ } else {
20047+ if (far_end == NULL) {
20048+ ret = -EPIPE;
20049+ goto error;
20050+ }
20051+
20052+ state = ISP_PIPELINE_STREAM_INPUT | ISP_PIPELINE_IDLE_INPUT;
20053+ pipe->input = video;
20054+ pipe->output = far_end;
20055+ }
20056+
20057+ /* Make sure the interconnect clock runs fast enough.
20058+ *
20059+ * Formula from: resource34xx.c set_opp()
20060+ * If MPU freq is above 500MHz, make sure the interconnect
20061+ * is at 100Mhz or above.
20062+ * throughput in KiB/s for 100 Mhz = 100 * 1000 * 4.
20063+ *
20064+ * We want to be fast enough then set OCP clock to be max as
20065+ * possible, in that case 185Mhz then:
20066+ * throughput in KiB/s for 185Mhz = 185 * 1000 * 4 = 740000 KiB/s
20067+ */
20068+ omap_pm_set_min_bus_tput(video->isp->dev, OCP_INITIATOR_AGENT, 740000);
20069+ pipe->l3_ick = clk_get_rate(video->isp->clock[ISP_CLK_L3_ICK]);
20070+
20071+ /* Validate the pipeline and update its state. */
20072+ ret = isp_video_validate_pipeline(pipe);
20073+ if (ret < 0)
20074+ goto error;
20075+
20076+ spin_lock_irqsave(&pipe->lock, flags);
20077+ pipe->state &= ~ISP_PIPELINE_STREAM;
20078+ pipe->state |= state;
20079+ spin_unlock_irqrestore(&pipe->lock, flags);
20080+
20081+ /* Set the maximum time per frame as the value requested by userspace.
20082+ * This is a soft limit that can be overridden if the hardware doesn't
20083+ * support the request limit.
20084+ */
20085+ if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
20086+ pipe->max_timeperframe = vfh->timeperframe;
20087+
20088+ video->queue = &vfh->queue;
20089+ INIT_LIST_HEAD(&video->dmaqueue);
20090+ atomic_set(&pipe->frame_number, -1);
20091+
20092+ ret = omap3isp_video_queue_streamon(&vfh->queue);
20093+ if (ret < 0)
20094+ goto error;
20095+
20096+ /* In sensor-to-memory mode, the stream can be started synchronously
20097+ * to the stream on command. In memory-to-memory mode, it will be
20098+ * started when buffers are queued on both the input and output.
20099+ */
20100+ if (pipe->input == NULL) {
20101+ ret = omap3isp_pipeline_set_stream(pipe,
20102+ ISP_PIPELINE_STREAM_CONTINUOUS);
20103+ if (ret < 0)
20104+ goto error;
20105+ spin_lock_irqsave(&video->queue->irqlock, flags);
20106+ if (list_empty(&video->dmaqueue))
20107+ video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
20108+ spin_unlock_irqrestore(&video->queue->irqlock, flags);
20109+ }
20110+
20111+error:
20112+ if (ret < 0) {
20113+ omap3isp_video_queue_streamoff(&vfh->queue);
20114+ omap_pm_set_min_bus_tput(video->isp->dev,
20115+ OCP_INITIATOR_AGENT, 0);
20116+ media_entity_pipeline_stop(&video->video.entity);
20117+ video->queue = NULL;
20118+ }
20119+
20120+ if (!ret)
20121+ video->streaming = 1;
20122+
20123+ mutex_unlock(&video->stream_lock);
20124+ return ret;
20125+}
20126+
20127+static int
20128+isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
20129+{
20130+ struct isp_video_fh *vfh = to_isp_video_fh(fh);
20131+ struct isp_video *video = video_drvdata(file);
20132+ struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
20133+ enum isp_pipeline_state state;
20134+ unsigned int streaming;
20135+ unsigned long flags;
20136+
20137+ if (type != video->type)
20138+ return -EINVAL;
20139+
20140+ mutex_lock(&video->stream_lock);
20141+
20142+ /* Make sure we're not streaming yet. */
20143+ mutex_lock(&vfh->queue.lock);
20144+ streaming = vfh->queue.streaming;
20145+ mutex_unlock(&vfh->queue.lock);
20146+
20147+ if (!streaming)
20148+ goto done;
20149+
20150+ /* Update the pipeline state. */
20151+ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
20152+ state = ISP_PIPELINE_STREAM_OUTPUT
20153+ | ISP_PIPELINE_QUEUE_OUTPUT;
20154+ else
20155+ state = ISP_PIPELINE_STREAM_INPUT
20156+ | ISP_PIPELINE_QUEUE_INPUT;
20157+
20158+ spin_lock_irqsave(&pipe->lock, flags);
20159+ pipe->state &= ~state;
20160+ spin_unlock_irqrestore(&pipe->lock, flags);
20161+
20162+ /* Stop the stream. */
20163+ omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_STOPPED);
20164+ omap3isp_video_queue_streamoff(&vfh->queue);
20165+ video->queue = NULL;
20166+ video->streaming = 0;
20167+
20168+ omap_pm_set_min_bus_tput(video->isp->dev, OCP_INITIATOR_AGENT, 0);
20169+ media_entity_pipeline_stop(&video->video.entity);
20170+
20171+done:
20172+ mutex_unlock(&video->stream_lock);
20173+ return 0;
20174+}
20175+
20176+static int
20177+isp_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
20178+{
20179+ if (input->index > 0)
20180+ return -EINVAL;
20181+
20182+ strlcpy(input->name, "camera", sizeof(input->name));
20183+ input->type = V4L2_INPUT_TYPE_CAMERA;
20184+
20185+ return 0;
20186+}
20187+
20188+static int
20189+isp_video_g_input(struct file *file, void *fh, unsigned int *input)
20190+{
20191+ *input = 0;
20192+
20193+ return 0;
20194+}
20195+
20196+static int
20197+isp_video_s_input(struct file *file, void *fh, unsigned int input)
20198+{
20199+ return input == 0 ? 0 : -EINVAL;
20200+}
20201+
20202+static const struct v4l2_ioctl_ops isp_video_ioctl_ops = {
20203+ .vidioc_querycap = isp_video_querycap,
20204+ .vidioc_g_fmt_vid_cap = isp_video_get_format,
20205+ .vidioc_s_fmt_vid_cap = isp_video_set_format,
20206+ .vidioc_try_fmt_vid_cap = isp_video_try_format,
20207+ .vidioc_g_fmt_vid_out = isp_video_get_format,
20208+ .vidioc_s_fmt_vid_out = isp_video_set_format,
20209+ .vidioc_try_fmt_vid_out = isp_video_try_format,
20210+ .vidioc_cropcap = isp_video_cropcap,
20211+ .vidioc_g_crop = isp_video_get_crop,
20212+ .vidioc_s_crop = isp_video_set_crop,
20213+ .vidioc_g_parm = isp_video_get_param,
20214+ .vidioc_s_parm = isp_video_set_param,
20215+ .vidioc_reqbufs = isp_video_reqbufs,
20216+ .vidioc_querybuf = isp_video_querybuf,
20217+ .vidioc_qbuf = isp_video_qbuf,
20218+ .vidioc_dqbuf = isp_video_dqbuf,
20219+ .vidioc_streamon = isp_video_streamon,
20220+ .vidioc_streamoff = isp_video_streamoff,
20221+ .vidioc_enum_input = isp_video_enum_input,
20222+ .vidioc_g_input = isp_video_g_input,
20223+ .vidioc_s_input = isp_video_s_input,
20224+};
20225+
20226+/* -----------------------------------------------------------------------------
20227+ * V4L2 file operations
20228+ */
20229+
20230+static int isp_video_open(struct file *file)
20231+{
20232+ struct isp_video *video = video_drvdata(file);
20233+ struct isp_video_fh *handle;
20234+ int ret = 0;
20235+
20236+ handle = kzalloc(sizeof(*handle), GFP_KERNEL);
20237+ if (handle == NULL)
20238+ return -ENOMEM;
20239+
20240+ v4l2_fh_init(&handle->vfh, &video->video);
20241+ v4l2_fh_add(&handle->vfh);
20242+
20243+ /* If this is the first user, initialise the pipeline. */
20244+ if (omap3isp_get(video->isp) == NULL) {
20245+ ret = -EBUSY;
20246+ goto done;
20247+ }
20248+
20249+ ret = omap3isp_pipeline_pm_use(&video->video.entity, 1);
20250+ if (ret < 0) {
20251+ omap3isp_put(video->isp);
20252+ goto done;
20253+ }
20254+
20255+ omap3isp_video_queue_init(&handle->queue, video->type,
20256+ &isp_video_queue_ops, video->isp->dev,
20257+ sizeof(struct isp_buffer));
20258+
20259+ memset(&handle->format, 0, sizeof(handle->format));
20260+ handle->format.type = video->type;
20261+ handle->timeperframe.denominator = 1;
20262+
20263+ handle->video = video;
20264+ file->private_data = &handle->vfh;
20265+
20266+done:
20267+ if (ret < 0) {
20268+ v4l2_fh_del(&handle->vfh);
20269+ kfree(handle);
20270+ }
20271+
20272+ return ret;
20273+}
20274+
20275+static int isp_video_release(struct file *file)
20276+{
20277+ struct isp_video *video = video_drvdata(file);
20278+ struct v4l2_fh *vfh = file->private_data;
20279+ struct isp_video_fh *handle = to_isp_video_fh(vfh);
20280+
20281+ /* Disable streaming and free the buffers queue resources. */
20282+ isp_video_streamoff(file, vfh, video->type);
20283+
20284+ mutex_lock(&handle->queue.lock);
20285+ omap3isp_video_queue_cleanup(&handle->queue);
20286+ mutex_unlock(&handle->queue.lock);
20287+
20288+ omap3isp_pipeline_pm_use(&video->video.entity, 0);
20289+
20290+ /* Release the file handle. */
20291+ v4l2_fh_del(vfh);
20292+ kfree(handle);
20293+ file->private_data = NULL;
20294+
20295+ omap3isp_put(video->isp);
20296+
20297+ return 0;
20298+}
20299+
20300+static unsigned int isp_video_poll(struct file *file, poll_table *wait)
20301+{
20302+ struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
20303+ struct isp_video_queue *queue = &vfh->queue;
20304+
20305+ return omap3isp_video_queue_poll(queue, file, wait);
20306+}
20307+
20308+static int isp_video_mmap(struct file *file, struct vm_area_struct *vma)
20309+{
20310+ struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
20311+
20312+ return omap3isp_video_queue_mmap(&vfh->queue, vma);
20313+}
20314+
20315+static struct v4l2_file_operations isp_video_fops = {
20316+ .owner = THIS_MODULE,
20317+ .unlocked_ioctl = video_ioctl2,
20318+ .open = isp_video_open,
20319+ .release = isp_video_release,
20320+ .poll = isp_video_poll,
20321+ .mmap = isp_video_mmap,
20322+};
20323+
20324+/* -----------------------------------------------------------------------------
20325+ * ISP video core
20326+ */
20327+
20328+static const struct isp_video_operations isp_video_dummy_ops = {
20329+};
20330+
20331+int omap3isp_video_init(struct isp_video *video, const char *name)
20332+{
20333+ const char *direction;
20334+ int ret;
20335+
20336+ switch (video->type) {
20337+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
20338+ direction = "output";
20339+ video->pad.flags = MEDIA_PAD_FL_INPUT;
20340+ break;
20341+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
20342+ direction = "input";
20343+ video->pad.flags = MEDIA_PAD_FL_OUTPUT;
20344+ break;
20345+
20346+ default:
20347+ return -EINVAL;
20348+ }
20349+
20350+ ret = media_entity_init(&video->video.entity, 1, &video->pad, 0);
20351+ if (ret < 0)
20352+ return ret;
20353+
20354+ mutex_init(&video->mutex);
20355+ atomic_set(&video->active, 0);
20356+
20357+ spin_lock_init(&video->pipe.lock);
20358+ mutex_init(&video->stream_lock);
20359+
20360+ /* Initialize the video device. */
20361+ if (video->ops == NULL)
20362+ video->ops = &isp_video_dummy_ops;
20363+
20364+ video->video.fops = &isp_video_fops;
20365+ snprintf(video->video.name, sizeof(video->video.name),
20366+ "OMAP3 ISP %s %s", name, direction);
20367+ video->video.vfl_type = VFL_TYPE_GRABBER;
20368+ video->video.release = video_device_release_empty;
20369+ video->video.ioctl_ops = &isp_video_ioctl_ops;
20370+ video->pipe.stream_state = ISP_PIPELINE_STREAM_STOPPED;
20371+
20372+ video_set_drvdata(&video->video, video);
20373+
20374+ return 0;
20375+}
20376+
20377+int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
20378+{
20379+ int ret;
20380+
20381+ video->video.v4l2_dev = vdev;
20382+
20383+ ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
20384+ if (ret < 0)
20385+ printk(KERN_ERR "%s: could not register video device (%d)\n",
20386+ __func__, ret);
20387+
20388+ return ret;
20389+}
20390+
20391+void omap3isp_video_unregister(struct isp_video *video)
20392+{
20393+ if (video_is_registered(&video->video)) {
20394+ media_entity_cleanup(&video->video.entity);
20395+ video_unregister_device(&video->video);
20396+ }
20397+}
20398diff --git a/drivers/media/video/isp/ispvideo.h b/drivers/media/video/isp/ispvideo.h
20399new file mode 100644
20400index 0000000..41c8fb9
20401--- /dev/null
20402+++ b/drivers/media/video/isp/ispvideo.h
20403@@ -0,0 +1,202 @@
20404+/*
20405+ * ispvideo.h
20406+ *
20407+ * TI OMAP3 ISP - Generic video node
20408+ *
20409+ * Copyright (C) 2009-2010 Nokia Corporation
20410+ *
20411+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
20412+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
20413+ *
20414+ * This program is free software; you can redistribute it and/or modify
20415+ * it under the terms of the GNU General Public License version 2 as
20416+ * published by the Free Software Foundation.
20417+ *
20418+ * This program is distributed in the hope that it will be useful, but
20419+ * WITHOUT ANY WARRANTY; without even the implied warranty of
20420+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20421+ * General Public License for more details.
20422+ *
20423+ * You should have received a copy of the GNU General Public License
20424+ * along with this program; if not, write to the Free Software
20425+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20426+ * 02110-1301 USA
20427+ */
20428+
20429+#ifndef OMAP3_ISP_VIDEO_H
20430+#define OMAP3_ISP_VIDEO_H
20431+
20432+#include <linux/v4l2-mediabus.h>
20433+#include <linux/version.h>
20434+#include <media/media-entity.h>
20435+#include <media/v4l2-dev.h>
20436+#include <media/v4l2-fh.h>
20437+
20438+#include "ispqueue.h"
20439+
20440+#define ISP_VIDEO_DRIVER_NAME "ispvideo"
20441+#define ISP_VIDEO_DRIVER_VERSION KERNEL_VERSION(0, 0, 1)
20442+
20443+struct isp_device;
20444+struct isp_video;
20445+struct v4l2_mbus_framefmt;
20446+struct v4l2_pix_format;
20447+
20448+/*
20449+ * struct isp_format_info - ISP media bus format information
20450+ * @code: V4L2 media bus format code
20451+ * @truncated: V4L2 media bus format code for the same format truncated to 10
20452+ * bits. Identical to @code if the format is 10 bits wide or less.
20453+ * @uncompressed: V4L2 media bus format code for the corresponding uncompressed
20454+ * format. Identical to @code if the format is not DPCM compressed.
20455+ * @pixelformat: V4L2 pixel format FCC identifier
20456+ * @bpp: Bits per pixel
20457+ */
20458+struct isp_format_info {
20459+ enum v4l2_mbus_pixelcode code;
20460+ enum v4l2_mbus_pixelcode truncated;
20461+ enum v4l2_mbus_pixelcode uncompressed;
20462+ u32 pixelformat;
20463+ unsigned int bpp;
20464+};
20465+
20466+enum isp_pipeline_stream_state {
20467+ ISP_PIPELINE_STREAM_STOPPED = 0,
20468+ ISP_PIPELINE_STREAM_CONTINUOUS = 1,
20469+ ISP_PIPELINE_STREAM_SINGLESHOT = 2,
20470+};
20471+
20472+enum isp_pipeline_state {
20473+ /* The stream has been started on the input video node. */
20474+ ISP_PIPELINE_STREAM_INPUT = 1,
20475+ /* The stream has been started on the output video node. */
20476+ ISP_PIPELINE_STREAM_OUTPUT = 2,
20477+ /* At least one buffer is queued on the input video node. */
20478+ ISP_PIPELINE_QUEUE_INPUT = 4,
20479+ /* At least one buffer is queued on the output video node. */
20480+ ISP_PIPELINE_QUEUE_OUTPUT = 8,
20481+ /* The input entity is idle, ready to be started. */
20482+ ISP_PIPELINE_IDLE_INPUT = 16,
20483+ /* The output entity is idle, ready to be started. */
20484+ ISP_PIPELINE_IDLE_OUTPUT = 32,
20485+ /* The pipeline is currently streaming. */
20486+ ISP_PIPELINE_STREAM = 64,
20487+};
20488+
20489+struct isp_pipeline {
20490+ struct media_pipeline pipe;
20491+ spinlock_t lock;
20492+ unsigned int state;
20493+ enum isp_pipeline_stream_state stream_state;
20494+ struct isp_video *input;
20495+ struct isp_video *output;
20496+ unsigned long l3_ick;
20497+ unsigned int max_rate;
20498+ atomic_t frame_number;
20499+ bool do_propagation; /* of frame number */
20500+ struct v4l2_fract max_timeperframe;
20501+};
20502+
20503+#define to_isp_pipeline(__e) \
20504+ container_of((__e)->pipe, struct isp_pipeline, pipe)
20505+
20506+static inline int isp_pipeline_ready(struct isp_pipeline *pipe)
20507+{
20508+ return pipe->state == (ISP_PIPELINE_STREAM_INPUT |
20509+ ISP_PIPELINE_STREAM_OUTPUT |
20510+ ISP_PIPELINE_QUEUE_INPUT |
20511+ ISP_PIPELINE_QUEUE_OUTPUT |
20512+ ISP_PIPELINE_IDLE_INPUT |
20513+ ISP_PIPELINE_IDLE_OUTPUT);
20514+}
20515+
20516+/*
20517+ * struct isp_buffer - ISP buffer
20518+ * @buffer: ISP video buffer
20519+ * @isp_addr: MMU mapped address (a.k.a. device address) of the buffer.
20520+ */
20521+struct isp_buffer {
20522+ struct isp_video_buffer buffer;
20523+ dma_addr_t isp_addr;
20524+};
20525+
20526+#define to_isp_buffer(buf) container_of(buf, struct isp_buffer, buffer)
20527+
20528+enum isp_video_dmaqueue_flags {
20529+ /* Set if DMA queue becomes empty when ISP_PIPELINE_STREAM_CONTINUOUS */
20530+ ISP_VIDEO_DMAQUEUE_UNDERRUN = (1 << 0),
20531+ /* Set when queuing buffer to an empty DMA queue */
20532+ ISP_VIDEO_DMAQUEUE_QUEUED = (1 << 1),
20533+};
20534+
20535+#define isp_video_dmaqueue_flags_clr(video) \
20536+ ({ (video)->dmaqueue_flags = 0; })
20537+
20538+/*
20539+ * struct isp_video_operations - ISP video operations
20540+ * @queue: Resume streaming when a buffer is queued. Called on VIDIOC_QBUF
20541+ * if there was no buffer previously queued.
20542+ */
20543+struct isp_video_operations {
20544+ int(*queue)(struct isp_video *video, struct isp_buffer *buffer);
20545+};
20546+
20547+struct isp_video {
20548+ struct video_device video;
20549+ enum v4l2_buf_type type;
20550+ struct media_pad pad;
20551+
20552+ struct mutex mutex;
20553+ atomic_t active;
20554+
20555+ struct isp_device *isp;
20556+
20557+ unsigned int capture_mem;
20558+ unsigned int bpl_alignment; /* alignment value */
20559+ unsigned int bpl_zero_padding; /* whether the alignment is optional */
20560+ unsigned int bpl_max; /* maximum bytes per line value */
20561+ unsigned int bpl_value; /* bytes per line value */
20562+ unsigned int bpl_padding; /* padding at end of line */
20563+
20564+ /* Entity video node streaming */
20565+ unsigned int streaming:1;
20566+
20567+ /* Pipeline state */
20568+ struct isp_pipeline pipe;
20569+ struct mutex stream_lock;
20570+
20571+ /* Video buffers queue */
20572+ struct isp_video_queue *queue;
20573+ struct list_head dmaqueue;
20574+ enum isp_video_dmaqueue_flags dmaqueue_flags;
20575+
20576+ const struct isp_video_operations *ops;
20577+};
20578+
20579+#define to_isp_video(vdev) container_of(vdev, struct isp_video, video)
20580+
20581+struct isp_video_fh {
20582+ struct v4l2_fh vfh;
20583+ struct isp_video *video;
20584+ struct isp_video_queue queue;
20585+ struct v4l2_format format;
20586+ struct v4l2_fract timeperframe;
20587+};
20588+
20589+#define to_isp_video_fh(fh) container_of(fh, struct isp_video_fh, vfh)
20590+#define isp_video_queue_to_isp_video_fh(q) \
20591+ container_of(q, struct isp_video_fh, queue)
20592+
20593+int omap3isp_video_init(struct isp_video *video, const char *name);
20594+int omap3isp_video_register(struct isp_video *video,
20595+ struct v4l2_device *vdev);
20596+void omap3isp_video_unregister(struct isp_video *video);
20597+struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
20598+ unsigned int error);
20599+void omap3isp_video_resume(struct isp_video *video, int continuous);
20600+struct media_pad *omap3isp_video_remote_pad(struct isp_video *video);
20601+
20602+const struct isp_format_info *
20603+omap3isp_video_format_info(enum v4l2_mbus_pixelcode code);
20604+
20605+#endif /* OMAP3_ISP_VIDEO_H */
20606diff --git a/drivers/media/video/isp/luma_enhance_table.h b/drivers/media/video/isp/luma_enhance_table.h
20607new file mode 100644
20608index 0000000..56d93c2
20609--- /dev/null
20610+++ b/drivers/media/video/isp/luma_enhance_table.h
20611@@ -0,0 +1,154 @@
20612+/*
20613+ * luma_enhance_table.h
20614+ *
20615+ * TI OMAP3 ISP - Luminance enhancement table
20616+ *
20617+ * Copyright (C) 2010 Nokia Corporation
20618+ * Copyright (C) 2009 Texas Instruments, Inc.
20619+ *
20620+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
20621+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
20622+ *
20623+ * This program is free software; you can redistribute it and/or modify
20624+ * it under the terms of the GNU General Public License version 2 as
20625+ * published by the Free Software Foundation.
20626+ *
20627+ * This program is distributed in the hope that it will be useful, but
20628+ * WITHOUT ANY WARRANTY; without even the implied warranty of
20629+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20630+ * General Public License for more details.
20631+ *
20632+ * You should have received a copy of the GNU General Public License
20633+ * along with this program; if not, write to the Free Software
20634+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20635+ * 02110-1301 USA
20636+ */
20637+
20638+1047552,
20639+1047552,
20640+1047552,
20641+1047552,
20642+1047552,
20643+1047552,
20644+1047552,
20645+1047552,
20646+1047552,
20647+1047552,
20648+1047552,
20649+1047552,
20650+1047552,
20651+1047552,
20652+1047552,
20653+1047552,
20654+1047552,
20655+1047552,
20656+1047552,
20657+1047552,
20658+1047552,
20659+1047552,
20660+1047552,
20661+1047552,
20662+1047552,
20663+1047552,
20664+1047552,
20665+1047552,
20666+1048575,
20667+1047551,
20668+1046527,
20669+1045503,
20670+1044479,
20671+1043455,
20672+1042431,
20673+1041407,
20674+1040383,
20675+1039359,
20676+1038335,
20677+1037311,
20678+1036287,
20679+1035263,
20680+1034239,
20681+1033215,
20682+1032191,
20683+1031167,
20684+1030143,
20685+1028096,
20686+1028096,
20687+1028096,
20688+1028096,
20689+1028096,
20690+1028096,
20691+1028096,
20692+1028096,
20693+1028096,
20694+1028096,
20695+1028100,
20696+1032196,
20697+1036292,
20698+1040388,
20699+1044484,
20700+0,
20701+0,
20702+0,
20703+5,
20704+5125,
20705+10245,
20706+15365,
20707+20485,
20708+25605,
20709+30720,
20710+30720,
20711+30720,
20712+30720,
20713+30720,
20714+30720,
20715+30720,
20716+30720,
20717+30720,
20718+30720,
20719+30720,
20720+31743,
20721+30719,
20722+29695,
20723+28671,
20724+27647,
20725+26623,
20726+25599,
20727+24575,
20728+23551,
20729+22527,
20730+21503,
20731+20479,
20732+19455,
20733+18431,
20734+17407,
20735+16383,
20736+15359,
20737+14335,
20738+13311,
20739+12287,
20740+11263,
20741+10239,
20742+9215,
20743+8191,
20744+7167,
20745+6143,
20746+5119,
20747+4095,
20748+3071,
20749+1024,
20750+1024,
20751+1024,
20752+1024,
20753+1024,
20754+1024,
20755+1024,
20756+1024,
20757+1024,
20758+1024,
20759+1024,
20760+1024,
20761+1024,
20762+1024,
20763+1024,
20764+1024,
20765+1024
20766diff --git a/drivers/media/video/isp/noise_filter_table.h b/drivers/media/video/isp/noise_filter_table.h
20767new file mode 100644
20768index 0000000..4b4c085
20769--- /dev/null
20770+++ b/drivers/media/video/isp/noise_filter_table.h
20771@@ -0,0 +1,90 @@
20772+/*
20773+ * noise_filter_table.h
20774+ *
20775+ * TI OMAP3 ISP - Noise filter table
20776+ *
20777+ * Copyright (C) 2010 Nokia Corporation
20778+ * Copyright (C) 2009 Texas Instruments, Inc.
20779+ *
20780+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
20781+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
20782+ *
20783+ * This program is free software; you can redistribute it and/or modify
20784+ * it under the terms of the GNU General Public License version 2 as
20785+ * published by the Free Software Foundation.
20786+ *
20787+ * This program is distributed in the hope that it will be useful, but
20788+ * WITHOUT ANY WARRANTY; without even the implied warranty of
20789+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20790+ * General Public License for more details.
20791+ *
20792+ * You should have received a copy of the GNU General Public License
20793+ * along with this program; if not, write to the Free Software
20794+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20795+ * 02110-1301 USA
20796+ */
20797+
20798+16,
20799+16,
20800+16,
20801+16,
20802+16,
20803+16,
20804+16,
20805+16,
20806+16,
20807+16,
20808+16,
20809+16,
20810+16,
20811+16,
20812+16,
20813+16,
20814+16,
20815+16,
20816+16,
20817+16,
20818+16,
20819+16,
20820+16,
20821+16,
20822+16,
20823+16,
20824+16,
20825+16,
20826+16,
20827+16,
20828+16,
20829+16,
20830+31,
20831+31,
20832+31,
20833+31,
20834+31,
20835+31,
20836+31,
20837+31,
20838+31,
20839+31,
20840+31,
20841+31,
20842+31,
20843+31,
20844+31,
20845+31,
20846+31,
20847+31,
20848+31,
20849+31,
20850+31,
20851+31,
20852+31,
20853+31,
20854+31,
20855+31,
20856+31,
20857+31,
20858+31,
20859+31,
20860+31,
20861+31
20862diff --git a/include/linux/Kbuild b/include/linux/Kbuild
20863index c0db7f4..f65f612 100644
20864--- a/include/linux/Kbuild
20865+++ b/include/linux/Kbuild
20866@@ -272,6 +272,7 @@ header-y += nfsacl.h
20867 header-y += nl80211.h
20868 header-y += nubus.h
20869 header-y += nvram.h
20870+header-y += omap3isp.h
20871 header-y += omapfb.h
20872 header-y += oom.h
20873 header-y += param.h
20874diff --git a/include/linux/omap3isp.h b/include/linux/omap3isp.h
20875new file mode 100644
20876index 0000000..ab249b2
20877--- /dev/null
20878+++ b/include/linux/omap3isp.h
20879@@ -0,0 +1,631 @@
20880+/*
20881+ * omap3isp.h
20882+ *
20883+ * TI OMAP3 ISP - User-space API
20884+ *
20885+ * Copyright (C) 2010 Nokia Corporation
20886+ * Copyright (C) 2009 Texas Instruments, Inc.
20887+ *
20888+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
20889+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
20890+ *
20891+ * This program is free software; you can redistribute it and/or modify
20892+ * it under the terms of the GNU General Public License version 2 as
20893+ * published by the Free Software Foundation.
20894+ *
20895+ * This program is distributed in the hope that it will be useful, but
20896+ * WITHOUT ANY WARRANTY; without even the implied warranty of
20897+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20898+ * General Public License for more details.
20899+ *
20900+ * You should have received a copy of the GNU General Public License
20901+ * along with this program; if not, write to the Free Software
20902+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20903+ * 02110-1301 USA
20904+ */
20905+
20906+#ifndef OMAP3_ISP_USER_H
20907+#define OMAP3_ISP_USER_H
20908+
20909+#include <linux/types.h>
20910+
20911+/* Private IOCTLs */
20912+
20913+#define VIDIOC_OMAP3ISP_CCDC_CFG \
20914+ _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct omap3isp_ccdc_update_config)
20915+#define VIDIOC_OMAP3ISP_PRV_CFG \
20916+ _IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct omap3isp_prev_update_config)
20917+#define VIDIOC_OMAP3ISP_AEWB_CFG \
20918+ _IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct omap3isp_h3a_aewb_config)
20919+#define VIDIOC_OMAP3ISP_HIST_CFG \
20920+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct omap3isp_hist_config)
20921+#define VIDIOC_OMAP3ISP_AF_CFG \
20922+ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct omap3isp_h3a_af_config)
20923+#define VIDIOC_OMAP3ISP_STAT_REQ \
20924+ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct omap3isp_stat_data)
20925+#define VIDIOC_OMAP3ISP_STAT_EN \
20926+ _IOWR('V', BASE_VIDIOC_PRIVATE + 7, unsigned long)
20927+
20928+/* Events */
20929+
20930+#define V4L2_EVENT_OMAP3ISP_CLASS (V4L2_EVENT_PRIVATE_START | 0x100)
20931+#define V4L2_EVENT_OMAP3ISP_AEWB (V4L2_EVENT_OMAP3ISP_CLASS | 0x1)
20932+#define V4L2_EVENT_OMAP3ISP_AF (V4L2_EVENT_OMAP3ISP_CLASS | 0x2)
20933+#define V4L2_EVENT_OMAP3ISP_HIST (V4L2_EVENT_OMAP3ISP_CLASS | 0x3)
20934+#define V4L2_EVENT_OMAP3ISP_HS_VS (V4L2_EVENT_OMAP3ISP_CLASS | 0x4)
20935+
20936+struct omap3isp_stat_event_status {
20937+ __u32 frame_number;
20938+ __u16 config_counter;
20939+ __u8 buf_err;
20940+};
20941+
20942+/* AE/AWB related structures and flags*/
20943+
20944+/* H3A Range Constants */
20945+#define OMAP3ISP_AEWB_MAX_SATURATION_LIM 1023
20946+#define OMAP3ISP_AEWB_MIN_WIN_H 2
20947+#define OMAP3ISP_AEWB_MAX_WIN_H 256
20948+#define OMAP3ISP_AEWB_MIN_WIN_W 6
20949+#define OMAP3ISP_AEWB_MAX_WIN_W 256
20950+#define OMAP3ISP_AEWB_MIN_WINVC 1
20951+#define OMAP3ISP_AEWB_MIN_WINHC 1
20952+#define OMAP3ISP_AEWB_MAX_WINVC 128
20953+#define OMAP3ISP_AEWB_MAX_WINHC 36
20954+#define OMAP3ISP_AEWB_MAX_WINSTART 4095
20955+#define OMAP3ISP_AEWB_MIN_SUB_INC 2
20956+#define OMAP3ISP_AEWB_MAX_SUB_INC 32
20957+#define OMAP3ISP_AEWB_MAX_BUF_SIZE 83600
20958+
20959+#define OMAP3ISP_AF_IIRSH_MIN 0
20960+#define OMAP3ISP_AF_IIRSH_MAX 4095
20961+#define OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN 1
20962+#define OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MAX 36
20963+#define OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN 1
20964+#define OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MAX 128
20965+#define OMAP3ISP_AF_PAXEL_INCREMENT_MIN 2
20966+#define OMAP3ISP_AF_PAXEL_INCREMENT_MAX 32
20967+#define OMAP3ISP_AF_PAXEL_HEIGHT_MIN 2
20968+#define OMAP3ISP_AF_PAXEL_HEIGHT_MAX 256
20969+#define OMAP3ISP_AF_PAXEL_WIDTH_MIN 16
20970+#define OMAP3ISP_AF_PAXEL_WIDTH_MAX 256
20971+#define OMAP3ISP_AF_PAXEL_HZSTART_MIN 1
20972+#define OMAP3ISP_AF_PAXEL_HZSTART_MAX 4095
20973+#define OMAP3ISP_AF_PAXEL_VTSTART_MIN 0
20974+#define OMAP3ISP_AF_PAXEL_VTSTART_MAX 4095
20975+#define OMAP3ISP_AF_THRESHOLD_MAX 255
20976+#define OMAP3ISP_AF_COEF_MAX 4095
20977+#define OMAP3ISP_AF_PAXEL_SIZE 48
20978+#define OMAP3ISP_AF_MAX_BUF_SIZE 221184
20979+
20980+/**
20981+ * struct omap3isp_h3a_aewb_config - AE AWB configuration reset values
20982+ * saturation_limit: Saturation limit.
20983+ * @win_height: Window Height. Range 2 - 256, even values only.
20984+ * @win_width: Window Width. Range 6 - 256, even values only.
20985+ * @ver_win_count: Vertical Window Count. Range 1 - 128.
20986+ * @hor_win_count: Horizontal Window Count. Range 1 - 36.
20987+ * @ver_win_start: Vertical Window Start. Range 0 - 4095.
20988+ * @hor_win_start: Horizontal Window Start. Range 0 - 4095.
20989+ * @blk_ver_win_start: Black Vertical Windows Start. Range 0 - 4095.
20990+ * @blk_win_height: Black Window Height. Range 2 - 256, even values only.
20991+ * @subsample_ver_inc: Subsample Vertical points increment Range 2 - 32, even
20992+ * values only.
20993+ * @subsample_hor_inc: Subsample Horizontal points increment Range 2 - 32, even
20994+ * values only.
20995+ * @alaw_enable: AEW ALAW EN flag.
20996+ * @aewb_enable: AE AWB stats generation EN flag.
20997+ */
20998+struct omap3isp_h3a_aewb_config {
20999+ /*
21000+ * Common fields.
21001+ * They should be the first ones and must be in the same order as in
21002+ * ispstat_generic_config struct.
21003+ */
21004+ __u32 buf_size;
21005+ __u16 config_counter;
21006+
21007+ /* Private fields */
21008+ __u16 saturation_limit;
21009+ __u16 win_height;
21010+ __u16 win_width;
21011+ __u16 ver_win_count;
21012+ __u16 hor_win_count;
21013+ __u16 ver_win_start;
21014+ __u16 hor_win_start;
21015+ __u16 blk_ver_win_start;
21016+ __u16 blk_win_height;
21017+ __u16 subsample_ver_inc;
21018+ __u16 subsample_hor_inc;
21019+ __u8 alaw_enable;
21020+};
21021+
21022+/**
21023+ * struct omap3isp_stat_data - Statistic data sent to or received from user
21024+ * @buf: Pointer to pass to user.
21025+ * @frame_number: Frame number of requested stats.
21026+ * @cur_frame: Current frame number being processed.
21027+ * @buf_size: Buffer size requested and returned.
21028+ * @ts: Timestamp of returned framestats.
21029+ */
21030+struct omap3isp_stat_data {
21031+ struct timeval ts;
21032+ void __user *buf;
21033+ __u32 buf_size;
21034+ __u16 frame_number;
21035+ __u16 cur_frame;
21036+ __u16 config_counter;
21037+ __u16 new_bufs; /* Deprecated */
21038+};
21039+
21040+
21041+/* Histogram related structs */
21042+
21043+/* Flags for number of bins */
21044+#define OMAP3ISP_HIST_BINS_32 0
21045+#define OMAP3ISP_HIST_BINS_64 1
21046+#define OMAP3ISP_HIST_BINS_128 2
21047+#define OMAP3ISP_HIST_BINS_256 3
21048+
21049+/* Number of bins * 4 colors * 4-bytes word */
21050+#define OMAP3ISP_HIST_MEM_SIZE_BINS(n) ((1 << ((n)+5))*4*4)
21051+
21052+#define OMAP3ISP_HIST_MEM_SIZE 1024
21053+#define OMAP3ISP_HIST_MIN_REGIONS 1
21054+#define OMAP3ISP_HIST_MAX_REGIONS 4
21055+#define OMAP3ISP_HIST_MAX_WB_GAIN 255
21056+#define OMAP3ISP_HIST_MIN_WB_GAIN 0
21057+#define OMAP3ISP_HIST_MAX_BIT_WIDTH 14
21058+#define OMAP3ISP_HIST_MIN_BIT_WIDTH 8
21059+#define OMAP3ISP_HIST_MAX_WG 4
21060+#define OMAP3ISP_HIST_MAX_BUF_SIZE 4096
21061+
21062+/* Source */
21063+#define OMAP3ISP_HIST_SOURCE_CCDC 0
21064+#define OMAP3ISP_HIST_SOURCE_MEM 1
21065+
21066+/* CFA pattern */
21067+#define OMAP3ISP_HIST_CFA_BAYER 0
21068+#define OMAP3ISP_HIST_CFA_FOVEONX3 1
21069+
21070+struct omap3isp_hist_region {
21071+ __u16 h_start;
21072+ __u16 h_end;
21073+ __u16 v_start;
21074+ __u16 v_end;
21075+};
21076+
21077+struct omap3isp_hist_config {
21078+ /*
21079+ * Common fields.
21080+ * They should be the first ones and must be in the same order as in
21081+ * ispstat_generic_config struct.
21082+ */
21083+ __u32 buf_size;
21084+ __u16 config_counter;
21085+
21086+ __u8 num_acc_frames; /* Num of image frames to be processed and
21087+ accumulated for each histogram frame */
21088+ __u16 hist_bins; /* number of bins: 32, 64, 128, or 256 */
21089+ __u8 cfa; /* BAYER or FOVEON X3 */
21090+ __u8 wg[OMAP3ISP_HIST_MAX_WG]; /* White Balance Gain */
21091+ __u8 num_regions; /* number of regions to be configured */
21092+ struct omap3isp_hist_region region[OMAP3ISP_HIST_MAX_REGIONS];
21093+};
21094+
21095+/* Auto Focus related structs */
21096+
21097+#define OMAP3ISP_AF_NUM_COEF 11
21098+
21099+enum omap3isp_h3a_af_fvmode {
21100+ OMAP3ISP_AF_MODE_SUMMED = 0,
21101+ OMAP3ISP_AF_MODE_PEAK = 1
21102+};
21103+
21104+/* Red, Green, and blue pixel location in the AF windows */
21105+enum omap3isp_h3a_af_rgbpos {
21106+ OMAP3ISP_AF_GR_GB_BAYER = 0, /* GR and GB as Bayer pattern */
21107+ OMAP3ISP_AF_RG_GB_BAYER = 1, /* RG and GB as Bayer pattern */
21108+ OMAP3ISP_AF_GR_BG_BAYER = 2, /* GR and BG as Bayer pattern */
21109+ OMAP3ISP_AF_RG_BG_BAYER = 3, /* RG and BG as Bayer pattern */
21110+ OMAP3ISP_AF_GG_RB_CUSTOM = 4, /* GG and RB as custom pattern */
21111+ OMAP3ISP_AF_RB_GG_CUSTOM = 5 /* RB and GG as custom pattern */
21112+};
21113+
21114+/* Contains the information regarding the Horizontal Median Filter */
21115+struct omap3isp_h3a_af_hmf {
21116+ __u8 enable; /* Status of Horizontal Median Filter */
21117+ __u8 threshold; /* Threshhold Value for Horizontal Median Filter */
21118+};
21119+
21120+/* Contains the information regarding the IIR Filters */
21121+struct omap3isp_h3a_af_iir {
21122+ __u16 h_start; /* IIR horizontal start */
21123+ __u16 coeff_set0[OMAP3ISP_AF_NUM_COEF]; /* Filter coefficient, set 0 */
21124+ __u16 coeff_set1[OMAP3ISP_AF_NUM_COEF]; /* Filter coefficient, set 1 */
21125+};
21126+
21127+/* Contains the information regarding the Paxels Structure in AF Engine */
21128+struct omap3isp_h3a_af_paxel {
21129+ __u16 h_start; /* Horizontal Start Position */
21130+ __u16 v_start; /* Vertical Start Position */
21131+ __u8 width; /* Width of the Paxel */
21132+ __u8 height; /* Height of the Paxel */
21133+ __u8 h_cnt; /* Horizontal Count */
21134+ __u8 v_cnt; /* vertical Count */
21135+ __u8 line_inc; /* Line Increment */
21136+};
21137+
21138+/* Contains the parameters required for hardware set up of AF Engine */
21139+struct omap3isp_h3a_af_config {
21140+ /*
21141+ * Common fields.
21142+ * They should be the first ones and must be in the same order as in
21143+ * ispstat_generic_config struct.
21144+ */
21145+ __u32 buf_size;
21146+ __u16 config_counter;
21147+
21148+ struct omap3isp_h3a_af_hmf hmf; /* HMF configurations */
21149+ struct omap3isp_h3a_af_iir iir; /* IIR filter configurations */
21150+ struct omap3isp_h3a_af_paxel paxel; /* Paxel parameters */
21151+ enum omap3isp_h3a_af_rgbpos rgb_pos; /* RGB Positions */
21152+ enum omap3isp_h3a_af_fvmode fvmode; /* Accumulator mode */
21153+ __u8 alaw_enable; /* AF ALAW status */
21154+};
21155+
21156+/* ISP CCDC structs */
21157+
21158+/* Abstraction layer CCDC configurations */
21159+#define OMAP3ISP_CCDC_ALAW (1 << 0)
21160+#define OMAP3ISP_CCDC_LPF (1 << 1)
21161+#define OMAP3ISP_CCDC_BLCLAMP (1 << 2)
21162+#define OMAP3ISP_CCDC_BCOMP (1 << 3)
21163+#define OMAP3ISP_CCDC_FPC (1 << 4)
21164+#define OMAP3ISP_CCDC_CULL (1 << 5)
21165+#define OMAP3ISP_CCDC_CONFIG_LSC (1 << 7)
21166+#define OMAP3ISP_CCDC_TBL_LSC (1 << 8)
21167+
21168+#define OMAP3ISP_RGB_MAX 3
21169+
21170+/* Enumeration constants for Alaw input width */
21171+enum omap3isp_alaw_ipwidth {
21172+ OMAP3ISP_ALAW_BIT12_3 = 0x3,
21173+ OMAP3ISP_ALAW_BIT11_2 = 0x4,
21174+ OMAP3ISP_ALAW_BIT10_1 = 0x5,
21175+ OMAP3ISP_ALAW_BIT9_0 = 0x6
21176+};
21177+
21178+/**
21179+ * struct omap3isp_ccdc_lsc_config - LSC configuration
21180+ * @offset: Table Offset of the gain table.
21181+ * @gain_mode_n: Vertical dimension of a paxel in LSC configuration.
21182+ * @gain_mode_m: Horizontal dimension of a paxel in LSC configuration.
21183+ * @gain_format: Gain table format.
21184+ * @fmtsph: Start pixel horizontal from start of the HS sync pulse.
21185+ * @fmtlnh: Number of pixels in horizontal direction to use for the data
21186+ * reformatter.
21187+ * @fmtslv: Start line from start of VS sync pulse for the data reformatter.
21188+ * @fmtlnv: Number of lines in vertical direction for the data reformatter.
21189+ * @initial_x: X position, in pixels, of the first active pixel in reference
21190+ * to the first active paxel. Must be an even number.
21191+ * @initial_y: Y position, in pixels, of the first active pixel in reference
21192+ * to the first active paxel. Must be an even number.
21193+ * @size: Size of LSC gain table. Filled when loaded from userspace.
21194+ */
21195+struct omap3isp_ccdc_lsc_config {
21196+ __u16 offset;
21197+ __u8 gain_mode_n;
21198+ __u8 gain_mode_m;
21199+ __u8 gain_format;
21200+ __u16 fmtsph;
21201+ __u16 fmtlnh;
21202+ __u16 fmtslv;
21203+ __u16 fmtlnv;
21204+ __u8 initial_x;
21205+ __u8 initial_y;
21206+ __u32 size;
21207+};
21208+
21209+/**
21210+ * struct omap3isp_ccdc_bclamp - Optical & Digital black clamp subtract
21211+ * @obgain: Optical black average gain.
21212+ * @obstpixel: Start Pixel w.r.t. HS pulse in Optical black sample.
21213+ * @oblines: Optical Black Sample lines.
21214+ * @oblen: Optical Black Sample Length.
21215+ * @dcsubval: Digital Black Clamp subtract value.
21216+ */
21217+struct omap3isp_ccdc_bclamp {
21218+ __u8 obgain;
21219+ __u8 obstpixel;
21220+ __u8 oblines;
21221+ __u8 oblen;
21222+ __u16 dcsubval;
21223+};
21224+
21225+/**
21226+ * struct omap3isp_ccdc_fpc - Faulty Pixels Correction
21227+ * @fpnum: Number of faulty pixels to be corrected in the frame.
21228+ * @fpcaddr: Memory address of the FPC Table
21229+ */
21230+struct omap3isp_ccdc_fpc {
21231+ __u16 fpnum;
21232+ __u32 fpcaddr;
21233+};
21234+
21235+/**
21236+ * struct omap3isp_ccdc_blcomp - Black Level Compensation parameters
21237+ * @b_mg: B/Mg pixels. 2's complement. -128 to +127.
21238+ * @gb_g: Gb/G pixels. 2's complement. -128 to +127.
21239+ * @gr_cy: Gr/Cy pixels. 2's complement. -128 to +127.
21240+ * @r_ye: R/Ye pixels. 2's complement. -128 to +127.
21241+ */
21242+struct omap3isp_ccdc_blcomp {
21243+ __u8 b_mg;
21244+ __u8 gb_g;
21245+ __u8 gr_cy;
21246+ __u8 r_ye;
21247+};
21248+
21249+/**
21250+ * omap3isp_ccdc_culling - Culling parameters
21251+ * @v_pattern: Vertical culling pattern.
21252+ * @h_odd: Horizontal Culling pattern for odd lines.
21253+ * @h_even: Horizontal Culling pattern for even lines.
21254+ */
21255+struct omap3isp_ccdc_culling {
21256+ __u8 v_pattern;
21257+ __u16 h_odd;
21258+ __u16 h_even;
21259+};
21260+
21261+/**
21262+ * omap3isp_ccdc_update_config - CCDC configuration
21263+ * @update: Specifies which CCDC registers should be updated.
21264+ * @flag: Specifies which CCDC functions should be enabled.
21265+ * @alawip: Enable/Disable A-Law compression.
21266+ * @bclamp: Black clamp control register.
21267+ * @blcomp: Black level compensation value for RGrGbB Pixels. 2's complement.
21268+ * @fpc: Number of faulty pixels corrected in the frame, address of FPC table.
21269+ * @cull: Cull control register.
21270+ * @lsc: Pointer to LSC gain table.
21271+ */
21272+struct omap3isp_ccdc_update_config {
21273+ __u16 update;
21274+ __u16 flag;
21275+ enum omap3isp_alaw_ipwidth alawip;
21276+ struct omap3isp_ccdc_bclamp __user *bclamp;
21277+ struct omap3isp_ccdc_blcomp __user *blcomp;
21278+ struct omap3isp_ccdc_fpc __user *fpc;
21279+ struct omap3isp_ccdc_lsc_config __user *lsc_cfg;
21280+ struct omap3isp_ccdc_culling __user *cull;
21281+ __u8 __user *lsc;
21282+};
21283+
21284+/* Preview configurations */
21285+#define OMAP3ISP_PREV_LUMAENH (1 << 0)
21286+#define OMAP3ISP_PREV_INVALAW (1 << 1)
21287+#define OMAP3ISP_PREV_HRZ_MED (1 << 2)
21288+#define OMAP3ISP_PREV_CFA (1 << 3)
21289+#define OMAP3ISP_PREV_CHROMA_SUPP (1 << 4)
21290+#define OMAP3ISP_PREV_WB (1 << 5)
21291+#define OMAP3ISP_PREV_BLKADJ (1 << 6)
21292+#define OMAP3ISP_PREV_RGB2RGB (1 << 7)
21293+#define OMAP3ISP_PREV_COLOR_CONV (1 << 8)
21294+#define OMAP3ISP_PREV_YC_LIMIT (1 << 9)
21295+#define OMAP3ISP_PREV_DEFECT_COR (1 << 10)
21296+#define OMAP3ISP_PREV_GAMMABYPASS (1 << 11)
21297+#define OMAP3ISP_PREV_DRK_FRM_CAPTURE (1 << 12)
21298+#define OMAP3ISP_PREV_DRK_FRM_SUBTRACT (1 << 13)
21299+#define OMAP3ISP_PREV_LENS_SHADING (1 << 14)
21300+#define OMAP3ISP_PREV_NF (1 << 15)
21301+#define OMAP3ISP_PREV_GAMMA (1 << 16)
21302+
21303+#define OMAP3ISP_PREV_NF_TBL_SIZE 64
21304+#define OMAP3ISP_PREV_CFA_TBL_SIZE 576
21305+#define OMAP3ISP_PREV_GAMMA_TBL_SIZE 1024
21306+#define OMAP3ISP_PREV_YENH_TBL_SIZE 128
21307+
21308+#define OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS 4
21309+
21310+/**
21311+ * struct omap3isp_prev_hmed - Horizontal Median Filter
21312+ * @odddist: Distance between consecutive pixels of same color in the odd line.
21313+ * @evendist: Distance between consecutive pixels of same color in the even
21314+ * line.
21315+ * @thres: Horizontal median filter threshold.
21316+ */
21317+struct omap3isp_prev_hmed {
21318+ __u8 odddist;
21319+ __u8 evendist;
21320+ __u8 thres;
21321+};
21322+
21323+/*
21324+ * Enumeration for CFA Formats supported by preview
21325+ */
21326+enum omap3isp_cfa_fmt {
21327+ OMAP3ISP_CFAFMT_BAYER,
21328+ OMAP3ISP_CFAFMT_SONYVGA,
21329+ OMAP3ISP_CFAFMT_RGBFOVEON,
21330+ OMAP3ISP_CFAFMT_DNSPL,
21331+ OMAP3ISP_CFAFMT_HONEYCOMB,
21332+ OMAP3ISP_CFAFMT_RRGGBBFOVEON
21333+};
21334+
21335+/**
21336+ * struct omap3isp_prev_cfa - CFA Interpolation
21337+ * @format: CFA Format Enum value supported by preview.
21338+ * @gradthrs_vert: CFA Gradient Threshold - Vertical.
21339+ * @gradthrs_horz: CFA Gradient Threshold - Horizontal.
21340+ * @table: Pointer to the CFA table.
21341+ */
21342+struct omap3isp_prev_cfa {
21343+ enum omap3isp_cfa_fmt format;
21344+ __u8 gradthrs_vert;
21345+ __u8 gradthrs_horz;
21346+ __u32 table[OMAP3ISP_PREV_CFA_TBL_SIZE];
21347+};
21348+
21349+/**
21350+ * struct omap3isp_prev_csup - Chrominance Suppression
21351+ * @gain: Gain.
21352+ * @thres: Threshold.
21353+ * @hypf_en: Flag to enable/disable the High Pass Filter.
21354+ */
21355+struct omap3isp_prev_csup {
21356+ __u8 gain;
21357+ __u8 thres;
21358+ __u8 hypf_en;
21359+};
21360+
21361+/**
21362+ * struct omap3isp_prev_wbal - White Balance
21363+ * @dgain: Digital gain (U10Q8).
21364+ * @coef3: White balance gain - COEF 3 (U8Q5).
21365+ * @coef2: White balance gain - COEF 2 (U8Q5).
21366+ * @coef1: White balance gain - COEF 1 (U8Q5).
21367+ * @coef0: White balance gain - COEF 0 (U8Q5).
21368+ */
21369+struct omap3isp_prev_wbal {
21370+ __u16 dgain;
21371+ __u8 coef3;
21372+ __u8 coef2;
21373+ __u8 coef1;
21374+ __u8 coef0;
21375+};
21376+
21377+/**
21378+ * struct omap3isp_prev_blkadj - Black Level Adjustment
21379+ * @red: Black level offset adjustment for Red in 2's complement format
21380+ * @green: Black level offset adjustment for Green in 2's complement format
21381+ * @blue: Black level offset adjustment for Blue in 2's complement format
21382+ */
21383+struct omap3isp_prev_blkadj {
21384+ /*Black level offset adjustment for Red in 2's complement format */
21385+ __u8 red;
21386+ /*Black level offset adjustment for Green in 2's complement format */
21387+ __u8 green;
21388+ /* Black level offset adjustment for Blue in 2's complement format */
21389+ __u8 blue;
21390+};
21391+
21392+/**
21393+ * struct omap3isp_prev_rgbtorgb - RGB to RGB Blending
21394+ * @matrix: Blending values(S12Q8 format)
21395+ * [RR] [GR] [BR]
21396+ * [RG] [GG] [BG]
21397+ * [RB] [GB] [BB]
21398+ * @offset: Blending offset value for R,G,B in 2's complement integer format.
21399+ */
21400+struct omap3isp_prev_rgbtorgb {
21401+ __u16 matrix[OMAP3ISP_RGB_MAX][OMAP3ISP_RGB_MAX];
21402+ __u16 offset[OMAP3ISP_RGB_MAX];
21403+};
21404+
21405+/**
21406+ * struct omap3isp_prev_csc - Color Space Conversion from RGB-YCbYCr
21407+ * @matrix: Color space conversion coefficients(S10Q8)
21408+ * [CSCRY] [CSCGY] [CSCBY]
21409+ * [CSCRCB] [CSCGCB] [CSCBCB]
21410+ * [CSCRCR] [CSCGCR] [CSCBCR]
21411+ * @offset: CSC offset values for Y offset, CB offset and CR offset respectively
21412+ */
21413+struct omap3isp_prev_csc {
21414+ __u16 matrix[OMAP3ISP_RGB_MAX][OMAP3ISP_RGB_MAX];
21415+ __s16 offset[OMAP3ISP_RGB_MAX];
21416+};
21417+
21418+/**
21419+ * struct omap3isp_prev_yclimit - Y, C Value Limit
21420+ * @minC: Minimum C value
21421+ * @maxC: Maximum C value
21422+ * @minY: Minimum Y value
21423+ * @maxY: Maximum Y value
21424+ */
21425+struct omap3isp_prev_yclimit {
21426+ __u8 minC;
21427+ __u8 maxC;
21428+ __u8 minY;
21429+ __u8 maxY;
21430+};
21431+
21432+/**
21433+ * struct omap3isp_prev_dcor - Defect correction
21434+ * @couplet_mode_en: Flag to enable or disable the couplet dc Correction in NF
21435+ * @detect_correct: Thresholds for correction bit 0:10 detect 16:25 correct
21436+ */
21437+struct omap3isp_prev_dcor {
21438+ __u8 couplet_mode_en;
21439+ __u32 detect_correct[OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS];
21440+};
21441+
21442+/**
21443+ * struct omap3isp_prev_nf - Noise Filter
21444+ * @spread: Spread value to be used in Noise Filter
21445+ * @table: Pointer to the Noise Filter table
21446+ */
21447+struct omap3isp_prev_nf {
21448+ __u8 spread;
21449+ __u32 table[OMAP3ISP_PREV_NF_TBL_SIZE];
21450+};
21451+
21452+/**
21453+ * struct omap3isp_prev_gtables - Gamma correction tables
21454+ * @red: Array for red gamma table.
21455+ * @green: Array for green gamma table.
21456+ * @blue: Array for blue gamma table.
21457+ */
21458+struct omap3isp_prev_gtables {
21459+ __u32 red[OMAP3ISP_PREV_GAMMA_TBL_SIZE];
21460+ __u32 green[OMAP3ISP_PREV_GAMMA_TBL_SIZE];
21461+ __u32 blue[OMAP3ISP_PREV_GAMMA_TBL_SIZE];
21462+};
21463+
21464+/**
21465+ * struct omap3isp_prev_luma - Luma enhancement
21466+ * @table: Array for luma enhancement table.
21467+ */
21468+struct omap3isp_prev_luma {
21469+ __u32 table[OMAP3ISP_PREV_YENH_TBL_SIZE];
21470+};
21471+
21472+/**
21473+ * struct omap3isp_prev_update_config - Preview engine configuration (user)
21474+ * @update: Specifies which ISP Preview registers should be updated.
21475+ * @flag: Specifies which ISP Preview functions should be enabled.
21476+ * @shading_shift: 3bit value of shift used in shading compensation.
21477+ * @luma: Pointer to luma enhancement structure.
21478+ * @hmed: Pointer to structure containing the odd and even distance.
21479+ * between the pixels in the image along with the filter threshold.
21480+ * @cfa: Pointer to structure containing the CFA interpolation table, CFA.
21481+ * format in the image, vertical and horizontal gradient threshold.
21482+ * @csup: Pointer to Structure for Chrominance Suppression coefficients.
21483+ * @wbal: Pointer to structure for White Balance.
21484+ * @blkadj: Pointer to structure for Black Adjustment.
21485+ * @rgb2rgb: Pointer to structure for RGB to RGB Blending.
21486+ * @csc: Pointer to structure for Color Space Conversion from RGB-YCbYCr.
21487+ * @yclimit: Pointer to structure for Y, C Value Limit.
21488+ * @dcor: Pointer to structure for defect correction.
21489+ * @nf: Pointer to structure for Noise Filter
21490+ * @gamma: Pointer to gamma structure.
21491+ */
21492+struct omap3isp_prev_update_config {
21493+ __u32 update;
21494+ __u32 flag;
21495+ __u32 shading_shift;
21496+ struct omap3isp_prev_luma __user *luma;
21497+ struct omap3isp_prev_hmed __user *hmed;
21498+ struct omap3isp_prev_cfa __user *cfa;
21499+ struct omap3isp_prev_csup __user *csup;
21500+ struct omap3isp_prev_wbal __user *wbal;
21501+ struct omap3isp_prev_blkadj __user *blkadj;
21502+ struct omap3isp_prev_rgbtorgb __user *rgb2rgb;
21503+ struct omap3isp_prev_csc __user *csc;
21504+ struct omap3isp_prev_yclimit __user *yclimit;
21505+ struct omap3isp_prev_dcor __user *dcor;
21506+ struct omap3isp_prev_nf __user *nf;
21507+ struct omap3isp_prev_gtables __user *gamma;
21508+};
21509+
21510+#endif /* OMAP3_ISP_USER_H */
21511--
215121.6.6.1
21513