aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/omap3isp
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 04:49:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 04:49:05 -0400
commit0b8e74c6f44094189dbe78baf4101acc7570c6af (patch)
tree6440561d09fb71ba5928664604ec92f29940be6b /drivers/media/platform/omap3isp
parent7f60ba388f5b9dd8b0da463b394412dace3ab814 (diff)
parentbd0d10498826ed150da5e4c45baf8b9c7088fb71 (diff)
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: "The first part of the media updates for Kernel 3.7. This series contain: - A major tree renaming patch series: now, drivers are organized internally by their used bus, instead of by V4L2 and/or DVB API, providing a cleaner driver location for hybrid drivers that implement both APIs, and allowing to cleanup the Kconfig items and make them more intuitive for the end user; - Media Kernel developers are typically very lazy with their duties of keeping the MAINTAINERS entries for their drivers updated. As now the tree is more organized, we're doing an effort to add/update those entries for the drivers that aren't currently orphan; - Several DVB USB drivers got moved to a new DVB USB v2 core; the new core fixes several bugs (as the existing one that got bitroted). Now, suspend/resume finally started to work fine (at least with some devices - we should expect more work with regards to it); - added multistream support for DVB-T2, and unified the API for DVB-S2 and ISDB-S. Backward binary support is preserved; - as usual, a few new drivers, some V4L2 core improvements and lots of drivers improvements and fixes. There are some points to notice on this series: 1) you should expect a trivial merge conflict on your tree, with the removal of Documentation/feature-removal-schedule.txt: this series would be adding two additional entries there. I opted to not rebase it due to this recent change; 2) With regards to the PCTV 520e udev-related breakage, I opted to fix it in a way that the patches can be backported to 3.5 even without your firmware fix patch. This way, Greg doesn't need to rush backporting your patch (as there are still the firmware cache and firmware path customization issues to be addressed there). I'll send later a patch (likely after the end of the merge window) reverting the rest of the DRX-K async firmware request, fully restoring its original behaviour to allow media drivers to initialize everything serialized as before for 3.7 and upper. 3) I'm planning to work on this weekend to test the DMABUF patches for V4L2. The patches are on my queue for several Kernel cycles, but, up to now, there is/was no way to test the series locally. I have some concerns about this particular changeset with regards to security issues, and with regards to the replacement of the old VIDIOC_OVERLAY ioctl's that is broken on modern systems, due to GPU drivers change. The Overlay API allows direct PCI2PCI transfers from a media capture card into the GPU framebuffer, but its API is crappy. Also, the only existing X11 driver that implements it requires a XV extension that is not available anymore on modern drivers. The DMABUF can do the same thing, but with it is promising to be a properly-designed API. If I can successfully test this series and be happy with it, I should be asking you to pull them next week." * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (717 commits) em28xx: regression fix: use DRX-K sync firmware requests on em28xx drxk: allow loading firmware synchrousnously em28xx: Make all em28xx extensions to be initialized asynchronously [media] tda18271: properly report read errors in tda18271_get_id [media] tda18271: delay IR & RF calibration until init() if delay_cal is set [media] MAINTAINERS: add Michael Krufky as tda827x maintainer [media] MAINTAINERS: add Michael Krufky as tda8290 maintainer [media] MAINTAINERS: add Michael Krufky as cxusb maintainer [media] MAINTAINERS: add Michael Krufky as lg2160 maintainer [media] MAINTAINERS: add Michael Krufky as lgdt3305 maintainer [media] MAINTAINERS: add Michael Krufky as mxl111sf maintainer [media] MAINTAINERS: add Michael Krufky as mxl5007t maintainer [media] MAINTAINERS: add Michael Krufky as tda18271 maintainer [media] s5p-tv: Report only multi-plane capabilities in vidioc_querycap [media] s5p-mfc: Fix misplaced return statement in s5p_mfc_suspend() [media] exynos-gsc: Add missing static storage class specifiers [media] exynos-gsc: Remove <linux/version.h> header file inclusion [media] s5p-fimc: Fix incorrect condition in fimc_lite_reqbufs() [media] s5p-tv: Fix potential NULL pointer dereference error [media] s5k6aa: Fix possible NULL pointer dereference ...
Diffstat (limited to 'drivers/media/platform/omap3isp')
-rw-r--r--drivers/media/platform/omap3isp/Makefile11
-rw-r--r--drivers/media/platform/omap3isp/cfa_coef_table.h61
-rw-r--r--drivers/media/platform/omap3isp/gamma_table.h90
-rw-r--r--drivers/media/platform/omap3isp/isp.c2245
-rw-r--r--drivers/media/platform/omap3isp/isp.h352
-rw-r--r--drivers/media/platform/omap3isp/ispccdc.c2583
-rw-r--r--drivers/media/platform/omap3isp/ispccdc.h172
-rw-r--r--drivers/media/platform/omap3isp/ispccp2.c1171
-rw-r--r--drivers/media/platform/omap3isp/ispccp2.h98
-rw-r--r--drivers/media/platform/omap3isp/ispcsi2.c1328
-rw-r--r--drivers/media/platform/omap3isp/ispcsi2.h165
-rw-r--r--drivers/media/platform/omap3isp/ispcsiphy.c249
-rw-r--r--drivers/media/platform/omap3isp/ispcsiphy.h63
-rw-r--r--drivers/media/platform/omap3isp/isph3a.h117
-rw-r--r--drivers/media/platform/omap3isp/isph3a_aewb.c368
-rw-r--r--drivers/media/platform/omap3isp/isph3a_af.c423
-rw-r--r--drivers/media/platform/omap3isp/isphist.c518
-rw-r--r--drivers/media/platform/omap3isp/isphist.h40
-rw-r--r--drivers/media/platform/omap3isp/isppreview.c2348
-rw-r--r--drivers/media/platform/omap3isp/isppreview.h174
-rw-r--r--drivers/media/platform/omap3isp/ispqueue.c1158
-rw-r--r--drivers/media/platform/omap3isp/ispqueue.h187
-rw-r--r--drivers/media/platform/omap3isp/ispreg.h1586
-rw-r--r--drivers/media/platform/omap3isp/ispresizer.c1778
-rw-r--r--drivers/media/platform/omap3isp/ispresizer.h146
-rw-r--r--drivers/media/platform/omap3isp/ispstat.c1102
-rw-r--r--drivers/media/platform/omap3isp/ispstat.h169
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.c1404
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.h216
-rw-r--r--drivers/media/platform/omap3isp/luma_enhance_table.h42
-rw-r--r--drivers/media/platform/omap3isp/noise_filter_table.h30
31 files changed, 20394 insertions, 0 deletions
diff --git a/drivers/media/platform/omap3isp/Makefile b/drivers/media/platform/omap3isp/Makefile
new file mode 100644
index 000000000000..e8847e79e31a
--- /dev/null
+++ b/drivers/media/platform/omap3isp/Makefile
@@ -0,0 +1,11 @@
1# Makefile for OMAP3 ISP driver
2
3ccflags-$(CONFIG_VIDEO_OMAP3_DEBUG) += -DDEBUG
4
5omap3-isp-objs += \
6 isp.o ispqueue.o ispvideo.o \
7 ispcsiphy.o ispccp2.o ispcsi2.o \
8 ispccdc.o isppreview.o ispresizer.o \
9 ispstat.o isph3a_aewb.o isph3a_af.o isphist.o
10
11obj-$(CONFIG_VIDEO_OMAP3) += omap3-isp.o
diff --git a/drivers/media/platform/omap3isp/cfa_coef_table.h b/drivers/media/platform/omap3isp/cfa_coef_table.h
new file mode 100644
index 000000000000..c84df0706f3e
--- /dev/null
+++ b/drivers/media/platform/omap3isp/cfa_coef_table.h
@@ -0,0 +1,61 @@
1/*
2 * cfa_coef_table.h
3 *
4 * TI OMAP3 ISP - CFA coefficients table
5 *
6 * Copyright (C) 2009-2010 Nokia Corporation
7 *
8 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9 * Sakari Ailus <sakari.ailus@iki.fi>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2 as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA
24 */
25
26{ 244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244,
27248, 0, 0, 0, 0, 40, 0, 0, 244, 12, 250, 4, 0, 27, 0, 250,
28247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248,
29244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244,
30248, 0, 0, 0, 0, 40, 0, 0, 244, 12, 250, 4, 0, 27, 0, 250,
31247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248,
32244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244,
33248, 0, 0, 0, 0, 40, 0, 0, 244, 12, 250, 4, 0, 27, 0, 250,
34247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248 },
35{ 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4,
36 0, 0, 0, 248, 0, 0, 40, 0, 4, 250, 12, 244, 250, 0, 27, 0,
37 12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0,
38 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4,
39 0, 0, 0, 248, 0, 0, 40, 0, 4, 250, 12, 244, 250, 0, 27, 0,
40 12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0,
41 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4,
42 0, 0, 0, 248, 0, 0, 40, 0, 4, 250, 12, 244, 250, 0, 27, 0,
43 12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0 },
44{ 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0,
45 0, 0, 0, 248, 0, 0, 40, 0, 0, 247, 0, 244, 247, 36, 27, 12,
46 0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0,
47 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0,
48 0, 0, 0, 248, 0, 0, 40, 0, 0, 247, 0, 244, 247, 36, 27, 12,
49 0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0,
50 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0,
51 0, 0, 0, 248, 0, 0, 40, 0, 0, 247, 0, 244, 247, 36, 27, 12,
52 0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0 },
53{ 244,12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244,
54248, 0, 0, 0, 0, 40, 0, 0, 244, 0, 247, 0, 12, 27, 36, 247,
55250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248,
56244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244,
57248, 0, 0, 0, 0, 40, 0, 0, 244, 0, 247, 0, 12, 27, 36, 247,
58250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248,
59244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244,
60248, 0, 0, 0, 0, 40, 0, 0, 244, 0, 247, 0, 12, 27, 36, 247,
61250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248 },
diff --git a/drivers/media/platform/omap3isp/gamma_table.h b/drivers/media/platform/omap3isp/gamma_table.h
new file mode 100644
index 000000000000..78deebf7d965
--- /dev/null
+++ b/drivers/media/platform/omap3isp/gamma_table.h
@@ -0,0 +1,90 @@
1/*
2 * gamma_table.h
3 *
4 * TI OMAP3 ISP - Default gamma table for all components
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27 0, 0, 1, 2, 3, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20,
28 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 36, 37, 39, 40, 41, 42,
29 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 54, 55, 56, 57,
30 58, 59, 60, 61, 62, 63, 63, 64, 65, 66, 66, 67, 68, 69, 69, 70,
31 71, 72, 72, 73, 74, 75, 75, 76, 77, 78, 78, 79, 80, 81, 81, 82,
32 83, 84, 84, 85, 86, 87, 88, 88, 89, 90, 91, 91, 92, 93, 94, 94,
33 95, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 103, 104, 104,
34105, 106, 107, 108, 108, 109, 110, 111, 111, 112, 113, 114, 114, 115, 116, 117,
35117, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125,
36126, 126, 127, 127, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 133,
37134, 134, 135, 135, 136, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141,
38142, 142, 143, 143, 144, 144, 145, 145, 146, 146, 147, 147, 148, 148, 149, 149,
39150, 150, 151, 151, 152, 152, 153, 153, 153, 153, 154, 154, 154, 154, 155, 155,
40156, 156, 157, 157, 158, 158, 158, 159, 159, 159, 160, 160, 160, 161, 161, 162,
41162, 163, 163, 164, 164, 164, 164, 165, 165, 165, 165, 166, 166, 167, 167, 168,
42168, 169, 169, 170, 170, 170, 170, 171, 171, 171, 171, 172, 172, 173, 173, 174,
43174, 175, 175, 176, 176, 176, 176, 177, 177, 177, 177, 178, 178, 178, 178, 179,
44179, 179, 179, 180, 180, 180, 180, 181, 181, 181, 181, 182, 182, 182, 182, 183,
45183, 183, 183, 184, 184, 184, 184, 185, 185, 185, 185, 186, 186, 186, 186, 187,
46187, 187, 187, 188, 188, 188, 188, 189, 189, 189, 189, 190, 190, 190, 190, 191,
47191, 191, 191, 192, 192, 192, 192, 193, 193, 193, 193, 194, 194, 194, 194, 195,
48195, 195, 195, 196, 196, 196, 196, 197, 197, 197, 197, 198, 198, 198, 198, 199,
49199, 199, 199, 200, 200, 200, 200, 201, 201, 201, 201, 202, 202, 202, 203, 203,
50203, 203, 204, 204, 204, 204, 205, 205, 205, 205, 206, 206, 206, 206, 207, 207,
51207, 207, 208, 208, 208, 208, 209, 209, 209, 209, 210, 210, 210, 210, 210, 210,
52210, 210, 210, 210, 210, 210, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
53211, 212, 212, 212, 212, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
54213, 214, 214, 214, 214, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
55216, 216, 216, 216, 217, 217, 217, 217, 218, 218, 218, 218, 219, 219, 219, 219,
56219, 219, 219, 219, 219, 219, 219, 219, 220, 220, 220, 220, 221, 221, 221, 221,
57221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 223, 223, 223, 223, 223,
58223, 223, 223, 223, 223, 223, 223, 224, 224, 224, 224, 225, 225, 225, 225, 225,
59225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 226, 226,
60226, 226, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 228, 228,
61228, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 230, 230, 230,
62230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 232, 232, 232,
63232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
64233, 233, 233, 233, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 235,
65235, 235, 235, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236,
66236, 236, 236, 236, 236, 236, 237, 237, 237, 237, 238, 238, 238, 238, 238, 238,
67238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
68238, 238, 238, 238, 238, 239, 239, 239, 239, 240, 240, 240, 240, 240, 240, 240,
69240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
70240, 240, 240, 240, 241, 241, 241, 241, 242, 242, 242, 242, 242, 242, 242, 242,
71242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242,
72242, 242, 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
73244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
74244, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246,
75246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246,
76246, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 248, 248, 248, 248, 248,
77248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
78248, 248, 248, 248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 250, 250,
79250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
80250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
81250, 250, 250, 250, 251, 251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 252,
82252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
83252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
84252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
85252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253, 253,
86253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
87253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
88253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
89253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
90255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
new file mode 100644
index 000000000000..99640d8c1db0
--- /dev/null
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -0,0 +1,2245 @@
1/*
2 * isp.c
3 *
4 * TI OMAP3 ISP - Core
5 *
6 * Copyright (C) 2006-2010 Nokia Corporation
7 * Copyright (C) 2007-2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * Contributors:
13 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
14 * Sakari Ailus <sakari.ailus@iki.fi>
15 * David Cohen <dacohen@gmail.com>
16 * Stanimir Varbanov <svarbanov@mm-sol.com>
17 * Vimarsh Zutshi <vimarsh.zutshi@gmail.com>
18 * Tuukka Toivonen <tuukkat76@gmail.com>
19 * Sergio Aguirre <saaguirre@ti.com>
20 * Antti Koskipaa <akoskipa@gmail.com>
21 * Ivan T. Ivanov <iivanov@mm-sol.com>
22 * RaniSuneela <r-m@ti.com>
23 * Atanas Filipov <afilipov@mm-sol.com>
24 * Gjorgji Rosikopulos <grosikopulos@mm-sol.com>
25 * Hiroshi DOYU <hiroshi.doyu@nokia.com>
26 * Nayden Kanchev <nkanchev@mm-sol.com>
27 * Phil Carmody <ext-phil.2.carmody@nokia.com>
28 * Artem Bityutskiy <artem.bityutskiy@nokia.com>
29 * Dominic Curran <dcurran@ti.com>
30 * Ilkka Myllyperkio <ilkka.myllyperkio@sofica.fi>
31 * Pallavi Kulkarni <p-kulkarni@ti.com>
32 * Vaibhav Hiremath <hvaibhav@ti.com>
33 * Mohit Jalori <mjalori@ti.com>
34 * Sameer Venkatraman <sameerv@ti.com>
35 * Senthilvadivu Guruswamy <svadivu@ti.com>
36 * Thara Gopinath <thara@ti.com>
37 * Toni Leinonen <toni.leinonen@nokia.com>
38 * Troy Laramy <t-laramy@ti.com>
39 *
40 * This program is free software; you can redistribute it and/or modify
41 * it under the terms of the GNU General Public License version 2 as
42 * published by the Free Software Foundation.
43 *
44 * This program is distributed in the hope that it will be useful, but
45 * WITHOUT ANY WARRANTY; without even the implied warranty of
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
47 * General Public License for more details.
48 *
49 * You should have received a copy of the GNU General Public License
50 * along with this program; if not, write to the Free Software
51 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
52 * 02110-1301 USA
53 */
54
55#include <asm/cacheflush.h>
56
57#include <linux/clk.h>
58#include <linux/delay.h>
59#include <linux/device.h>
60#include <linux/dma-mapping.h>
61#include <linux/i2c.h>
62#include <linux/interrupt.h>
63#include <linux/module.h>
64#include <linux/platform_device.h>
65#include <linux/regulator/consumer.h>
66#include <linux/slab.h>
67#include <linux/sched.h>
68#include <linux/vmalloc.h>
69
70#include <media/v4l2-common.h>
71#include <media/v4l2-device.h>
72
73#include <plat/cpu.h>
74
75#include "isp.h"
76#include "ispreg.h"
77#include "ispccdc.h"
78#include "isppreview.h"
79#include "ispresizer.h"
80#include "ispcsi2.h"
81#include "ispccp2.h"
82#include "isph3a.h"
83#include "isphist.h"
84
85static unsigned int autoidle;
86module_param(autoidle, int, 0444);
87MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support");
88
89static void isp_save_ctx(struct isp_device *isp);
90
91static void isp_restore_ctx(struct isp_device *isp);
92
93static const struct isp_res_mapping isp_res_maps[] = {
94 {
95 .isp_rev = ISP_REVISION_2_0,
96 .map = 1 << OMAP3_ISP_IOMEM_MAIN |
97 1 << OMAP3_ISP_IOMEM_CCP2 |
98 1 << OMAP3_ISP_IOMEM_CCDC |
99 1 << OMAP3_ISP_IOMEM_HIST |
100 1 << OMAP3_ISP_IOMEM_H3A |
101 1 << OMAP3_ISP_IOMEM_PREV |
102 1 << OMAP3_ISP_IOMEM_RESZ |
103 1 << OMAP3_ISP_IOMEM_SBL |
104 1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
105 1 << OMAP3_ISP_IOMEM_CSIPHY2,
106 },
107 {
108 .isp_rev = ISP_REVISION_15_0,
109 .map = 1 << OMAP3_ISP_IOMEM_MAIN |
110 1 << OMAP3_ISP_IOMEM_CCP2 |
111 1 << OMAP3_ISP_IOMEM_CCDC |
112 1 << OMAP3_ISP_IOMEM_HIST |
113 1 << OMAP3_ISP_IOMEM_H3A |
114 1 << OMAP3_ISP_IOMEM_PREV |
115 1 << OMAP3_ISP_IOMEM_RESZ |
116 1 << OMAP3_ISP_IOMEM_SBL |
117 1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
118 1 << OMAP3_ISP_IOMEM_CSIPHY2 |
119 1 << OMAP3_ISP_IOMEM_CSI2A_REGS2 |
120 1 << OMAP3_ISP_IOMEM_CSI2C_REGS1 |
121 1 << OMAP3_ISP_IOMEM_CSIPHY1 |
122 1 << OMAP3_ISP_IOMEM_CSI2C_REGS2,
123 },
124};
125
126/* Structure for saving/restoring ISP module registers */
127static struct isp_reg isp_reg_list[] = {
128 {OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG, 0},
129 {OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, 0},
130 {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL, 0},
131 {0, ISP_TOK_TERM, 0}
132};
133
134/*
135 * omap3isp_flush - Post pending L3 bus writes by doing a register readback
136 * @isp: OMAP3 ISP device
137 *
138 * In order to force posting of pending writes, we need to write and
139 * readback the same register, in this case the revision register.
140 *
141 * See this link for reference:
142 * http://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html
143 */
144void omap3isp_flush(struct isp_device *isp)
145{
146 isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
147 isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
148}
149
150/*
151 * isp_enable_interrupts - Enable ISP interrupts.
152 * @isp: OMAP3 ISP device
153 */
154static void isp_enable_interrupts(struct isp_device *isp)
155{
156 static const u32 irq = IRQ0ENABLE_CSIA_IRQ
157 | IRQ0ENABLE_CSIB_IRQ
158 | IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ
159 | IRQ0ENABLE_CCDC_LSC_DONE_IRQ
160 | IRQ0ENABLE_CCDC_VD0_IRQ
161 | IRQ0ENABLE_CCDC_VD1_IRQ
162 | IRQ0ENABLE_HS_VS_IRQ
163 | IRQ0ENABLE_HIST_DONE_IRQ
164 | IRQ0ENABLE_H3A_AWB_DONE_IRQ
165 | IRQ0ENABLE_H3A_AF_DONE_IRQ
166 | IRQ0ENABLE_PRV_DONE_IRQ
167 | IRQ0ENABLE_RSZ_DONE_IRQ;
168
169 isp_reg_writel(isp, irq, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
170 isp_reg_writel(isp, irq, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE);
171}
172
173/*
174 * isp_disable_interrupts - Disable ISP interrupts.
175 * @isp: OMAP3 ISP device
176 */
177static void isp_disable_interrupts(struct isp_device *isp)
178{
179 isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE);
180}
181
182/**
183 * isp_set_xclk - Configures the specified cam_xclk to the desired frequency.
184 * @isp: OMAP3 ISP device
185 * @xclk: Desired frequency of the clock in Hz. 0 = stable low, 1 is stable high
186 * @xclksel: XCLK to configure (0 = A, 1 = B).
187 *
188 * Configures the specified MCLK divisor in the ISP timing control register
189 * (TCTRL_CTRL) to generate the desired xclk clock value.
190 *
191 * Divisor = cam_mclk_hz / xclk
192 *
193 * Returns the final frequency that is actually being generated
194 **/
195static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
196{
197 u32 divisor;
198 u32 currentxclk;
199 unsigned long mclk_hz;
200
201 if (!omap3isp_get(isp))
202 return 0;
203
204 mclk_hz = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
205
206 if (xclk >= mclk_hz) {
207 divisor = ISPTCTRL_CTRL_DIV_BYPASS;
208 currentxclk = mclk_hz;
209 } else if (xclk >= 2) {
210 divisor = mclk_hz / xclk;
211 if (divisor >= ISPTCTRL_CTRL_DIV_BYPASS)
212 divisor = ISPTCTRL_CTRL_DIV_BYPASS - 1;
213 currentxclk = mclk_hz / divisor;
214 } else {
215 divisor = xclk;
216 currentxclk = 0;
217 }
218
219 switch (xclksel) {
220 case ISP_XCLK_A:
221 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
222 ISPTCTRL_CTRL_DIVA_MASK,
223 divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
224 dev_dbg(isp->dev, "isp_set_xclk(): cam_xclka set to %d Hz\n",
225 currentxclk);
226 break;
227 case ISP_XCLK_B:
228 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
229 ISPTCTRL_CTRL_DIVB_MASK,
230 divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
231 dev_dbg(isp->dev, "isp_set_xclk(): cam_xclkb set to %d Hz\n",
232 currentxclk);
233 break;
234 case ISP_XCLK_NONE:
235 default:
236 omap3isp_put(isp);
237 dev_dbg(isp->dev, "ISP_ERR: isp_set_xclk(): Invalid requested "
238 "xclk. Must be 0 (A) or 1 (B).\n");
239 return -EINVAL;
240 }
241
242 /* Do we go from stable whatever to clock? */
243 if (divisor >= 2 && isp->xclk_divisor[xclksel - 1] < 2)
244 omap3isp_get(isp);
245 /* Stopping the clock. */
246 else if (divisor < 2 && isp->xclk_divisor[xclksel - 1] >= 2)
247 omap3isp_put(isp);
248
249 isp->xclk_divisor[xclksel - 1] = divisor;
250
251 omap3isp_put(isp);
252
253 return currentxclk;
254}
255
256/*
257 * isp_core_init - ISP core settings
258 * @isp: OMAP3 ISP device
259 * @idle: Consider idle state.
260 *
261 * Set the power settings for the ISP and SBL bus and cConfigure the HS/VS
262 * interrupt source.
263 *
264 * We need to configure the HS/VS interrupt source before interrupts get
265 * enabled, as the sensor might be free-running and the ISP default setting
266 * (HS edge) would put an unnecessary burden on the CPU.
267 */
268static void isp_core_init(struct isp_device *isp, int idle)
269{
270 isp_reg_writel(isp,
271 ((idle ? ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY :
272 ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY) <<
273 ISP_SYSCONFIG_MIDLEMODE_SHIFT) |
274 ((isp->revision == ISP_REVISION_15_0) ?
275 ISP_SYSCONFIG_AUTOIDLE : 0),
276 OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
277
278 isp_reg_writel(isp,
279 (isp->autoidle ? ISPCTRL_SBL_AUTOIDLE : 0) |
280 ISPCTRL_SYNC_DETECT_VSRISE,
281 OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
282}
283
284/*
285 * Configure the bridge and lane shifter. Valid inputs are
286 *
287 * CCDC_INPUT_PARALLEL: Parallel interface
288 * CCDC_INPUT_CSI2A: CSI2a receiver
289 * CCDC_INPUT_CCP2B: CCP2b receiver
290 * CCDC_INPUT_CSI2C: CSI2c receiver
291 *
292 * The bridge and lane shifter are configured according to the selected input
293 * and the ISP platform data.
294 */
295void omap3isp_configure_bridge(struct isp_device *isp,
296 enum ccdc_input_entity input,
297 const struct isp_parallel_platform_data *pdata,
298 unsigned int shift, unsigned int bridge)
299{
300 u32 ispctrl_val;
301
302 ispctrl_val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
303 ispctrl_val &= ~ISPCTRL_SHIFT_MASK;
304 ispctrl_val &= ~ISPCTRL_PAR_CLK_POL_INV;
305 ispctrl_val &= ~ISPCTRL_PAR_SER_CLK_SEL_MASK;
306 ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_MASK;
307 ispctrl_val |= bridge;
308
309 switch (input) {
310 case CCDC_INPUT_PARALLEL:
311 ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
312 ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
313 shift += pdata->data_lane_shift * 2;
314 break;
315
316 case CCDC_INPUT_CSI2A:
317 ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIA;
318 break;
319
320 case CCDC_INPUT_CCP2B:
321 ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIB;
322 break;
323
324 case CCDC_INPUT_CSI2C:
325 ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIC;
326 break;
327
328 default:
329 return;
330 }
331
332 ispctrl_val |= ((shift/2) << ISPCTRL_SHIFT_SHIFT) & ISPCTRL_SHIFT_MASK;
333
334 isp_reg_writel(isp, ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
335}
336
337void omap3isp_hist_dma_done(struct isp_device *isp)
338{
339 if (omap3isp_ccdc_busy(&isp->isp_ccdc) ||
340 omap3isp_stat_pcr_busy(&isp->isp_hist)) {
341 /* Histogram cannot be enabled in this frame anymore */
342 atomic_set(&isp->isp_hist.buf_err, 1);
343 dev_dbg(isp->dev, "hist: Out of synchronization with "
344 "CCDC. Ignoring next buffer.\n");
345 }
346}
347
348static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus)
349{
350 static const char *name[] = {
351 "CSIA_IRQ",
352 "res1",
353 "res2",
354 "CSIB_LCM_IRQ",
355 "CSIB_IRQ",
356 "res5",
357 "res6",
358 "res7",
359 "CCDC_VD0_IRQ",
360 "CCDC_VD1_IRQ",
361 "CCDC_VD2_IRQ",
362 "CCDC_ERR_IRQ",
363 "H3A_AF_DONE_IRQ",
364 "H3A_AWB_DONE_IRQ",
365 "res14",
366 "res15",
367 "HIST_DONE_IRQ",
368 "CCDC_LSC_DONE",
369 "CCDC_LSC_PREFETCH_COMPLETED",
370 "CCDC_LSC_PREFETCH_ERROR",
371 "PRV_DONE_IRQ",
372 "CBUFF_IRQ",
373 "res22",
374 "res23",
375 "RSZ_DONE_IRQ",
376 "OVF_IRQ",
377 "res26",
378 "res27",
379 "MMU_ERR_IRQ",
380 "OCP_ERR_IRQ",
381 "SEC_ERR_IRQ",
382 "HS_VS_IRQ",
383 };
384 int i;
385
386 dev_dbg(isp->dev, "ISP IRQ: ");
387
388 for (i = 0; i < ARRAY_SIZE(name); i++) {
389 if ((1 << i) & irqstatus)
390 printk(KERN_CONT "%s ", name[i]);
391 }
392 printk(KERN_CONT "\n");
393}
394
395static void isp_isr_sbl(struct isp_device *isp)
396{
397 struct device *dev = isp->dev;
398 struct isp_pipeline *pipe;
399 u32 sbl_pcr;
400
401 /*
402 * Handle shared buffer logic overflows for video buffers.
403 * ISPSBL_PCR_CCDCPRV_2_RSZ_OVF can be safely ignored.
404 */
405 sbl_pcr = isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_PCR);
406 isp_reg_writel(isp, sbl_pcr, OMAP3_ISP_IOMEM_SBL, ISPSBL_PCR);
407 sbl_pcr &= ~ISPSBL_PCR_CCDCPRV_2_RSZ_OVF;
408
409 if (sbl_pcr)
410 dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr);
411
412 if (sbl_pcr & ISPSBL_PCR_CSIB_WBL_OVF) {
413 pipe = to_isp_pipeline(&isp->isp_ccp2.subdev.entity);
414 if (pipe != NULL)
415 pipe->error = true;
416 }
417
418 if (sbl_pcr & ISPSBL_PCR_CSIA_WBL_OVF) {
419 pipe = to_isp_pipeline(&isp->isp_csi2a.subdev.entity);
420 if (pipe != NULL)
421 pipe->error = true;
422 }
423
424 if (sbl_pcr & ISPSBL_PCR_CCDC_WBL_OVF) {
425 pipe = to_isp_pipeline(&isp->isp_ccdc.subdev.entity);
426 if (pipe != NULL)
427 pipe->error = true;
428 }
429
430 if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) {
431 pipe = to_isp_pipeline(&isp->isp_prev.subdev.entity);
432 if (pipe != NULL)
433 pipe->error = true;
434 }
435
436 if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF
437 | ISPSBL_PCR_RSZ2_WBL_OVF
438 | ISPSBL_PCR_RSZ3_WBL_OVF
439 | ISPSBL_PCR_RSZ4_WBL_OVF)) {
440 pipe = to_isp_pipeline(&isp->isp_res.subdev.entity);
441 if (pipe != NULL)
442 pipe->error = true;
443 }
444
445 if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF)
446 omap3isp_stat_sbl_overflow(&isp->isp_af);
447
448 if (sbl_pcr & ISPSBL_PCR_H3A_AEAWB_WBL_OVF)
449 omap3isp_stat_sbl_overflow(&isp->isp_aewb);
450}
451
452/*
453 * isp_isr - Interrupt Service Routine for Camera ISP module.
454 * @irq: Not used currently.
455 * @_isp: Pointer to the OMAP3 ISP device
456 *
457 * Handles the corresponding callback if plugged in.
458 *
459 * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
460 * IRQ wasn't handled.
461 */
462static irqreturn_t isp_isr(int irq, void *_isp)
463{
464 static const u32 ccdc_events = IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ |
465 IRQ0STATUS_CCDC_LSC_DONE_IRQ |
466 IRQ0STATUS_CCDC_VD0_IRQ |
467 IRQ0STATUS_CCDC_VD1_IRQ |
468 IRQ0STATUS_HS_VS_IRQ;
469 struct isp_device *isp = _isp;
470 u32 irqstatus;
471
472 irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
473 isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
474
475 isp_isr_sbl(isp);
476
477 if (irqstatus & IRQ0STATUS_CSIA_IRQ)
478 omap3isp_csi2_isr(&isp->isp_csi2a);
479
480 if (irqstatus & IRQ0STATUS_CSIB_IRQ)
481 omap3isp_ccp2_isr(&isp->isp_ccp2);
482
483 if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) {
484 if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
485 omap3isp_preview_isr_frame_sync(&isp->isp_prev);
486 if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)
487 omap3isp_resizer_isr_frame_sync(&isp->isp_res);
488 omap3isp_stat_isr_frame_sync(&isp->isp_aewb);
489 omap3isp_stat_isr_frame_sync(&isp->isp_af);
490 omap3isp_stat_isr_frame_sync(&isp->isp_hist);
491 }
492
493 if (irqstatus & ccdc_events)
494 omap3isp_ccdc_isr(&isp->isp_ccdc, irqstatus & ccdc_events);
495
496 if (irqstatus & IRQ0STATUS_PRV_DONE_IRQ) {
497 if (isp->isp_prev.output & PREVIEW_OUTPUT_RESIZER)
498 omap3isp_resizer_isr_frame_sync(&isp->isp_res);
499 omap3isp_preview_isr(&isp->isp_prev);
500 }
501
502 if (irqstatus & IRQ0STATUS_RSZ_DONE_IRQ)
503 omap3isp_resizer_isr(&isp->isp_res);
504
505 if (irqstatus & IRQ0STATUS_H3A_AWB_DONE_IRQ)
506 omap3isp_stat_isr(&isp->isp_aewb);
507
508 if (irqstatus & IRQ0STATUS_H3A_AF_DONE_IRQ)
509 omap3isp_stat_isr(&isp->isp_af);
510
511 if (irqstatus & IRQ0STATUS_HIST_DONE_IRQ)
512 omap3isp_stat_isr(&isp->isp_hist);
513
514 omap3isp_flush(isp);
515
516#if defined(DEBUG) && defined(ISP_ISR_DEBUG)
517 isp_isr_dbg(isp, irqstatus);
518#endif
519
520 return IRQ_HANDLED;
521}
522
523/* -----------------------------------------------------------------------------
524 * Pipeline power management
525 *
526 * Entities must be powered up when part of a pipeline that contains at least
527 * one open video device node.
528 *
529 * To achieve this use the entity use_count field to track the number of users.
530 * For entities corresponding to video device nodes the use_count field stores
531 * the users count of the node. For entities corresponding to subdevs the
532 * use_count field stores the total number of users of all video device nodes
533 * in the pipeline.
534 *
535 * The omap3isp_pipeline_pm_use() function must be called in the open() and
536 * close() handlers of video device nodes. It increments or decrements the use
537 * count of all subdev entities in the pipeline.
538 *
539 * To react to link management on powered pipelines, the link setup notification
540 * callback updates the use count of all entities in the source and sink sides
541 * of the link.
542 */
543
544/*
545 * isp_pipeline_pm_use_count - Count the number of users of a pipeline
546 * @entity: The entity
547 *
548 * Return the total number of users of all video device nodes in the pipeline.
549 */
550static int isp_pipeline_pm_use_count(struct media_entity *entity)
551{
552 struct media_entity_graph graph;
553 int use = 0;
554
555 media_entity_graph_walk_start(&graph, entity);
556
557 while ((entity = media_entity_graph_walk_next(&graph))) {
558 if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
559 use += entity->use_count;
560 }
561
562 return use;
563}
564
565/*
566 * isp_pipeline_pm_power_one - Apply power change to an entity
567 * @entity: The entity
568 * @change: Use count change
569 *
570 * Change the entity use count by @change. If the entity is a subdev update its
571 * power state by calling the core::s_power operation when the use count goes
572 * from 0 to != 0 or from != 0 to 0.
573 *
574 * Return 0 on success or a negative error code on failure.
575 */
576static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
577{
578 struct v4l2_subdev *subdev;
579 int ret;
580
581 subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
582 ? media_entity_to_v4l2_subdev(entity) : NULL;
583
584 if (entity->use_count == 0 && change > 0 && subdev != NULL) {
585 ret = v4l2_subdev_call(subdev, core, s_power, 1);
586 if (ret < 0 && ret != -ENOIOCTLCMD)
587 return ret;
588 }
589
590 entity->use_count += change;
591 WARN_ON(entity->use_count < 0);
592
593 if (entity->use_count == 0 && change < 0 && subdev != NULL)
594 v4l2_subdev_call(subdev, core, s_power, 0);
595
596 return 0;
597}
598
599/*
600 * isp_pipeline_pm_power - Apply power change to all entities in a pipeline
601 * @entity: The entity
602 * @change: Use count change
603 *
604 * Walk the pipeline to update the use count and the power state of all non-node
605 * entities.
606 *
607 * Return 0 on success or a negative error code on failure.
608 */
609static int isp_pipeline_pm_power(struct media_entity *entity, int change)
610{
611 struct media_entity_graph graph;
612 struct media_entity *first = entity;
613 int ret = 0;
614
615 if (!change)
616 return 0;
617
618 media_entity_graph_walk_start(&graph, entity);
619
620 while (!ret && (entity = media_entity_graph_walk_next(&graph)))
621 if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
622 ret = isp_pipeline_pm_power_one(entity, change);
623
624 if (!ret)
625 return 0;
626
627 media_entity_graph_walk_start(&graph, first);
628
629 while ((first = media_entity_graph_walk_next(&graph))
630 && first != entity)
631 if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
632 isp_pipeline_pm_power_one(first, -change);
633
634 return ret;
635}
636
637/*
638 * omap3isp_pipeline_pm_use - Update the use count of an entity
639 * @entity: The entity
640 * @use: Use (1) or stop using (0) the entity
641 *
642 * Update the use count of all entities in the pipeline and power entities on or
643 * off accordingly.
644 *
645 * Return 0 on success or a negative error code on failure. Powering entities
646 * off is assumed to never fail. No failure can occur when the use parameter is
647 * set to 0.
648 */
649int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
650{
651 int change = use ? 1 : -1;
652 int ret;
653
654 mutex_lock(&entity->parent->graph_mutex);
655
656 /* Apply use count to node. */
657 entity->use_count += change;
658 WARN_ON(entity->use_count < 0);
659
660 /* Apply power change to connected non-nodes. */
661 ret = isp_pipeline_pm_power(entity, change);
662 if (ret < 0)
663 entity->use_count -= change;
664
665 mutex_unlock(&entity->parent->graph_mutex);
666
667 return ret;
668}
669
670/*
671 * isp_pipeline_link_notify - Link management notification callback
672 * @source: Pad at the start of the link
673 * @sink: Pad at the end of the link
674 * @flags: New link flags that will be applied
675 *
676 * React to link management on powered pipelines by updating the use count of
677 * all entities in the source and sink sides of the link. Entities are powered
678 * on or off accordingly.
679 *
680 * Return 0 on success or a negative error code on failure. Powering entities
681 * off is assumed to never fail. This function will not fail for disconnection
682 * events.
683 */
684static int isp_pipeline_link_notify(struct media_pad *source,
685 struct media_pad *sink, u32 flags)
686{
687 int source_use = isp_pipeline_pm_use_count(source->entity);
688 int sink_use = isp_pipeline_pm_use_count(sink->entity);
689 int ret;
690
691 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
692 /* Powering off entities is assumed to never fail. */
693 isp_pipeline_pm_power(source->entity, -sink_use);
694 isp_pipeline_pm_power(sink->entity, -source_use);
695 return 0;
696 }
697
698 ret = isp_pipeline_pm_power(source->entity, sink_use);
699 if (ret < 0)
700 return ret;
701
702 ret = isp_pipeline_pm_power(sink->entity, source_use);
703 if (ret < 0)
704 isp_pipeline_pm_power(source->entity, -sink_use);
705
706 return ret;
707}
708
709/* -----------------------------------------------------------------------------
710 * Pipeline stream management
711 */
712
713/*
714 * isp_pipeline_enable - Enable streaming on a pipeline
715 * @pipe: ISP pipeline
716 * @mode: Stream mode (single shot or continuous)
717 *
718 * Walk the entities chain starting at the pipeline output video node and start
719 * all modules in the chain in the given mode.
720 *
721 * Return 0 if successful, or the return value of the failed video::s_stream
722 * operation otherwise.
723 */
724static int isp_pipeline_enable(struct isp_pipeline *pipe,
725 enum isp_pipeline_stream_state mode)
726{
727 struct isp_device *isp = pipe->output->isp;
728 struct media_entity *entity;
729 struct media_pad *pad;
730 struct v4l2_subdev *subdev;
731 unsigned long flags;
732 int ret;
733
734 /* If the preview engine crashed it might not respond to read/write
735 * operations on the L4 bus. This would result in a bus fault and a
736 * kernel oops. Refuse to start streaming in that case. This check must
737 * be performed before the loop below to avoid starting entities if the
738 * pipeline won't start anyway (those entities would then likely fail to
739 * stop, making the problem worse).
740 */
741 if ((pipe->entities & isp->crashed) &
742 (1U << isp->isp_prev.subdev.entity.id))
743 return -EIO;
744
745 spin_lock_irqsave(&pipe->lock, flags);
746 pipe->state &= ~(ISP_PIPELINE_IDLE_INPUT | ISP_PIPELINE_IDLE_OUTPUT);
747 spin_unlock_irqrestore(&pipe->lock, flags);
748
749 pipe->do_propagation = false;
750
751 entity = &pipe->output->video.entity;
752 while (1) {
753 pad = &entity->pads[0];
754 if (!(pad->flags & MEDIA_PAD_FL_SINK))
755 break;
756
757 pad = media_entity_remote_source(pad);
758 if (pad == NULL ||
759 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
760 break;
761
762 entity = pad->entity;
763 subdev = media_entity_to_v4l2_subdev(entity);
764
765 ret = v4l2_subdev_call(subdev, video, s_stream, mode);
766 if (ret < 0 && ret != -ENOIOCTLCMD)
767 return ret;
768
769 if (subdev == &isp->isp_ccdc.subdev) {
770 v4l2_subdev_call(&isp->isp_aewb.subdev, video,
771 s_stream, mode);
772 v4l2_subdev_call(&isp->isp_af.subdev, video,
773 s_stream, mode);
774 v4l2_subdev_call(&isp->isp_hist.subdev, video,
775 s_stream, mode);
776 pipe->do_propagation = true;
777 }
778 }
779
780 return 0;
781}
782
783static int isp_pipeline_wait_resizer(struct isp_device *isp)
784{
785 return omap3isp_resizer_busy(&isp->isp_res);
786}
787
788static int isp_pipeline_wait_preview(struct isp_device *isp)
789{
790 return omap3isp_preview_busy(&isp->isp_prev);
791}
792
793static int isp_pipeline_wait_ccdc(struct isp_device *isp)
794{
795 return omap3isp_stat_busy(&isp->isp_af)
796 || omap3isp_stat_busy(&isp->isp_aewb)
797 || omap3isp_stat_busy(&isp->isp_hist)
798 || omap3isp_ccdc_busy(&isp->isp_ccdc);
799}
800
801#define ISP_STOP_TIMEOUT msecs_to_jiffies(1000)
802
803static int isp_pipeline_wait(struct isp_device *isp,
804 int(*busy)(struct isp_device *isp))
805{
806 unsigned long timeout = jiffies + ISP_STOP_TIMEOUT;
807
808 while (!time_after(jiffies, timeout)) {
809 if (!busy(isp))
810 return 0;
811 }
812
813 return 1;
814}
815
816/*
817 * isp_pipeline_disable - Disable streaming on a pipeline
818 * @pipe: ISP pipeline
819 *
820 * Walk the entities chain starting at the pipeline output video node and stop
821 * all modules in the chain. Wait synchronously for the modules to be stopped if
822 * necessary.
823 *
824 * Return 0 if all modules have been properly stopped, or -ETIMEDOUT if a module
825 * can't be stopped (in which case a software reset of the ISP is probably
826 * necessary).
827 */
828static int isp_pipeline_disable(struct isp_pipeline *pipe)
829{
830 struct isp_device *isp = pipe->output->isp;
831 struct media_entity *entity;
832 struct media_pad *pad;
833 struct v4l2_subdev *subdev;
834 int failure = 0;
835 int ret;
836
837 /*
838 * We need to stop all the modules after CCDC first or they'll
839 * never stop since they may not get a full frame from CCDC.
840 */
841 entity = &pipe->output->video.entity;
842 while (1) {
843 pad = &entity->pads[0];
844 if (!(pad->flags & MEDIA_PAD_FL_SINK))
845 break;
846
847 pad = media_entity_remote_source(pad);
848 if (pad == NULL ||
849 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
850 break;
851
852 entity = pad->entity;
853 subdev = media_entity_to_v4l2_subdev(entity);
854
855 if (subdev == &isp->isp_ccdc.subdev) {
856 v4l2_subdev_call(&isp->isp_aewb.subdev,
857 video, s_stream, 0);
858 v4l2_subdev_call(&isp->isp_af.subdev,
859 video, s_stream, 0);
860 v4l2_subdev_call(&isp->isp_hist.subdev,
861 video, s_stream, 0);
862 }
863
864 v4l2_subdev_call(subdev, video, s_stream, 0);
865
866 if (subdev == &isp->isp_res.subdev)
867 ret = isp_pipeline_wait(isp, isp_pipeline_wait_resizer);
868 else if (subdev == &isp->isp_prev.subdev)
869 ret = isp_pipeline_wait(isp, isp_pipeline_wait_preview);
870 else if (subdev == &isp->isp_ccdc.subdev)
871 ret = isp_pipeline_wait(isp, isp_pipeline_wait_ccdc);
872 else
873 ret = 0;
874
875 if (ret) {
876 dev_info(isp->dev, "Unable to stop %s\n", subdev->name);
877 /* If the entity failed to stopped, assume it has
878 * crashed. Mark it as such, the ISP will be reset when
879 * applications will release it.
880 */
881 isp->crashed |= 1U << subdev->entity.id;
882 failure = -ETIMEDOUT;
883 }
884 }
885
886 return failure;
887}
888
889/*
890 * omap3isp_pipeline_set_stream - Enable/disable streaming on a pipeline
891 * @pipe: ISP pipeline
892 * @state: Stream state (stopped, single shot or continuous)
893 *
894 * Set the pipeline to the given stream state. Pipelines can be started in
895 * single-shot or continuous mode.
896 *
897 * Return 0 if successful, or the return value of the failed video::s_stream
898 * operation otherwise. The pipeline state is not updated when the operation
899 * fails, except when stopping the pipeline.
900 */
901int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
902 enum isp_pipeline_stream_state state)
903{
904 int ret;
905
906 if (state == ISP_PIPELINE_STREAM_STOPPED)
907 ret = isp_pipeline_disable(pipe);
908 else
909 ret = isp_pipeline_enable(pipe, state);
910
911 if (ret == 0 || state == ISP_PIPELINE_STREAM_STOPPED)
912 pipe->stream_state = state;
913
914 return ret;
915}
916
917/*
918 * isp_pipeline_resume - Resume streaming on a pipeline
919 * @pipe: ISP pipeline
920 *
921 * Resume video output and input and re-enable pipeline.
922 */
923static void isp_pipeline_resume(struct isp_pipeline *pipe)
924{
925 int singleshot = pipe->stream_state == ISP_PIPELINE_STREAM_SINGLESHOT;
926
927 omap3isp_video_resume(pipe->output, !singleshot);
928 if (singleshot)
929 omap3isp_video_resume(pipe->input, 0);
930 isp_pipeline_enable(pipe, pipe->stream_state);
931}
932
933/*
934 * isp_pipeline_suspend - Suspend streaming on a pipeline
935 * @pipe: ISP pipeline
936 *
937 * Suspend pipeline.
938 */
939static void isp_pipeline_suspend(struct isp_pipeline *pipe)
940{
941 isp_pipeline_disable(pipe);
942}
943
944/*
945 * isp_pipeline_is_last - Verify if entity has an enabled link to the output
946 * video node
947 * @me: ISP module's media entity
948 *
949 * Returns 1 if the entity has an enabled link to the output video node or 0
950 * otherwise. It's true only while pipeline can have no more than one output
951 * node.
952 */
953static int isp_pipeline_is_last(struct media_entity *me)
954{
955 struct isp_pipeline *pipe;
956 struct media_pad *pad;
957
958 if (!me->pipe)
959 return 0;
960 pipe = to_isp_pipeline(me);
961 if (pipe->stream_state == ISP_PIPELINE_STREAM_STOPPED)
962 return 0;
963 pad = media_entity_remote_source(&pipe->output->pad);
964 return pad->entity == me;
965}
966
967/*
968 * isp_suspend_module_pipeline - Suspend pipeline to which belongs the module
969 * @me: ISP module's media entity
970 *
971 * Suspend the whole pipeline if module's entity has an enabled link to the
972 * output video node. It works only while pipeline can have no more than one
973 * output node.
974 */
975static void isp_suspend_module_pipeline(struct media_entity *me)
976{
977 if (isp_pipeline_is_last(me))
978 isp_pipeline_suspend(to_isp_pipeline(me));
979}
980
981/*
982 * isp_resume_module_pipeline - Resume pipeline to which belongs the module
983 * @me: ISP module's media entity
984 *
985 * Resume the whole pipeline if module's entity has an enabled link to the
986 * output video node. It works only while pipeline can have no more than one
987 * output node.
988 */
989static void isp_resume_module_pipeline(struct media_entity *me)
990{
991 if (isp_pipeline_is_last(me))
992 isp_pipeline_resume(to_isp_pipeline(me));
993}
994
995/*
996 * isp_suspend_modules - Suspend ISP submodules.
997 * @isp: OMAP3 ISP device
998 *
999 * Returns 0 if suspend left in idle state all the submodules properly,
1000 * or returns 1 if a general Reset is required to suspend the submodules.
1001 */
1002static int isp_suspend_modules(struct isp_device *isp)
1003{
1004 unsigned long timeout;
1005
1006 omap3isp_stat_suspend(&isp->isp_aewb);
1007 omap3isp_stat_suspend(&isp->isp_af);
1008 omap3isp_stat_suspend(&isp->isp_hist);
1009 isp_suspend_module_pipeline(&isp->isp_res.subdev.entity);
1010 isp_suspend_module_pipeline(&isp->isp_prev.subdev.entity);
1011 isp_suspend_module_pipeline(&isp->isp_ccdc.subdev.entity);
1012 isp_suspend_module_pipeline(&isp->isp_csi2a.subdev.entity);
1013 isp_suspend_module_pipeline(&isp->isp_ccp2.subdev.entity);
1014
1015 timeout = jiffies + ISP_STOP_TIMEOUT;
1016 while (omap3isp_stat_busy(&isp->isp_af)
1017 || omap3isp_stat_busy(&isp->isp_aewb)
1018 || omap3isp_stat_busy(&isp->isp_hist)
1019 || omap3isp_preview_busy(&isp->isp_prev)
1020 || omap3isp_resizer_busy(&isp->isp_res)
1021 || omap3isp_ccdc_busy(&isp->isp_ccdc)) {
1022 if (time_after(jiffies, timeout)) {
1023 dev_info(isp->dev, "can't stop modules.\n");
1024 return 1;
1025 }
1026 msleep(1);
1027 }
1028
1029 return 0;
1030}
1031
1032/*
1033 * isp_resume_modules - Resume ISP submodules.
1034 * @isp: OMAP3 ISP device
1035 */
1036static void isp_resume_modules(struct isp_device *isp)
1037{
1038 omap3isp_stat_resume(&isp->isp_aewb);
1039 omap3isp_stat_resume(&isp->isp_af);
1040 omap3isp_stat_resume(&isp->isp_hist);
1041 isp_resume_module_pipeline(&isp->isp_res.subdev.entity);
1042 isp_resume_module_pipeline(&isp->isp_prev.subdev.entity);
1043 isp_resume_module_pipeline(&isp->isp_ccdc.subdev.entity);
1044 isp_resume_module_pipeline(&isp->isp_csi2a.subdev.entity);
1045 isp_resume_module_pipeline(&isp->isp_ccp2.subdev.entity);
1046}
1047
1048/*
1049 * isp_reset - Reset ISP with a timeout wait for idle.
1050 * @isp: OMAP3 ISP device
1051 */
1052static int isp_reset(struct isp_device *isp)
1053{
1054 unsigned long timeout = 0;
1055
1056 isp_reg_writel(isp,
1057 isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG)
1058 | ISP_SYSCONFIG_SOFTRESET,
1059 OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
1060 while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN,
1061 ISP_SYSSTATUS) & 0x1)) {
1062 if (timeout++ > 10000) {
1063 dev_alert(isp->dev, "cannot reset ISP\n");
1064 return -ETIMEDOUT;
1065 }
1066 udelay(1);
1067 }
1068
1069 isp->crashed = 0;
1070 return 0;
1071}
1072
1073/*
1074 * isp_save_context - Saves the values of the ISP module registers.
1075 * @isp: OMAP3 ISP device
1076 * @reg_list: Structure containing pairs of register address and value to
1077 * modify on OMAP.
1078 */
1079static void
1080isp_save_context(struct isp_device *isp, struct isp_reg *reg_list)
1081{
1082 struct isp_reg *next = reg_list;
1083
1084 for (; next->reg != ISP_TOK_TERM; next++)
1085 next->val = isp_reg_readl(isp, next->mmio_range, next->reg);
1086}
1087
1088/*
1089 * isp_restore_context - Restores the values of the ISP module registers.
1090 * @isp: OMAP3 ISP device
1091 * @reg_list: Structure containing pairs of register address and value to
1092 * modify on OMAP.
1093 */
1094static void
1095isp_restore_context(struct isp_device *isp, struct isp_reg *reg_list)
1096{
1097 struct isp_reg *next = reg_list;
1098
1099 for (; next->reg != ISP_TOK_TERM; next++)
1100 isp_reg_writel(isp, next->val, next->mmio_range, next->reg);
1101}
1102
1103/*
1104 * isp_save_ctx - Saves ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
1105 * @isp: OMAP3 ISP device
1106 *
1107 * Routine for saving the context of each module in the ISP.
1108 * CCDC, HIST, H3A, PREV, RESZ and MMU.
1109 */
1110static void isp_save_ctx(struct isp_device *isp)
1111{
1112 isp_save_context(isp, isp_reg_list);
1113 omap_iommu_save_ctx(isp->dev);
1114}
1115
1116/*
1117 * isp_restore_ctx - Restores ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
1118 * @isp: OMAP3 ISP device
1119 *
1120 * Routine for restoring the context of each module in the ISP.
1121 * CCDC, HIST, H3A, PREV, RESZ and MMU.
1122 */
1123static void isp_restore_ctx(struct isp_device *isp)
1124{
1125 isp_restore_context(isp, isp_reg_list);
1126 omap_iommu_restore_ctx(isp->dev);
1127 omap3isp_ccdc_restore_context(isp);
1128 omap3isp_preview_restore_context(isp);
1129}
1130
1131/* -----------------------------------------------------------------------------
1132 * SBL resources management
1133 */
1134#define OMAP3_ISP_SBL_READ (OMAP3_ISP_SBL_CSI1_READ | \
1135 OMAP3_ISP_SBL_CCDC_LSC_READ | \
1136 OMAP3_ISP_SBL_PREVIEW_READ | \
1137 OMAP3_ISP_SBL_RESIZER_READ)
1138#define OMAP3_ISP_SBL_WRITE (OMAP3_ISP_SBL_CSI1_WRITE | \
1139 OMAP3_ISP_SBL_CSI2A_WRITE | \
1140 OMAP3_ISP_SBL_CSI2C_WRITE | \
1141 OMAP3_ISP_SBL_CCDC_WRITE | \
1142 OMAP3_ISP_SBL_PREVIEW_WRITE)
1143
1144void omap3isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res)
1145{
1146 u32 sbl = 0;
1147
1148 isp->sbl_resources |= res;
1149
1150 if (isp->sbl_resources & OMAP3_ISP_SBL_CSI1_READ)
1151 sbl |= ISPCTRL_SBL_SHARED_RPORTA;
1152
1153 if (isp->sbl_resources & OMAP3_ISP_SBL_CCDC_LSC_READ)
1154 sbl |= ISPCTRL_SBL_SHARED_RPORTB;
1155
1156 if (isp->sbl_resources & OMAP3_ISP_SBL_CSI2C_WRITE)
1157 sbl |= ISPCTRL_SBL_SHARED_WPORTC;
1158
1159 if (isp->sbl_resources & OMAP3_ISP_SBL_RESIZER_WRITE)
1160 sbl |= ISPCTRL_SBL_WR0_RAM_EN;
1161
1162 if (isp->sbl_resources & OMAP3_ISP_SBL_WRITE)
1163 sbl |= ISPCTRL_SBL_WR1_RAM_EN;
1164
1165 if (isp->sbl_resources & OMAP3_ISP_SBL_READ)
1166 sbl |= ISPCTRL_SBL_RD_RAM_EN;
1167
1168 isp_reg_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, sbl);
1169}
1170
1171void omap3isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res)
1172{
1173 u32 sbl = 0;
1174
1175 isp->sbl_resources &= ~res;
1176
1177 if (!(isp->sbl_resources & OMAP3_ISP_SBL_CSI1_READ))
1178 sbl |= ISPCTRL_SBL_SHARED_RPORTA;
1179
1180 if (!(isp->sbl_resources & OMAP3_ISP_SBL_CCDC_LSC_READ))
1181 sbl |= ISPCTRL_SBL_SHARED_RPORTB;
1182
1183 if (!(isp->sbl_resources & OMAP3_ISP_SBL_CSI2C_WRITE))
1184 sbl |= ISPCTRL_SBL_SHARED_WPORTC;
1185
1186 if (!(isp->sbl_resources & OMAP3_ISP_SBL_RESIZER_WRITE))
1187 sbl |= ISPCTRL_SBL_WR0_RAM_EN;
1188
1189 if (!(isp->sbl_resources & OMAP3_ISP_SBL_WRITE))
1190 sbl |= ISPCTRL_SBL_WR1_RAM_EN;
1191
1192 if (!(isp->sbl_resources & OMAP3_ISP_SBL_READ))
1193 sbl |= ISPCTRL_SBL_RD_RAM_EN;
1194
1195 isp_reg_clr(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, sbl);
1196}
1197
1198/*
1199 * isp_module_sync_idle - Helper to sync module with its idle state
1200 * @me: ISP submodule's media entity
1201 * @wait: ISP submodule's wait queue for streamoff/interrupt synchronization
1202 * @stopping: flag which tells module wants to stop
1203 *
1204 * This function checks if ISP submodule needs to wait for next interrupt. If
1205 * yes, makes the caller to sleep while waiting for such event.
1206 */
1207int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
1208 atomic_t *stopping)
1209{
1210 struct isp_pipeline *pipe = to_isp_pipeline(me);
1211
1212 if (pipe->stream_state == ISP_PIPELINE_STREAM_STOPPED ||
1213 (pipe->stream_state == ISP_PIPELINE_STREAM_SINGLESHOT &&
1214 !isp_pipeline_ready(pipe)))
1215 return 0;
1216
1217 /*
1218 * atomic_set() doesn't include memory barrier on ARM platform for SMP
1219 * scenario. We'll call it here to avoid race conditions.
1220 */
1221 atomic_set(stopping, 1);
1222 smp_mb();
1223
1224 /*
1225 * If module is the last one, it's writing to memory. In this case,
1226 * it's necessary to check if the module is already paused due to
1227 * DMA queue underrun or if it has to wait for next interrupt to be
1228 * idle.
1229 * If it isn't the last one, the function won't sleep but *stopping
1230 * will still be set to warn next submodule caller's interrupt the
1231 * module wants to be idle.
1232 */
1233 if (isp_pipeline_is_last(me)) {
1234 struct isp_video *video = pipe->output;
1235 unsigned long flags;
1236 spin_lock_irqsave(&video->queue->irqlock, flags);
1237 if (video->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
1238 spin_unlock_irqrestore(&video->queue->irqlock, flags);
1239 atomic_set(stopping, 0);
1240 smp_mb();
1241 return 0;
1242 }
1243 spin_unlock_irqrestore(&video->queue->irqlock, flags);
1244 if (!wait_event_timeout(*wait, !atomic_read(stopping),
1245 msecs_to_jiffies(1000))) {
1246 atomic_set(stopping, 0);
1247 smp_mb();
1248 return -ETIMEDOUT;
1249 }
1250 }
1251
1252 return 0;
1253}
1254
1255/*
1256 * omap3isp_module_sync_is_stopped - Helper to verify if module was stopping
1257 * @wait: ISP submodule's wait queue for streamoff/interrupt synchronization
1258 * @stopping: flag which tells module wants to stop
1259 *
1260 * This function checks if ISP submodule was stopping. In case of yes, it
1261 * notices the caller by setting stopping to 0 and waking up the wait queue.
1262 * Returns 1 if it was stopping or 0 otherwise.
1263 */
1264int omap3isp_module_sync_is_stopping(wait_queue_head_t *wait,
1265 atomic_t *stopping)
1266{
1267 if (atomic_cmpxchg(stopping, 1, 0)) {
1268 wake_up(wait);
1269 return 1;
1270 }
1271
1272 return 0;
1273}
1274
1275/* --------------------------------------------------------------------------
1276 * Clock management
1277 */
1278
1279#define ISPCTRL_CLKS_MASK (ISPCTRL_H3A_CLK_EN | \
1280 ISPCTRL_HIST_CLK_EN | \
1281 ISPCTRL_RSZ_CLK_EN | \
1282 (ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN) | \
1283 (ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN))
1284
1285static void __isp_subclk_update(struct isp_device *isp)
1286{
1287 u32 clk = 0;
1288
1289 /* AEWB and AF share the same clock. */
1290 if (isp->subclk_resources &
1291 (OMAP3_ISP_SUBCLK_AEWB | OMAP3_ISP_SUBCLK_AF))
1292 clk |= ISPCTRL_H3A_CLK_EN;
1293
1294 if (isp->subclk_resources & OMAP3_ISP_SUBCLK_HIST)
1295 clk |= ISPCTRL_HIST_CLK_EN;
1296
1297 if (isp->subclk_resources & OMAP3_ISP_SUBCLK_RESIZER)
1298 clk |= ISPCTRL_RSZ_CLK_EN;
1299
1300 /* NOTE: For CCDC & Preview submodules, we need to affect internal
1301 * RAM as well.
1302 */
1303 if (isp->subclk_resources & OMAP3_ISP_SUBCLK_CCDC)
1304 clk |= ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN;
1305
1306 if (isp->subclk_resources & OMAP3_ISP_SUBCLK_PREVIEW)
1307 clk |= ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN;
1308
1309 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
1310 ISPCTRL_CLKS_MASK, clk);
1311}
1312
1313void omap3isp_subclk_enable(struct isp_device *isp,
1314 enum isp_subclk_resource res)
1315{
1316 isp->subclk_resources |= res;
1317
1318 __isp_subclk_update(isp);
1319}
1320
1321void omap3isp_subclk_disable(struct isp_device *isp,
1322 enum isp_subclk_resource res)
1323{
1324 isp->subclk_resources &= ~res;
1325
1326 __isp_subclk_update(isp);
1327}
1328
1329/*
1330 * isp_enable_clocks - Enable ISP clocks
1331 * @isp: OMAP3 ISP device
1332 *
1333 * Return 0 if successful, or clk_enable return value if any of tthem fails.
1334 */
1335static int isp_enable_clocks(struct isp_device *isp)
1336{
1337 int r;
1338 unsigned long rate;
1339 int divisor;
1340
1341 /*
1342 * cam_mclk clock chain:
1343 * dpll4 -> dpll4_m5 -> dpll4_m5x2 -> cam_mclk
1344 *
1345 * In OMAP3630 dpll4_m5x2 != 2 x dpll4_m5 but both are
1346 * set to the same value. Hence the rate set for dpll4_m5
1347 * has to be twice of what is set on OMAP3430 to get
1348 * the required value for cam_mclk
1349 */
1350 if (cpu_is_omap3630())
1351 divisor = 1;
1352 else
1353 divisor = 2;
1354
1355 r = clk_enable(isp->clock[ISP_CLK_CAM_ICK]);
1356 if (r) {
1357 dev_err(isp->dev, "clk_enable cam_ick failed\n");
1358 goto out_clk_enable_ick;
1359 }
1360 r = clk_set_rate(isp->clock[ISP_CLK_DPLL4_M5_CK],
1361 CM_CAM_MCLK_HZ/divisor);
1362 if (r) {
1363 dev_err(isp->dev, "clk_set_rate for dpll4_m5_ck failed\n");
1364 goto out_clk_enable_mclk;
1365 }
1366 r = clk_enable(isp->clock[ISP_CLK_CAM_MCLK]);
1367 if (r) {
1368 dev_err(isp->dev, "clk_enable cam_mclk failed\n");
1369 goto out_clk_enable_mclk;
1370 }
1371 rate = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
1372 if (rate != CM_CAM_MCLK_HZ)
1373 dev_warn(isp->dev, "unexpected cam_mclk rate:\n"
1374 " expected : %d\n"
1375 " actual : %ld\n", CM_CAM_MCLK_HZ, rate);
1376 r = clk_enable(isp->clock[ISP_CLK_CSI2_FCK]);
1377 if (r) {
1378 dev_err(isp->dev, "clk_enable csi2_fck failed\n");
1379 goto out_clk_enable_csi2_fclk;
1380 }
1381 return 0;
1382
1383out_clk_enable_csi2_fclk:
1384 clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
1385out_clk_enable_mclk:
1386 clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
1387out_clk_enable_ick:
1388 return r;
1389}
1390
1391/*
1392 * isp_disable_clocks - Disable ISP clocks
1393 * @isp: OMAP3 ISP device
1394 */
1395static void isp_disable_clocks(struct isp_device *isp)
1396{
1397 clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
1398 clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
1399 clk_disable(isp->clock[ISP_CLK_CSI2_FCK]);
1400}
1401
1402static const char *isp_clocks[] = {
1403 "cam_ick",
1404 "cam_mclk",
1405 "dpll4_m5_ck",
1406 "csi2_96m_fck",
1407 "l3_ick",
1408};
1409
1410static void isp_put_clocks(struct isp_device *isp)
1411{
1412 unsigned int i;
1413
1414 for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
1415 if (isp->clock[i]) {
1416 clk_put(isp->clock[i]);
1417 isp->clock[i] = NULL;
1418 }
1419 }
1420}
1421
1422static int isp_get_clocks(struct isp_device *isp)
1423{
1424 struct clk *clk;
1425 unsigned int i;
1426
1427 for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
1428 clk = clk_get(isp->dev, isp_clocks[i]);
1429 if (IS_ERR(clk)) {
1430 dev_err(isp->dev, "clk_get %s failed\n", isp_clocks[i]);
1431 isp_put_clocks(isp);
1432 return PTR_ERR(clk);
1433 }
1434
1435 isp->clock[i] = clk;
1436 }
1437
1438 return 0;
1439}
1440
1441/*
1442 * omap3isp_get - Acquire the ISP resource.
1443 *
1444 * Initializes the clocks for the first acquire.
1445 *
1446 * Increment the reference count on the ISP. If the first reference is taken,
1447 * enable clocks and power-up all submodules.
1448 *
1449 * Return a pointer to the ISP device structure, or NULL if an error occurred.
1450 */
1451static struct isp_device *__omap3isp_get(struct isp_device *isp, bool irq)
1452{
1453 struct isp_device *__isp = isp;
1454
1455 if (isp == NULL)
1456 return NULL;
1457
1458 mutex_lock(&isp->isp_mutex);
1459 if (isp->ref_count > 0)
1460 goto out;
1461
1462 if (isp_enable_clocks(isp) < 0) {
1463 __isp = NULL;
1464 goto out;
1465 }
1466
1467 /* We don't want to restore context before saving it! */
1468 if (isp->has_context)
1469 isp_restore_ctx(isp);
1470
1471 if (irq)
1472 isp_enable_interrupts(isp);
1473
1474out:
1475 if (__isp != NULL)
1476 isp->ref_count++;
1477 mutex_unlock(&isp->isp_mutex);
1478
1479 return __isp;
1480}
1481
1482struct isp_device *omap3isp_get(struct isp_device *isp)
1483{
1484 return __omap3isp_get(isp, true);
1485}
1486
1487/*
1488 * omap3isp_put - Release the ISP
1489 *
1490 * Decrement the reference count on the ISP. If the last reference is released,
1491 * power-down all submodules, disable clocks and free temporary buffers.
1492 */
1493void omap3isp_put(struct isp_device *isp)
1494{
1495 if (isp == NULL)
1496 return;
1497
1498 mutex_lock(&isp->isp_mutex);
1499 BUG_ON(isp->ref_count == 0);
1500 if (--isp->ref_count == 0) {
1501 isp_disable_interrupts(isp);
1502 if (isp->domain) {
1503 isp_save_ctx(isp);
1504 isp->has_context = 1;
1505 }
1506 /* Reset the ISP if an entity has failed to stop. This is the
1507 * only way to recover from such conditions.
1508 */
1509 if (isp->crashed)
1510 isp_reset(isp);
1511 isp_disable_clocks(isp);
1512 }
1513 mutex_unlock(&isp->isp_mutex);
1514}
1515
1516/* --------------------------------------------------------------------------
1517 * Platform device driver
1518 */
1519
1520/*
1521 * omap3isp_print_status - Prints the values of the ISP Control Module registers
1522 * @isp: OMAP3 ISP device
1523 */
1524#define ISP_PRINT_REGISTER(isp, name)\
1525 dev_dbg(isp->dev, "###ISP " #name "=0x%08x\n", \
1526 isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_##name))
1527#define SBL_PRINT_REGISTER(isp, name)\
1528 dev_dbg(isp->dev, "###SBL " #name "=0x%08x\n", \
1529 isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_##name))
1530
1531void omap3isp_print_status(struct isp_device *isp)
1532{
1533 dev_dbg(isp->dev, "-------------ISP Register dump--------------\n");
1534
1535 ISP_PRINT_REGISTER(isp, SYSCONFIG);
1536 ISP_PRINT_REGISTER(isp, SYSSTATUS);
1537 ISP_PRINT_REGISTER(isp, IRQ0ENABLE);
1538 ISP_PRINT_REGISTER(isp, IRQ0STATUS);
1539 ISP_PRINT_REGISTER(isp, TCTRL_GRESET_LENGTH);
1540 ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_REPLAY);
1541 ISP_PRINT_REGISTER(isp, CTRL);
1542 ISP_PRINT_REGISTER(isp, TCTRL_CTRL);
1543 ISP_PRINT_REGISTER(isp, TCTRL_FRAME);
1544 ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_DELAY);
1545 ISP_PRINT_REGISTER(isp, TCTRL_STRB_DELAY);
1546 ISP_PRINT_REGISTER(isp, TCTRL_SHUT_DELAY);
1547 ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_LENGTH);
1548 ISP_PRINT_REGISTER(isp, TCTRL_STRB_LENGTH);
1549 ISP_PRINT_REGISTER(isp, TCTRL_SHUT_LENGTH);
1550
1551 SBL_PRINT_REGISTER(isp, PCR);
1552 SBL_PRINT_REGISTER(isp, SDR_REQ_EXP);
1553
1554 dev_dbg(isp->dev, "--------------------------------------------\n");
1555}
1556
1557#ifdef CONFIG_PM
1558
1559/*
1560 * Power management support.
1561 *
1562 * As the ISP can't properly handle an input video stream interruption on a non
1563 * frame boundary, the ISP pipelines need to be stopped before sensors get
1564 * suspended. However, as suspending the sensors can require a running clock,
1565 * which can be provided by the ISP, the ISP can't be completely suspended
1566 * before the sensor.
1567 *
1568 * To solve this problem power management support is split into prepare/complete
1569 * and suspend/resume operations. The pipelines are stopped in prepare() and the
1570 * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in
1571 * resume(), and the the pipelines are restarted in complete().
1572 *
1573 * TODO: PM dependencies between the ISP and sensors are not modeled explicitly
1574 * yet.
1575 */
1576static int isp_pm_prepare(struct device *dev)
1577{
1578 struct isp_device *isp = dev_get_drvdata(dev);
1579 int reset;
1580
1581 WARN_ON(mutex_is_locked(&isp->isp_mutex));
1582
1583 if (isp->ref_count == 0)
1584 return 0;
1585
1586 reset = isp_suspend_modules(isp);
1587 isp_disable_interrupts(isp);
1588 isp_save_ctx(isp);
1589 if (reset)
1590 isp_reset(isp);
1591
1592 return 0;
1593}
1594
1595static int isp_pm_suspend(struct device *dev)
1596{
1597 struct isp_device *isp = dev_get_drvdata(dev);
1598
1599 WARN_ON(mutex_is_locked(&isp->isp_mutex));
1600
1601 if (isp->ref_count)
1602 isp_disable_clocks(isp);
1603
1604 return 0;
1605}
1606
1607static int isp_pm_resume(struct device *dev)
1608{
1609 struct isp_device *isp = dev_get_drvdata(dev);
1610
1611 if (isp->ref_count == 0)
1612 return 0;
1613
1614 return isp_enable_clocks(isp);
1615}
1616
1617static void isp_pm_complete(struct device *dev)
1618{
1619 struct isp_device *isp = dev_get_drvdata(dev);
1620
1621 if (isp->ref_count == 0)
1622 return;
1623
1624 isp_restore_ctx(isp);
1625 isp_enable_interrupts(isp);
1626 isp_resume_modules(isp);
1627}
1628
1629#else
1630
1631#define isp_pm_prepare NULL
1632#define isp_pm_suspend NULL
1633#define isp_pm_resume NULL
1634#define isp_pm_complete NULL
1635
1636#endif /* CONFIG_PM */
1637
1638static void isp_unregister_entities(struct isp_device *isp)
1639{
1640 omap3isp_csi2_unregister_entities(&isp->isp_csi2a);
1641 omap3isp_ccp2_unregister_entities(&isp->isp_ccp2);
1642 omap3isp_ccdc_unregister_entities(&isp->isp_ccdc);
1643 omap3isp_preview_unregister_entities(&isp->isp_prev);
1644 omap3isp_resizer_unregister_entities(&isp->isp_res);
1645 omap3isp_stat_unregister_entities(&isp->isp_aewb);
1646 omap3isp_stat_unregister_entities(&isp->isp_af);
1647 omap3isp_stat_unregister_entities(&isp->isp_hist);
1648
1649 v4l2_device_unregister(&isp->v4l2_dev);
1650 media_device_unregister(&isp->media_dev);
1651}
1652
1653/*
1654 * isp_register_subdev_group - Register a group of subdevices
1655 * @isp: OMAP3 ISP device
1656 * @board_info: I2C subdevs board information array
1657 *
1658 * Register all I2C subdevices in the board_info array. The array must be
1659 * terminated by a NULL entry, and the first entry must be the sensor.
1660 *
1661 * Return a pointer to the sensor media entity if it has been successfully
1662 * registered, or NULL otherwise.
1663 */
1664static struct v4l2_subdev *
1665isp_register_subdev_group(struct isp_device *isp,
1666 struct isp_subdev_i2c_board_info *board_info)
1667{
1668 struct v4l2_subdev *sensor = NULL;
1669 unsigned int first;
1670
1671 if (board_info->board_info == NULL)
1672 return NULL;
1673
1674 for (first = 1; board_info->board_info; ++board_info, first = 0) {
1675 struct v4l2_subdev *subdev;
1676 struct i2c_adapter *adapter;
1677
1678 adapter = i2c_get_adapter(board_info->i2c_adapter_id);
1679 if (adapter == NULL) {
1680 printk(KERN_ERR "%s: Unable to get I2C adapter %d for "
1681 "device %s\n", __func__,
1682 board_info->i2c_adapter_id,
1683 board_info->board_info->type);
1684 continue;
1685 }
1686
1687 subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
1688 board_info->board_info, NULL);
1689 if (subdev == NULL) {
1690 printk(KERN_ERR "%s: Unable to register subdev %s\n",
1691 __func__, board_info->board_info->type);
1692 continue;
1693 }
1694
1695 if (first)
1696 sensor = subdev;
1697 }
1698
1699 return sensor;
1700}
1701
1702static int isp_register_entities(struct isp_device *isp)
1703{
1704 struct isp_platform_data *pdata = isp->pdata;
1705 struct isp_v4l2_subdevs_group *subdevs;
1706 int ret;
1707
1708 isp->media_dev.dev = isp->dev;
1709 strlcpy(isp->media_dev.model, "TI OMAP3 ISP",
1710 sizeof(isp->media_dev.model));
1711 isp->media_dev.hw_revision = isp->revision;
1712 isp->media_dev.link_notify = isp_pipeline_link_notify;
1713 ret = media_device_register(&isp->media_dev);
1714 if (ret < 0) {
1715 printk(KERN_ERR "%s: Media device registration failed (%d)\n",
1716 __func__, ret);
1717 return ret;
1718 }
1719
1720 isp->v4l2_dev.mdev = &isp->media_dev;
1721 ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
1722 if (ret < 0) {
1723 printk(KERN_ERR "%s: V4L2 device registration failed (%d)\n",
1724 __func__, ret);
1725 goto done;
1726 }
1727
1728 /* Register internal entities */
1729 ret = omap3isp_ccp2_register_entities(&isp->isp_ccp2, &isp->v4l2_dev);
1730 if (ret < 0)
1731 goto done;
1732
1733 ret = omap3isp_csi2_register_entities(&isp->isp_csi2a, &isp->v4l2_dev);
1734 if (ret < 0)
1735 goto done;
1736
1737 ret = omap3isp_ccdc_register_entities(&isp->isp_ccdc, &isp->v4l2_dev);
1738 if (ret < 0)
1739 goto done;
1740
1741 ret = omap3isp_preview_register_entities(&isp->isp_prev,
1742 &isp->v4l2_dev);
1743 if (ret < 0)
1744 goto done;
1745
1746 ret = omap3isp_resizer_register_entities(&isp->isp_res, &isp->v4l2_dev);
1747 if (ret < 0)
1748 goto done;
1749
1750 ret = omap3isp_stat_register_entities(&isp->isp_aewb, &isp->v4l2_dev);
1751 if (ret < 0)
1752 goto done;
1753
1754 ret = omap3isp_stat_register_entities(&isp->isp_af, &isp->v4l2_dev);
1755 if (ret < 0)
1756 goto done;
1757
1758 ret = omap3isp_stat_register_entities(&isp->isp_hist, &isp->v4l2_dev);
1759 if (ret < 0)
1760 goto done;
1761
1762 /* Register external entities */
1763 for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) {
1764 struct v4l2_subdev *sensor;
1765 struct media_entity *input;
1766 unsigned int flags;
1767 unsigned int pad;
1768
1769 sensor = isp_register_subdev_group(isp, subdevs->subdevs);
1770 if (sensor == NULL)
1771 continue;
1772
1773 sensor->host_priv = subdevs;
1774
1775 /* Connect the sensor to the correct interface module. Parallel
1776 * sensors are connected directly to the CCDC, while serial
1777 * sensors are connected to the CSI2a, CCP2b or CSI2c receiver
1778 * through CSIPHY1 or CSIPHY2.
1779 */
1780 switch (subdevs->interface) {
1781 case ISP_INTERFACE_PARALLEL:
1782 input = &isp->isp_ccdc.subdev.entity;
1783 pad = CCDC_PAD_SINK;
1784 flags = 0;
1785 break;
1786
1787 case ISP_INTERFACE_CSI2A_PHY2:
1788 input = &isp->isp_csi2a.subdev.entity;
1789 pad = CSI2_PAD_SINK;
1790 flags = MEDIA_LNK_FL_IMMUTABLE
1791 | MEDIA_LNK_FL_ENABLED;
1792 break;
1793
1794 case ISP_INTERFACE_CCP2B_PHY1:
1795 case ISP_INTERFACE_CCP2B_PHY2:
1796 input = &isp->isp_ccp2.subdev.entity;
1797 pad = CCP2_PAD_SINK;
1798 flags = 0;
1799 break;
1800
1801 case ISP_INTERFACE_CSI2C_PHY1:
1802 input = &isp->isp_csi2c.subdev.entity;
1803 pad = CSI2_PAD_SINK;
1804 flags = MEDIA_LNK_FL_IMMUTABLE
1805 | MEDIA_LNK_FL_ENABLED;
1806 break;
1807
1808 default:
1809 printk(KERN_ERR "%s: invalid interface type %u\n",
1810 __func__, subdevs->interface);
1811 ret = -EINVAL;
1812 goto done;
1813 }
1814
1815 ret = media_entity_create_link(&sensor->entity, 0, input, pad,
1816 flags);
1817 if (ret < 0)
1818 goto done;
1819 }
1820
1821 ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
1822
1823done:
1824 if (ret < 0)
1825 isp_unregister_entities(isp);
1826
1827 return ret;
1828}
1829
1830static void isp_cleanup_modules(struct isp_device *isp)
1831{
1832 omap3isp_h3a_aewb_cleanup(isp);
1833 omap3isp_h3a_af_cleanup(isp);
1834 omap3isp_hist_cleanup(isp);
1835 omap3isp_resizer_cleanup(isp);
1836 omap3isp_preview_cleanup(isp);
1837 omap3isp_ccdc_cleanup(isp);
1838 omap3isp_ccp2_cleanup(isp);
1839 omap3isp_csi2_cleanup(isp);
1840}
1841
1842static int isp_initialize_modules(struct isp_device *isp)
1843{
1844 int ret;
1845
1846 ret = omap3isp_csiphy_init(isp);
1847 if (ret < 0) {
1848 dev_err(isp->dev, "CSI PHY initialization failed\n");
1849 goto error_csiphy;
1850 }
1851
1852 ret = omap3isp_csi2_init(isp);
1853 if (ret < 0) {
1854 dev_err(isp->dev, "CSI2 initialization failed\n");
1855 goto error_csi2;
1856 }
1857
1858 ret = omap3isp_ccp2_init(isp);
1859 if (ret < 0) {
1860 dev_err(isp->dev, "CCP2 initialization failed\n");
1861 goto error_ccp2;
1862 }
1863
1864 ret = omap3isp_ccdc_init(isp);
1865 if (ret < 0) {
1866 dev_err(isp->dev, "CCDC initialization failed\n");
1867 goto error_ccdc;
1868 }
1869
1870 ret = omap3isp_preview_init(isp);
1871 if (ret < 0) {
1872 dev_err(isp->dev, "Preview initialization failed\n");
1873 goto error_preview;
1874 }
1875
1876 ret = omap3isp_resizer_init(isp);
1877 if (ret < 0) {
1878 dev_err(isp->dev, "Resizer initialization failed\n");
1879 goto error_resizer;
1880 }
1881
1882 ret = omap3isp_hist_init(isp);
1883 if (ret < 0) {
1884 dev_err(isp->dev, "Histogram initialization failed\n");
1885 goto error_hist;
1886 }
1887
1888 ret = omap3isp_h3a_aewb_init(isp);
1889 if (ret < 0) {
1890 dev_err(isp->dev, "H3A AEWB initialization failed\n");
1891 goto error_h3a_aewb;
1892 }
1893
1894 ret = omap3isp_h3a_af_init(isp);
1895 if (ret < 0) {
1896 dev_err(isp->dev, "H3A AF initialization failed\n");
1897 goto error_h3a_af;
1898 }
1899
1900 /* Connect the submodules. */
1901 ret = media_entity_create_link(
1902 &isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
1903 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
1904 if (ret < 0)
1905 goto error_link;
1906
1907 ret = media_entity_create_link(
1908 &isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
1909 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
1910 if (ret < 0)
1911 goto error_link;
1912
1913 ret = media_entity_create_link(
1914 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
1915 &isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
1916 if (ret < 0)
1917 goto error_link;
1918
1919 ret = media_entity_create_link(
1920 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
1921 &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
1922 if (ret < 0)
1923 goto error_link;
1924
1925 ret = media_entity_create_link(
1926 &isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
1927 &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
1928 if (ret < 0)
1929 goto error_link;
1930
1931 ret = media_entity_create_link(
1932 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
1933 &isp->isp_aewb.subdev.entity, 0,
1934 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
1935 if (ret < 0)
1936 goto error_link;
1937
1938 ret = media_entity_create_link(
1939 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
1940 &isp->isp_af.subdev.entity, 0,
1941 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
1942 if (ret < 0)
1943 goto error_link;
1944
1945 ret = media_entity_create_link(
1946 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
1947 &isp->isp_hist.subdev.entity, 0,
1948 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
1949 if (ret < 0)
1950 goto error_link;
1951
1952 return 0;
1953
1954error_link:
1955 omap3isp_h3a_af_cleanup(isp);
1956error_h3a_af:
1957 omap3isp_h3a_aewb_cleanup(isp);
1958error_h3a_aewb:
1959 omap3isp_hist_cleanup(isp);
1960error_hist:
1961 omap3isp_resizer_cleanup(isp);
1962error_resizer:
1963 omap3isp_preview_cleanup(isp);
1964error_preview:
1965 omap3isp_ccdc_cleanup(isp);
1966error_ccdc:
1967 omap3isp_ccp2_cleanup(isp);
1968error_ccp2:
1969 omap3isp_csi2_cleanup(isp);
1970error_csi2:
1971error_csiphy:
1972 return ret;
1973}
1974
1975/*
1976 * isp_remove - Remove ISP platform device
1977 * @pdev: Pointer to ISP platform device
1978 *
1979 * Always returns 0.
1980 */
1981static int __devexit isp_remove(struct platform_device *pdev)
1982{
1983 struct isp_device *isp = platform_get_drvdata(pdev);
1984 int i;
1985
1986 isp_unregister_entities(isp);
1987 isp_cleanup_modules(isp);
1988
1989 __omap3isp_get(isp, false);
1990 iommu_detach_device(isp->domain, &pdev->dev);
1991 iommu_domain_free(isp->domain);
1992 isp->domain = NULL;
1993 omap3isp_put(isp);
1994
1995 free_irq(isp->irq_num, isp);
1996 isp_put_clocks(isp);
1997
1998 for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) {
1999 if (isp->mmio_base[i]) {
2000 iounmap(isp->mmio_base[i]);
2001 isp->mmio_base[i] = NULL;
2002 }
2003
2004 if (isp->mmio_base_phys[i]) {
2005 release_mem_region(isp->mmio_base_phys[i],
2006 isp->mmio_size[i]);
2007 isp->mmio_base_phys[i] = 0;
2008 }
2009 }
2010
2011 regulator_put(isp->isp_csiphy1.vdd);
2012 regulator_put(isp->isp_csiphy2.vdd);
2013 kfree(isp);
2014
2015 return 0;
2016}
2017
2018static int isp_map_mem_resource(struct platform_device *pdev,
2019 struct isp_device *isp,
2020 enum isp_mem_resources res)
2021{
2022 struct resource *mem;
2023
2024 /* request the mem region for the camera registers */
2025
2026 mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
2027 if (!mem) {
2028 dev_err(isp->dev, "no mem resource?\n");
2029 return -ENODEV;
2030 }
2031
2032 if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
2033 dev_err(isp->dev,
2034 "cannot reserve camera register I/O region\n");
2035 return -ENODEV;
2036 }
2037 isp->mmio_base_phys[res] = mem->start;
2038 isp->mmio_size[res] = resource_size(mem);
2039
2040 /* map the region */
2041 isp->mmio_base[res] = ioremap_nocache(isp->mmio_base_phys[res],
2042 isp->mmio_size[res]);
2043 if (!isp->mmio_base[res]) {
2044 dev_err(isp->dev, "cannot map camera register I/O region\n");
2045 return -ENODEV;
2046 }
2047
2048 return 0;
2049}
2050
2051/*
2052 * isp_probe - Probe ISP platform device
2053 * @pdev: Pointer to ISP platform device
2054 *
2055 * Returns 0 if successful,
2056 * -ENOMEM if no memory available,
2057 * -ENODEV if no platform device resources found
2058 * or no space for remapping registers,
2059 * -EINVAL if couldn't install ISR,
2060 * or clk_get return error value.
2061 */
2062static int __devinit isp_probe(struct platform_device *pdev)
2063{
2064 struct isp_platform_data *pdata = pdev->dev.platform_data;
2065 struct isp_device *isp;
2066 int ret;
2067 int i, m;
2068
2069 if (pdata == NULL)
2070 return -EINVAL;
2071
2072 isp = kzalloc(sizeof(*isp), GFP_KERNEL);
2073 if (!isp) {
2074 dev_err(&pdev->dev, "could not allocate memory\n");
2075 return -ENOMEM;
2076 }
2077
2078 isp->autoidle = autoidle;
2079 isp->platform_cb.set_xclk = isp_set_xclk;
2080
2081 mutex_init(&isp->isp_mutex);
2082 spin_lock_init(&isp->stat_lock);
2083
2084 isp->dev = &pdev->dev;
2085 isp->pdata = pdata;
2086 isp->ref_count = 0;
2087
2088 isp->raw_dmamask = DMA_BIT_MASK(32);
2089 isp->dev->dma_mask = &isp->raw_dmamask;
2090 isp->dev->coherent_dma_mask = DMA_BIT_MASK(32);
2091
2092 platform_set_drvdata(pdev, isp);
2093
2094 /* Regulators */
2095 isp->isp_csiphy1.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY1");
2096 isp->isp_csiphy2.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY2");
2097
2098 /* Clocks */
2099 ret = isp_map_mem_resource(pdev, isp, OMAP3_ISP_IOMEM_MAIN);
2100 if (ret < 0)
2101 goto error;
2102
2103 ret = isp_get_clocks(isp);
2104 if (ret < 0)
2105 goto error;
2106
2107 if (__omap3isp_get(isp, false) == NULL) {
2108 ret = -ENODEV;
2109 goto error;
2110 }
2111
2112 ret = isp_reset(isp);
2113 if (ret < 0)
2114 goto error_isp;
2115
2116 /* Memory resources */
2117 isp->revision = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
2118 dev_info(isp->dev, "Revision %d.%d found\n",
2119 (isp->revision & 0xf0) >> 4, isp->revision & 0x0f);
2120
2121 for (m = 0; m < ARRAY_SIZE(isp_res_maps); m++)
2122 if (isp->revision == isp_res_maps[m].isp_rev)
2123 break;
2124
2125 if (m == ARRAY_SIZE(isp_res_maps)) {
2126 dev_err(isp->dev, "No resource map found for ISP rev %d.%d\n",
2127 (isp->revision & 0xf0) >> 4, isp->revision & 0xf);
2128 ret = -ENODEV;
2129 goto error_isp;
2130 }
2131
2132 for (i = 1; i < OMAP3_ISP_IOMEM_LAST; i++) {
2133 if (isp_res_maps[m].map & 1 << i) {
2134 ret = isp_map_mem_resource(pdev, isp, i);
2135 if (ret)
2136 goto error_isp;
2137 }
2138 }
2139
2140 isp->domain = iommu_domain_alloc(pdev->dev.bus);
2141 if (!isp->domain) {
2142 dev_err(isp->dev, "can't alloc iommu domain\n");
2143 ret = -ENOMEM;
2144 goto error_isp;
2145 }
2146
2147 ret = iommu_attach_device(isp->domain, &pdev->dev);
2148 if (ret) {
2149 dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret);
2150 goto free_domain;
2151 }
2152
2153 /* Interrupt */
2154 isp->irq_num = platform_get_irq(pdev, 0);
2155 if (isp->irq_num <= 0) {
2156 dev_err(isp->dev, "No IRQ resource\n");
2157 ret = -ENODEV;
2158 goto detach_dev;
2159 }
2160
2161 if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) {
2162 dev_err(isp->dev, "Unable to request IRQ\n");
2163 ret = -EINVAL;
2164 goto detach_dev;
2165 }
2166
2167 /* Entities */
2168 ret = isp_initialize_modules(isp);
2169 if (ret < 0)
2170 goto error_irq;
2171
2172 ret = isp_register_entities(isp);
2173 if (ret < 0)
2174 goto error_modules;
2175
2176 isp_core_init(isp, 1);
2177 omap3isp_put(isp);
2178
2179 return 0;
2180
2181error_modules:
2182 isp_cleanup_modules(isp);
2183error_irq:
2184 free_irq(isp->irq_num, isp);
2185detach_dev:
2186 iommu_detach_device(isp->domain, &pdev->dev);
2187free_domain:
2188 iommu_domain_free(isp->domain);
2189error_isp:
2190 omap3isp_put(isp);
2191error:
2192 isp_put_clocks(isp);
2193
2194 for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) {
2195 if (isp->mmio_base[i]) {
2196 iounmap(isp->mmio_base[i]);
2197 isp->mmio_base[i] = NULL;
2198 }
2199
2200 if (isp->mmio_base_phys[i]) {
2201 release_mem_region(isp->mmio_base_phys[i],
2202 isp->mmio_size[i]);
2203 isp->mmio_base_phys[i] = 0;
2204 }
2205 }
2206 regulator_put(isp->isp_csiphy2.vdd);
2207 regulator_put(isp->isp_csiphy1.vdd);
2208 platform_set_drvdata(pdev, NULL);
2209
2210 mutex_destroy(&isp->isp_mutex);
2211 kfree(isp);
2212
2213 return ret;
2214}
2215
2216static const struct dev_pm_ops omap3isp_pm_ops = {
2217 .prepare = isp_pm_prepare,
2218 .suspend = isp_pm_suspend,
2219 .resume = isp_pm_resume,
2220 .complete = isp_pm_complete,
2221};
2222
2223static struct platform_device_id omap3isp_id_table[] = {
2224 { "omap3isp", 0 },
2225 { },
2226};
2227MODULE_DEVICE_TABLE(platform, omap3isp_id_table);
2228
2229static struct platform_driver omap3isp_driver = {
2230 .probe = isp_probe,
2231 .remove = __devexit_p(isp_remove),
2232 .id_table = omap3isp_id_table,
2233 .driver = {
2234 .owner = THIS_MODULE,
2235 .name = "omap3isp",
2236 .pm = &omap3isp_pm_ops,
2237 },
2238};
2239
2240module_platform_driver(omap3isp_driver);
2241
2242MODULE_AUTHOR("Nokia Corporation");
2243MODULE_DESCRIPTION("TI OMAP3 ISP driver");
2244MODULE_LICENSE("GPL");
2245MODULE_VERSION(ISP_VIDEO_DRIVER_VERSION);
diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h
new file mode 100644
index 000000000000..8be7487c326f
--- /dev/null
+++ b/drivers/media/platform/omap3isp/isp.h
@@ -0,0 +1,352 @@
1/*
2 * isp.h
3 *
4 * TI OMAP3 ISP - Core
5 *
6 * Copyright (C) 2009-2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#ifndef OMAP3_ISP_CORE_H
28#define OMAP3_ISP_CORE_H
29
30#include <media/omap3isp.h>
31#include <media/v4l2-device.h>
32#include <linux/device.h>
33#include <linux/io.h>
34#include <linux/platform_device.h>
35#include <linux/wait.h>
36#include <linux/iommu.h>
37#include <plat/iommu.h>
38#include <plat/iovmm.h>
39
40#include "ispstat.h"
41#include "ispccdc.h"
42#include "ispreg.h"
43#include "ispresizer.h"
44#include "isppreview.h"
45#include "ispcsiphy.h"
46#include "ispcsi2.h"
47#include "ispccp2.h"
48
49#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
50
51#define ISP_TOK_TERM 0xFFFFFFFF /*
52 * terminating token for ISP
53 * modules reg list
54 */
55#define to_isp_device(ptr_module) \
56 container_of(ptr_module, struct isp_device, isp_##ptr_module)
57#define to_device(ptr_module) \
58 (to_isp_device(ptr_module)->dev)
59
60enum isp_mem_resources {
61 OMAP3_ISP_IOMEM_MAIN,
62 OMAP3_ISP_IOMEM_CCP2,
63 OMAP3_ISP_IOMEM_CCDC,
64 OMAP3_ISP_IOMEM_HIST,
65 OMAP3_ISP_IOMEM_H3A,
66 OMAP3_ISP_IOMEM_PREV,
67 OMAP3_ISP_IOMEM_RESZ,
68 OMAP3_ISP_IOMEM_SBL,
69 OMAP3_ISP_IOMEM_CSI2A_REGS1,
70 OMAP3_ISP_IOMEM_CSIPHY2,
71 OMAP3_ISP_IOMEM_CSI2A_REGS2,
72 OMAP3_ISP_IOMEM_CSI2C_REGS1,
73 OMAP3_ISP_IOMEM_CSIPHY1,
74 OMAP3_ISP_IOMEM_CSI2C_REGS2,
75 OMAP3_ISP_IOMEM_LAST
76};
77
78enum isp_sbl_resource {
79 OMAP3_ISP_SBL_CSI1_READ = 0x1,
80 OMAP3_ISP_SBL_CSI1_WRITE = 0x2,
81 OMAP3_ISP_SBL_CSI2A_WRITE = 0x4,
82 OMAP3_ISP_SBL_CSI2C_WRITE = 0x8,
83 OMAP3_ISP_SBL_CCDC_LSC_READ = 0x10,
84 OMAP3_ISP_SBL_CCDC_WRITE = 0x20,
85 OMAP3_ISP_SBL_PREVIEW_READ = 0x40,
86 OMAP3_ISP_SBL_PREVIEW_WRITE = 0x80,
87 OMAP3_ISP_SBL_RESIZER_READ = 0x100,
88 OMAP3_ISP_SBL_RESIZER_WRITE = 0x200,
89};
90
91enum isp_subclk_resource {
92 OMAP3_ISP_SUBCLK_CCDC = (1 << 0),
93 OMAP3_ISP_SUBCLK_AEWB = (1 << 1),
94 OMAP3_ISP_SUBCLK_AF = (1 << 2),
95 OMAP3_ISP_SUBCLK_HIST = (1 << 3),
96 OMAP3_ISP_SUBCLK_PREVIEW = (1 << 4),
97 OMAP3_ISP_SUBCLK_RESIZER = (1 << 5),
98};
99
100/* ISP: OMAP 34xx ES 1.0 */
101#define ISP_REVISION_1_0 0x10
102/* ISP2: OMAP 34xx ES 2.0, 2.1 and 3.0 */
103#define ISP_REVISION_2_0 0x20
104/* ISP2P: OMAP 36xx */
105#define ISP_REVISION_15_0 0xF0
106
107/*
108 * struct isp_res_mapping - Map ISP io resources to ISP revision.
109 * @isp_rev: ISP_REVISION_x_x
110 * @map: bitmap for enum isp_mem_resources
111 */
112struct isp_res_mapping {
113 u32 isp_rev;
114 u32 map;
115};
116
117/*
118 * struct isp_reg - Structure for ISP register values.
119 * @reg: 32-bit Register address.
120 * @val: 32-bit Register value.
121 */
122struct isp_reg {
123 enum isp_mem_resources mmio_range;
124 u32 reg;
125 u32 val;
126};
127
128struct isp_platform_callback {
129 u32 (*set_xclk)(struct isp_device *isp, u32 xclk, u8 xclksel);
130 int (*csiphy_config)(struct isp_csiphy *phy,
131 struct isp_csiphy_dphy_cfg *dphy,
132 struct isp_csiphy_lanes_cfg *lanes);
133};
134
135/*
136 * struct isp_device - ISP device structure.
137 * @dev: Device pointer specific to the OMAP3 ISP.
138 * @revision: Stores current ISP module revision.
139 * @irq_num: Currently used IRQ number.
140 * @mmio_base: Array with kernel base addresses for ioremapped ISP register
141 * regions.
142 * @mmio_base_phys: Array with physical L4 bus addresses for ISP register
143 * regions.
144 * @mmio_size: Array with ISP register regions size in bytes.
145 * @raw_dmamask: Raw DMA mask
146 * @stat_lock: Spinlock for handling statistics
147 * @isp_mutex: Mutex for serializing requests to ISP.
148 * @crashed: Bitmask of crashed entities (indexed by entity ID)
149 * @has_context: Context has been saved at least once and can be restored.
150 * @ref_count: Reference count for handling multiple ISP requests.
151 * @cam_ick: Pointer to camera interface clock structure.
152 * @cam_mclk: Pointer to camera functional clock structure.
153 * @dpll4_m5_ck: Pointer to DPLL4 M5 clock structure.
154 * @csi2_fck: Pointer to camera CSI2 complexIO clock structure.
155 * @l3_ick: Pointer to OMAP3 L3 bus interface clock.
156 * @irq: Currently attached ISP ISR callbacks information structure.
157 * @isp_af: Pointer to current settings for ISP AutoFocus SCM.
158 * @isp_hist: Pointer to current settings for ISP Histogram SCM.
159 * @isp_h3a: Pointer to current settings for ISP Auto Exposure and
160 * White Balance SCM.
161 * @isp_res: Pointer to current settings for ISP Resizer.
162 * @isp_prev: Pointer to current settings for ISP Preview.
163 * @isp_ccdc: Pointer to current settings for ISP CCDC.
164 * @iommu: Pointer to requested IOMMU instance for ISP.
165 * @platform_cb: ISP driver callback function pointers for platform code
166 *
167 * This structure is used to store the OMAP ISP Information.
168 */
169struct isp_device {
170 struct v4l2_device v4l2_dev;
171 struct media_device media_dev;
172 struct device *dev;
173 u32 revision;
174
175 /* platform HW resources */
176 struct isp_platform_data *pdata;
177 unsigned int irq_num;
178
179 void __iomem *mmio_base[OMAP3_ISP_IOMEM_LAST];
180 unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_LAST];
181 resource_size_t mmio_size[OMAP3_ISP_IOMEM_LAST];
182
183 u64 raw_dmamask;
184
185 /* ISP Obj */
186 spinlock_t stat_lock; /* common lock for statistic drivers */
187 struct mutex isp_mutex; /* For handling ref_count field */
188 u32 crashed;
189 int has_context;
190 int ref_count;
191 unsigned int autoidle;
192 u32 xclk_divisor[2]; /* Two clocks, a and b. */
193#define ISP_CLK_CAM_ICK 0
194#define ISP_CLK_CAM_MCLK 1
195#define ISP_CLK_DPLL4_M5_CK 2
196#define ISP_CLK_CSI2_FCK 3
197#define ISP_CLK_L3_ICK 4
198 struct clk *clock[5];
199
200 /* ISP modules */
201 struct ispstat isp_af;
202 struct ispstat isp_aewb;
203 struct ispstat isp_hist;
204 struct isp_res_device isp_res;
205 struct isp_prev_device isp_prev;
206 struct isp_ccdc_device isp_ccdc;
207 struct isp_csi2_device isp_csi2a;
208 struct isp_csi2_device isp_csi2c;
209 struct isp_ccp2_device isp_ccp2;
210 struct isp_csiphy isp_csiphy1;
211 struct isp_csiphy isp_csiphy2;
212
213 unsigned int sbl_resources;
214 unsigned int subclk_resources;
215
216 struct iommu_domain *domain;
217
218 struct isp_platform_callback platform_cb;
219};
220
221#define v4l2_dev_to_isp_device(dev) \
222 container_of(dev, struct isp_device, v4l2_dev)
223
224void omap3isp_hist_dma_done(struct isp_device *isp);
225
226void omap3isp_flush(struct isp_device *isp);
227
228int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
229 atomic_t *stopping);
230
231int omap3isp_module_sync_is_stopping(wait_queue_head_t *wait,
232 atomic_t *stopping);
233
234int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
235 enum isp_pipeline_stream_state state);
236void omap3isp_configure_bridge(struct isp_device *isp,
237 enum ccdc_input_entity input,
238 const struct isp_parallel_platform_data *pdata,
239 unsigned int shift, unsigned int bridge);
240
241struct isp_device *omap3isp_get(struct isp_device *isp);
242void omap3isp_put(struct isp_device *isp);
243
244void omap3isp_print_status(struct isp_device *isp);
245
246void omap3isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res);
247void omap3isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res);
248
249void omap3isp_subclk_enable(struct isp_device *isp,
250 enum isp_subclk_resource res);
251void omap3isp_subclk_disable(struct isp_device *isp,
252 enum isp_subclk_resource res);
253
254int omap3isp_pipeline_pm_use(struct media_entity *entity, int use);
255
256int omap3isp_register_entities(struct platform_device *pdev,
257 struct v4l2_device *v4l2_dev);
258void omap3isp_unregister_entities(struct platform_device *pdev);
259
260/*
261 * isp_reg_readl - Read value of an OMAP3 ISP register
262 * @dev: Device pointer specific to the OMAP3 ISP.
263 * @isp_mmio_range: Range to which the register offset refers to.
264 * @reg_offset: Register offset to read from.
265 *
266 * Returns an unsigned 32 bit value with the required register contents.
267 */
268static inline
269u32 isp_reg_readl(struct isp_device *isp, enum isp_mem_resources isp_mmio_range,
270 u32 reg_offset)
271{
272 return __raw_readl(isp->mmio_base[isp_mmio_range] + reg_offset);
273}
274
275/*
276 * isp_reg_writel - Write value to an OMAP3 ISP register
277 * @dev: Device pointer specific to the OMAP3 ISP.
278 * @reg_value: 32 bit value to write to the register.
279 * @isp_mmio_range: Range to which the register offset refers to.
280 * @reg_offset: Register offset to write into.
281 */
282static inline
283void isp_reg_writel(struct isp_device *isp, u32 reg_value,
284 enum isp_mem_resources isp_mmio_range, u32 reg_offset)
285{
286 __raw_writel(reg_value, isp->mmio_base[isp_mmio_range] + reg_offset);
287}
288
289/*
290 * isp_reg_and - Clear individual bits in an OMAP3 ISP register
291 * @dev: Device pointer specific to the OMAP3 ISP.
292 * @mmio_range: Range to which the register offset refers to.
293 * @reg: Register offset to work on.
294 * @clr_bits: 32 bit value which would be cleared in the register.
295 */
296static inline
297void isp_reg_clr(struct isp_device *isp, enum isp_mem_resources mmio_range,
298 u32 reg, u32 clr_bits)
299{
300 u32 v = isp_reg_readl(isp, mmio_range, reg);
301
302 isp_reg_writel(isp, v & ~clr_bits, mmio_range, reg);
303}
304
305/*
306 * isp_reg_set - Set individual bits in an OMAP3 ISP register
307 * @dev: Device pointer specific to the OMAP3 ISP.
308 * @mmio_range: Range to which the register offset refers to.
309 * @reg: Register offset to work on.
310 * @set_bits: 32 bit value which would be set in the register.
311 */
312static inline
313void isp_reg_set(struct isp_device *isp, enum isp_mem_resources mmio_range,
314 u32 reg, u32 set_bits)
315{
316 u32 v = isp_reg_readl(isp, mmio_range, reg);
317
318 isp_reg_writel(isp, v | set_bits, mmio_range, reg);
319}
320
321/*
322 * isp_reg_clr_set - Clear and set invidial bits in an OMAP3 ISP register
323 * @dev: Device pointer specific to the OMAP3 ISP.
324 * @mmio_range: Range to which the register offset refers to.
325 * @reg: Register offset to work on.
326 * @clr_bits: 32 bit value which would be cleared in the register.
327 * @set_bits: 32 bit value which would be set in the register.
328 *
329 * The clear operation is done first, and then the set operation.
330 */
331static inline
332void isp_reg_clr_set(struct isp_device *isp, enum isp_mem_resources mmio_range,
333 u32 reg, u32 clr_bits, u32 set_bits)
334{
335 u32 v = isp_reg_readl(isp, mmio_range, reg);
336
337 isp_reg_writel(isp, (v & ~clr_bits) | set_bits, mmio_range, reg);
338}
339
340static inline enum v4l2_buf_type
341isp_pad_buffer_type(const struct v4l2_subdev *subdev, int pad)
342{
343 if (pad >= subdev->entity.num_pads)
344 return 0;
345
346 if (subdev->entity.pads[pad].flags & MEDIA_PAD_FL_SINK)
347 return V4L2_BUF_TYPE_VIDEO_OUTPUT;
348 else
349 return V4L2_BUF_TYPE_VIDEO_CAPTURE;
350}
351
352#endif /* OMAP3_ISP_CORE_H */
diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
new file mode 100644
index 000000000000..60181ab96063
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -0,0 +1,2583 @@
1/*
2 * ispccdc.c
3 *
4 * TI OMAP3 ISP - CCDC module
5 *
6 * Copyright (C) 2009-2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#include <linux/module.h>
28#include <linux/uaccess.h>
29#include <linux/delay.h>
30#include <linux/device.h>
31#include <linux/dma-mapping.h>
32#include <linux/mm.h>
33#include <linux/sched.h>
34#include <linux/slab.h>
35#include <media/v4l2-event.h>
36
37#include "isp.h"
38#include "ispreg.h"
39#include "ispccdc.h"
40
41#define CCDC_MIN_WIDTH 32
42#define CCDC_MIN_HEIGHT 32
43
44static struct v4l2_mbus_framefmt *
45__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
46 unsigned int pad, enum v4l2_subdev_format_whence which);
47
48static const unsigned int ccdc_fmts[] = {
49 V4L2_MBUS_FMT_Y8_1X8,
50 V4L2_MBUS_FMT_Y10_1X10,
51 V4L2_MBUS_FMT_Y12_1X12,
52 V4L2_MBUS_FMT_SGRBG8_1X8,
53 V4L2_MBUS_FMT_SRGGB8_1X8,
54 V4L2_MBUS_FMT_SBGGR8_1X8,
55 V4L2_MBUS_FMT_SGBRG8_1X8,
56 V4L2_MBUS_FMT_SGRBG10_1X10,
57 V4L2_MBUS_FMT_SRGGB10_1X10,
58 V4L2_MBUS_FMT_SBGGR10_1X10,
59 V4L2_MBUS_FMT_SGBRG10_1X10,
60 V4L2_MBUS_FMT_SGRBG12_1X12,
61 V4L2_MBUS_FMT_SRGGB12_1X12,
62 V4L2_MBUS_FMT_SBGGR12_1X12,
63 V4L2_MBUS_FMT_SGBRG12_1X12,
64 V4L2_MBUS_FMT_YUYV8_2X8,
65 V4L2_MBUS_FMT_UYVY8_2X8,
66};
67
68/*
69 * ccdc_print_status - Print current CCDC Module register values.
70 * @ccdc: Pointer to ISP CCDC device.
71 *
72 * Also prints other debug information stored in the CCDC module.
73 */
74#define CCDC_PRINT_REGISTER(isp, name)\
75 dev_dbg(isp->dev, "###CCDC " #name "=0x%08x\n", \
76 isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_##name))
77
78static void ccdc_print_status(struct isp_ccdc_device *ccdc)
79{
80 struct isp_device *isp = to_isp_device(ccdc);
81
82 dev_dbg(isp->dev, "-------------CCDC Register dump-------------\n");
83
84 CCDC_PRINT_REGISTER(isp, PCR);
85 CCDC_PRINT_REGISTER(isp, SYN_MODE);
86 CCDC_PRINT_REGISTER(isp, HD_VD_WID);
87 CCDC_PRINT_REGISTER(isp, PIX_LINES);
88 CCDC_PRINT_REGISTER(isp, HORZ_INFO);
89 CCDC_PRINT_REGISTER(isp, VERT_START);
90 CCDC_PRINT_REGISTER(isp, VERT_LINES);
91 CCDC_PRINT_REGISTER(isp, CULLING);
92 CCDC_PRINT_REGISTER(isp, HSIZE_OFF);
93 CCDC_PRINT_REGISTER(isp, SDOFST);
94 CCDC_PRINT_REGISTER(isp, SDR_ADDR);
95 CCDC_PRINT_REGISTER(isp, CLAMP);
96 CCDC_PRINT_REGISTER(isp, DCSUB);
97 CCDC_PRINT_REGISTER(isp, COLPTN);
98 CCDC_PRINT_REGISTER(isp, BLKCMP);
99 CCDC_PRINT_REGISTER(isp, FPC);
100 CCDC_PRINT_REGISTER(isp, FPC_ADDR);
101 CCDC_PRINT_REGISTER(isp, VDINT);
102 CCDC_PRINT_REGISTER(isp, ALAW);
103 CCDC_PRINT_REGISTER(isp, REC656IF);
104 CCDC_PRINT_REGISTER(isp, CFG);
105 CCDC_PRINT_REGISTER(isp, FMTCFG);
106 CCDC_PRINT_REGISTER(isp, FMT_HORZ);
107 CCDC_PRINT_REGISTER(isp, FMT_VERT);
108 CCDC_PRINT_REGISTER(isp, PRGEVEN0);
109 CCDC_PRINT_REGISTER(isp, PRGEVEN1);
110 CCDC_PRINT_REGISTER(isp, PRGODD0);
111 CCDC_PRINT_REGISTER(isp, PRGODD1);
112 CCDC_PRINT_REGISTER(isp, VP_OUT);
113 CCDC_PRINT_REGISTER(isp, LSC_CONFIG);
114 CCDC_PRINT_REGISTER(isp, LSC_INITIAL);
115 CCDC_PRINT_REGISTER(isp, LSC_TABLE_BASE);
116 CCDC_PRINT_REGISTER(isp, LSC_TABLE_OFFSET);
117
118 dev_dbg(isp->dev, "--------------------------------------------\n");
119}
120
121/*
122 * omap3isp_ccdc_busy - Get busy state of the CCDC.
123 * @ccdc: Pointer to ISP CCDC device.
124 */
125int omap3isp_ccdc_busy(struct isp_ccdc_device *ccdc)
126{
127 struct isp_device *isp = to_isp_device(ccdc);
128
129 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
130 ISPCCDC_PCR_BUSY;
131}
132
133/* -----------------------------------------------------------------------------
134 * Lens Shading Compensation
135 */
136
137/*
138 * ccdc_lsc_validate_config - Check that LSC configuration is valid.
139 * @ccdc: Pointer to ISP CCDC device.
140 * @lsc_cfg: the LSC configuration to check.
141 *
142 * Returns 0 if the LSC configuration is valid, or -EINVAL if invalid.
143 */
144static int ccdc_lsc_validate_config(struct isp_ccdc_device *ccdc,
145 struct omap3isp_ccdc_lsc_config *lsc_cfg)
146{
147 struct isp_device *isp = to_isp_device(ccdc);
148 struct v4l2_mbus_framefmt *format;
149 unsigned int paxel_width, paxel_height;
150 unsigned int paxel_shift_x, paxel_shift_y;
151 unsigned int min_width, min_height, min_size;
152 unsigned int input_width, input_height;
153
154 paxel_shift_x = lsc_cfg->gain_mode_m;
155 paxel_shift_y = lsc_cfg->gain_mode_n;
156
157 if ((paxel_shift_x < 2) || (paxel_shift_x > 6) ||
158 (paxel_shift_y < 2) || (paxel_shift_y > 6)) {
159 dev_dbg(isp->dev, "CCDC: LSC: Invalid paxel size\n");
160 return -EINVAL;
161 }
162
163 if (lsc_cfg->offset & 3) {
164 dev_dbg(isp->dev, "CCDC: LSC: Offset must be a multiple of "
165 "4\n");
166 return -EINVAL;
167 }
168
169 if ((lsc_cfg->initial_x & 1) || (lsc_cfg->initial_y & 1)) {
170 dev_dbg(isp->dev, "CCDC: LSC: initial_x and y must be even\n");
171 return -EINVAL;
172 }
173
174 format = __ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
175 V4L2_SUBDEV_FORMAT_ACTIVE);
176 input_width = format->width;
177 input_height = format->height;
178
179 /* Calculate minimum bytesize for validation */
180 paxel_width = 1 << paxel_shift_x;
181 min_width = ((input_width + lsc_cfg->initial_x + paxel_width - 1)
182 >> paxel_shift_x) + 1;
183
184 paxel_height = 1 << paxel_shift_y;
185 min_height = ((input_height + lsc_cfg->initial_y + paxel_height - 1)
186 >> paxel_shift_y) + 1;
187
188 min_size = 4 * min_width * min_height;
189 if (min_size > lsc_cfg->size) {
190 dev_dbg(isp->dev, "CCDC: LSC: too small table\n");
191 return -EINVAL;
192 }
193 if (lsc_cfg->offset < (min_width * 4)) {
194 dev_dbg(isp->dev, "CCDC: LSC: Offset is too small\n");
195 return -EINVAL;
196 }
197 if ((lsc_cfg->size / lsc_cfg->offset) < min_height) {
198 dev_dbg(isp->dev, "CCDC: LSC: Wrong size/offset combination\n");
199 return -EINVAL;
200 }
201 return 0;
202}
203
204/*
205 * ccdc_lsc_program_table - Program Lens Shading Compensation table address.
206 * @ccdc: Pointer to ISP CCDC device.
207 */
208static void ccdc_lsc_program_table(struct isp_ccdc_device *ccdc, u32 addr)
209{
210 isp_reg_writel(to_isp_device(ccdc), addr,
211 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
212}
213
214/*
215 * ccdc_lsc_setup_regs - Configures the lens shading compensation module
216 * @ccdc: Pointer to ISP CCDC device.
217 */
218static void ccdc_lsc_setup_regs(struct isp_ccdc_device *ccdc,
219 struct omap3isp_ccdc_lsc_config *cfg)
220{
221 struct isp_device *isp = to_isp_device(ccdc);
222 int reg;
223
224 isp_reg_writel(isp, cfg->offset, OMAP3_ISP_IOMEM_CCDC,
225 ISPCCDC_LSC_TABLE_OFFSET);
226
227 reg = 0;
228 reg |= cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT;
229 reg |= cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT;
230 reg |= cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT;
231 isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
232
233 reg = 0;
234 reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
235 reg |= cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT;
236 reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
237 reg |= cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT;
238 isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC,
239 ISPCCDC_LSC_INITIAL);
240}
241
242static int ccdc_lsc_wait_prefetch(struct isp_ccdc_device *ccdc)
243{
244 struct isp_device *isp = to_isp_device(ccdc);
245 unsigned int wait;
246
247 isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ,
248 OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
249
250 /* timeout 1 ms */
251 for (wait = 0; wait < 1000; wait++) {
252 if (isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS) &
253 IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ) {
254 isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ,
255 OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
256 return 0;
257 }
258
259 rmb();
260 udelay(1);
261 }
262
263 return -ETIMEDOUT;
264}
265
266/*
267 * __ccdc_lsc_enable - Enables/Disables the Lens Shading Compensation module.
268 * @ccdc: Pointer to ISP CCDC device.
269 * @enable: 0 Disables LSC, 1 Enables LSC.
270 */
271static int __ccdc_lsc_enable(struct isp_ccdc_device *ccdc, int enable)
272{
273 struct isp_device *isp = to_isp_device(ccdc);
274 const struct v4l2_mbus_framefmt *format =
275 __ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
276 V4L2_SUBDEV_FORMAT_ACTIVE);
277
278 if ((format->code != V4L2_MBUS_FMT_SGRBG10_1X10) &&
279 (format->code != V4L2_MBUS_FMT_SRGGB10_1X10) &&
280 (format->code != V4L2_MBUS_FMT_SBGGR10_1X10) &&
281 (format->code != V4L2_MBUS_FMT_SGBRG10_1X10))
282 return -EINVAL;
283
284 if (enable)
285 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_LSC_READ);
286
287 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG,
288 ISPCCDC_LSC_ENABLE, enable ? ISPCCDC_LSC_ENABLE : 0);
289
290 if (enable) {
291 if (ccdc_lsc_wait_prefetch(ccdc) < 0) {
292 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC,
293 ISPCCDC_LSC_CONFIG, ISPCCDC_LSC_ENABLE);
294 ccdc->lsc.state = LSC_STATE_STOPPED;
295 dev_warn(to_device(ccdc), "LSC prefecth timeout\n");
296 return -ETIMEDOUT;
297 }
298 ccdc->lsc.state = LSC_STATE_RUNNING;
299 } else {
300 ccdc->lsc.state = LSC_STATE_STOPPING;
301 }
302
303 return 0;
304}
305
306static int ccdc_lsc_busy(struct isp_ccdc_device *ccdc)
307{
308 struct isp_device *isp = to_isp_device(ccdc);
309
310 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG) &
311 ISPCCDC_LSC_BUSY;
312}
313
314/* __ccdc_lsc_configure - Apply a new configuration to the LSC engine
315 * @ccdc: Pointer to ISP CCDC device
316 * @req: New configuration request
317 *
318 * context: in_interrupt()
319 */
320static int __ccdc_lsc_configure(struct isp_ccdc_device *ccdc,
321 struct ispccdc_lsc_config_req *req)
322{
323 if (!req->enable)
324 return -EINVAL;
325
326 if (ccdc_lsc_validate_config(ccdc, &req->config) < 0) {
327 dev_dbg(to_device(ccdc), "Discard LSC configuration\n");
328 return -EINVAL;
329 }
330
331 if (ccdc_lsc_busy(ccdc))
332 return -EBUSY;
333
334 ccdc_lsc_setup_regs(ccdc, &req->config);
335 ccdc_lsc_program_table(ccdc, req->table);
336 return 0;
337}
338
339/*
340 * ccdc_lsc_error_handler - Handle LSC prefetch error scenario.
341 * @ccdc: Pointer to ISP CCDC device.
342 *
343 * Disables LSC, and defers enablement to shadow registers update time.
344 */
345static void ccdc_lsc_error_handler(struct isp_ccdc_device *ccdc)
346{
347 struct isp_device *isp = to_isp_device(ccdc);
348 /*
349 * From OMAP3 TRM: When this event is pending, the module
350 * goes into transparent mode (output =input). Normal
351 * operation can be resumed at the start of the next frame
352 * after:
353 * 1) Clearing this event
354 * 2) Disabling the LSC module
355 * 3) Enabling it
356 */
357 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG,
358 ISPCCDC_LSC_ENABLE);
359 ccdc->lsc.state = LSC_STATE_STOPPED;
360}
361
362static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc,
363 struct ispccdc_lsc_config_req *req)
364{
365 struct isp_device *isp = to_isp_device(ccdc);
366
367 if (req == NULL)
368 return;
369
370 if (req->iovm)
371 dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
372 req->iovm->sgt->nents, DMA_TO_DEVICE);
373 if (req->table)
374 omap_iommu_vfree(isp->domain, isp->dev, req->table);
375 kfree(req);
376}
377
378static void ccdc_lsc_free_queue(struct isp_ccdc_device *ccdc,
379 struct list_head *queue)
380{
381 struct ispccdc_lsc_config_req *req, *n;
382 unsigned long flags;
383
384 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
385 list_for_each_entry_safe(req, n, queue, list) {
386 list_del(&req->list);
387 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
388 ccdc_lsc_free_request(ccdc, req);
389 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
390 }
391 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
392}
393
394static void ccdc_lsc_free_table_work(struct work_struct *work)
395{
396 struct isp_ccdc_device *ccdc;
397 struct ispccdc_lsc *lsc;
398
399 lsc = container_of(work, struct ispccdc_lsc, table_work);
400 ccdc = container_of(lsc, struct isp_ccdc_device, lsc);
401
402 ccdc_lsc_free_queue(ccdc, &lsc->free_queue);
403}
404
405/*
406 * ccdc_lsc_config - Configure the LSC module from a userspace request
407 *
408 * Store the request LSC configuration in the LSC engine request pointer. The
409 * configuration will be applied to the hardware when the CCDC will be enabled,
410 * or at the next LSC interrupt if the CCDC is already running.
411 */
412static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
413 struct omap3isp_ccdc_update_config *config)
414{
415 struct isp_device *isp = to_isp_device(ccdc);
416 struct ispccdc_lsc_config_req *req;
417 unsigned long flags;
418 void *table;
419 u16 update;
420 int ret;
421
422 update = config->update &
423 (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC);
424 if (!update)
425 return 0;
426
427 if (update != (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC)) {
428 dev_dbg(to_device(ccdc), "%s: Both LSC configuration and table "
429 "need to be supplied\n", __func__);
430 return -EINVAL;
431 }
432
433 req = kzalloc(sizeof(*req), GFP_KERNEL);
434 if (req == NULL)
435 return -ENOMEM;
436
437 if (config->flag & OMAP3ISP_CCDC_CONFIG_LSC) {
438 if (copy_from_user(&req->config, config->lsc_cfg,
439 sizeof(req->config))) {
440 ret = -EFAULT;
441 goto done;
442 }
443
444 req->enable = 1;
445
446 req->table = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
447 req->config.size, IOMMU_FLAG);
448 if (IS_ERR_VALUE(req->table)) {
449 req->table = 0;
450 ret = -ENOMEM;
451 goto done;
452 }
453
454 req->iovm = omap_find_iovm_area(isp->dev, req->table);
455 if (req->iovm == NULL) {
456 ret = -ENOMEM;
457 goto done;
458 }
459
460 if (!dma_map_sg(isp->dev, req->iovm->sgt->sgl,
461 req->iovm->sgt->nents, DMA_TO_DEVICE)) {
462 ret = -ENOMEM;
463 req->iovm = NULL;
464 goto done;
465 }
466
467 dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl,
468 req->iovm->sgt->nents, DMA_TO_DEVICE);
469
470 table = omap_da_to_va(isp->dev, req->table);
471 if (copy_from_user(table, config->lsc, req->config.size)) {
472 ret = -EFAULT;
473 goto done;
474 }
475
476 dma_sync_sg_for_device(isp->dev, req->iovm->sgt->sgl,
477 req->iovm->sgt->nents, DMA_TO_DEVICE);
478 }
479
480 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
481 if (ccdc->lsc.request) {
482 list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue);
483 schedule_work(&ccdc->lsc.table_work);
484 }
485 ccdc->lsc.request = req;
486 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
487
488 ret = 0;
489
490done:
491 if (ret < 0)
492 ccdc_lsc_free_request(ccdc, req);
493
494 return ret;
495}
496
497static inline int ccdc_lsc_is_configured(struct isp_ccdc_device *ccdc)
498{
499 unsigned long flags;
500
501 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
502 if (ccdc->lsc.active) {
503 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
504 return 1;
505 }
506 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
507 return 0;
508}
509
510static int ccdc_lsc_enable(struct isp_ccdc_device *ccdc)
511{
512 struct ispccdc_lsc *lsc = &ccdc->lsc;
513
514 if (lsc->state != LSC_STATE_STOPPED)
515 return -EINVAL;
516
517 if (lsc->active) {
518 list_add_tail(&lsc->active->list, &lsc->free_queue);
519 lsc->active = NULL;
520 }
521
522 if (__ccdc_lsc_configure(ccdc, lsc->request) < 0) {
523 omap3isp_sbl_disable(to_isp_device(ccdc),
524 OMAP3_ISP_SBL_CCDC_LSC_READ);
525 list_add_tail(&lsc->request->list, &lsc->free_queue);
526 lsc->request = NULL;
527 goto done;
528 }
529
530 lsc->active = lsc->request;
531 lsc->request = NULL;
532 __ccdc_lsc_enable(ccdc, 1);
533
534done:
535 if (!list_empty(&lsc->free_queue))
536 schedule_work(&lsc->table_work);
537
538 return 0;
539}
540
541/* -----------------------------------------------------------------------------
542 * Parameters configuration
543 */
544
545/*
546 * ccdc_configure_clamp - Configure optical-black or digital clamping
547 * @ccdc: Pointer to ISP CCDC device.
548 *
549 * The CCDC performs either optical-black or digital clamp. Configure and enable
550 * the selected clamp method.
551 */
552static void ccdc_configure_clamp(struct isp_ccdc_device *ccdc)
553{
554 struct isp_device *isp = to_isp_device(ccdc);
555 u32 clamp;
556
557 if (ccdc->obclamp) {
558 clamp = ccdc->clamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
559 clamp |= ccdc->clamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
560 clamp |= ccdc->clamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
561 clamp |= ccdc->clamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
562 isp_reg_writel(isp, clamp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP);
563 } else {
564 isp_reg_writel(isp, ccdc->clamp.dcsubval,
565 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB);
566 }
567
568 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
569 ISPCCDC_CLAMP_CLAMPEN,
570 ccdc->obclamp ? ISPCCDC_CLAMP_CLAMPEN : 0);
571}
572
573/*
574 * ccdc_configure_fpc - Configure Faulty Pixel Correction
575 * @ccdc: Pointer to ISP CCDC device.
576 */
577static void ccdc_configure_fpc(struct isp_ccdc_device *ccdc)
578{
579 struct isp_device *isp = to_isp_device(ccdc);
580
581 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, ISPCCDC_FPC_FPCEN);
582
583 if (!ccdc->fpc_en)
584 return;
585
586 isp_reg_writel(isp, ccdc->fpc.fpcaddr, OMAP3_ISP_IOMEM_CCDC,
587 ISPCCDC_FPC_ADDR);
588 /* The FPNUM field must be set before enabling FPC. */
589 isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
590 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
591 isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT) |
592 ISPCCDC_FPC_FPCEN, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
593}
594
595/*
596 * ccdc_configure_black_comp - Configure Black Level Compensation.
597 * @ccdc: Pointer to ISP CCDC device.
598 */
599static void ccdc_configure_black_comp(struct isp_ccdc_device *ccdc)
600{
601 struct isp_device *isp = to_isp_device(ccdc);
602 u32 blcomp;
603
604 blcomp = ccdc->blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
605 blcomp |= ccdc->blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
606 blcomp |= ccdc->blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
607 blcomp |= ccdc->blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
608
609 isp_reg_writel(isp, blcomp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP);
610}
611
612/*
613 * ccdc_configure_lpf - Configure Low-Pass Filter (LPF).
614 * @ccdc: Pointer to ISP CCDC device.
615 */
616static void ccdc_configure_lpf(struct isp_ccdc_device *ccdc)
617{
618 struct isp_device *isp = to_isp_device(ccdc);
619
620 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
621 ISPCCDC_SYN_MODE_LPF,
622 ccdc->lpf ? ISPCCDC_SYN_MODE_LPF : 0);
623}
624
625/*
626 * ccdc_configure_alaw - Configure A-law compression.
627 * @ccdc: Pointer to ISP CCDC device.
628 */
629static void ccdc_configure_alaw(struct isp_ccdc_device *ccdc)
630{
631 struct isp_device *isp = to_isp_device(ccdc);
632 const struct isp_format_info *info;
633 u32 alaw = 0;
634
635 info = omap3isp_video_format_info(ccdc->formats[CCDC_PAD_SINK].code);
636
637 switch (info->width) {
638 case 8:
639 return;
640
641 case 10:
642 alaw = ISPCCDC_ALAW_GWDI_9_0;
643 break;
644 case 11:
645 alaw = ISPCCDC_ALAW_GWDI_10_1;
646 break;
647 case 12:
648 alaw = ISPCCDC_ALAW_GWDI_11_2;
649 break;
650 case 13:
651 alaw = ISPCCDC_ALAW_GWDI_12_3;
652 break;
653 }
654
655 if (ccdc->alaw)
656 alaw |= ISPCCDC_ALAW_CCDTBL;
657
658 isp_reg_writel(isp, alaw, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
659}
660
661/*
662 * ccdc_config_imgattr - Configure sensor image specific attributes.
663 * @ccdc: Pointer to ISP CCDC device.
664 * @colptn: Color pattern of the sensor.
665 */
666static void ccdc_config_imgattr(struct isp_ccdc_device *ccdc, u32 colptn)
667{
668 struct isp_device *isp = to_isp_device(ccdc);
669
670 isp_reg_writel(isp, colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
671}
672
673/*
674 * ccdc_config - Set CCDC configuration from userspace
675 * @ccdc: Pointer to ISP CCDC device.
676 * @userspace_add: Structure containing CCDC configuration sent from userspace.
677 *
678 * Returns 0 if successful, -EINVAL if the pointer to the configuration
679 * structure is null, or the copy_from_user function fails to copy user space
680 * memory to kernel space memory.
681 */
682static int ccdc_config(struct isp_ccdc_device *ccdc,
683 struct omap3isp_ccdc_update_config *ccdc_struct)
684{
685 struct isp_device *isp = to_isp_device(ccdc);
686 unsigned long flags;
687
688 spin_lock_irqsave(&ccdc->lock, flags);
689 ccdc->shadow_update = 1;
690 spin_unlock_irqrestore(&ccdc->lock, flags);
691
692 if (OMAP3ISP_CCDC_ALAW & ccdc_struct->update) {
693 ccdc->alaw = !!(OMAP3ISP_CCDC_ALAW & ccdc_struct->flag);
694 ccdc->update |= OMAP3ISP_CCDC_ALAW;
695 }
696
697 if (OMAP3ISP_CCDC_LPF & ccdc_struct->update) {
698 ccdc->lpf = !!(OMAP3ISP_CCDC_LPF & ccdc_struct->flag);
699 ccdc->update |= OMAP3ISP_CCDC_LPF;
700 }
701
702 if (OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->update) {
703 if (copy_from_user(&ccdc->clamp, ccdc_struct->bclamp,
704 sizeof(ccdc->clamp))) {
705 ccdc->shadow_update = 0;
706 return -EFAULT;
707 }
708
709 ccdc->obclamp = !!(OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->flag);
710 ccdc->update |= OMAP3ISP_CCDC_BLCLAMP;
711 }
712
713 if (OMAP3ISP_CCDC_BCOMP & ccdc_struct->update) {
714 if (copy_from_user(&ccdc->blcomp, ccdc_struct->blcomp,
715 sizeof(ccdc->blcomp))) {
716 ccdc->shadow_update = 0;
717 return -EFAULT;
718 }
719
720 ccdc->update |= OMAP3ISP_CCDC_BCOMP;
721 }
722
723 ccdc->shadow_update = 0;
724
725 if (OMAP3ISP_CCDC_FPC & ccdc_struct->update) {
726 u32 table_old = 0;
727 u32 table_new;
728 u32 size;
729
730 if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED)
731 return -EBUSY;
732
733 ccdc->fpc_en = !!(OMAP3ISP_CCDC_FPC & ccdc_struct->flag);
734
735 if (ccdc->fpc_en) {
736 if (copy_from_user(&ccdc->fpc, ccdc_struct->fpc,
737 sizeof(ccdc->fpc)))
738 return -EFAULT;
739
740 /*
741 * table_new must be 64-bytes aligned, but it's
742 * already done by omap_iommu_vmalloc().
743 */
744 size = ccdc->fpc.fpnum * 4;
745 table_new = omap_iommu_vmalloc(isp->domain, isp->dev,
746 0, size, IOMMU_FLAG);
747 if (IS_ERR_VALUE(table_new))
748 return -ENOMEM;
749
750 if (copy_from_user(omap_da_to_va(isp->dev, table_new),
751 (__force void __user *)
752 ccdc->fpc.fpcaddr, size)) {
753 omap_iommu_vfree(isp->domain, isp->dev,
754 table_new);
755 return -EFAULT;
756 }
757
758 table_old = ccdc->fpc.fpcaddr;
759 ccdc->fpc.fpcaddr = table_new;
760 }
761
762 ccdc_configure_fpc(ccdc);
763 if (table_old != 0)
764 omap_iommu_vfree(isp->domain, isp->dev, table_old);
765 }
766
767 return ccdc_lsc_config(ccdc, ccdc_struct);
768}
769
770static void ccdc_apply_controls(struct isp_ccdc_device *ccdc)
771{
772 if (ccdc->update & OMAP3ISP_CCDC_ALAW) {
773 ccdc_configure_alaw(ccdc);
774 ccdc->update &= ~OMAP3ISP_CCDC_ALAW;
775 }
776
777 if (ccdc->update & OMAP3ISP_CCDC_LPF) {
778 ccdc_configure_lpf(ccdc);
779 ccdc->update &= ~OMAP3ISP_CCDC_LPF;
780 }
781
782 if (ccdc->update & OMAP3ISP_CCDC_BLCLAMP) {
783 ccdc_configure_clamp(ccdc);
784 ccdc->update &= ~OMAP3ISP_CCDC_BLCLAMP;
785 }
786
787 if (ccdc->update & OMAP3ISP_CCDC_BCOMP) {
788 ccdc_configure_black_comp(ccdc);
789 ccdc->update &= ~OMAP3ISP_CCDC_BCOMP;
790 }
791}
792
793/*
794 * omap3isp_ccdc_restore_context - Restore values of the CCDC module registers
795 * @dev: Pointer to ISP device
796 */
797void omap3isp_ccdc_restore_context(struct isp_device *isp)
798{
799 struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
800
801 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC);
802
803 ccdc->update = OMAP3ISP_CCDC_ALAW | OMAP3ISP_CCDC_LPF
804 | OMAP3ISP_CCDC_BLCLAMP | OMAP3ISP_CCDC_BCOMP;
805 ccdc_apply_controls(ccdc);
806 ccdc_configure_fpc(ccdc);
807}
808
809/* -----------------------------------------------------------------------------
810 * Format- and pipeline-related configuration helpers
811 */
812
813/*
814 * ccdc_config_vp - Configure the Video Port.
815 * @ccdc: Pointer to ISP CCDC device.
816 */
817static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
818{
819 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
820 struct isp_device *isp = to_isp_device(ccdc);
821 const struct isp_format_info *info;
822 unsigned long l3_ick = pipe->l3_ick;
823 unsigned int max_div = isp->revision == ISP_REVISION_15_0 ? 64 : 8;
824 unsigned int div = 0;
825 u32 fmtcfg_vp;
826
827 fmtcfg_vp = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG)
828 & ~(ISPCCDC_FMTCFG_VPIN_MASK | ISPCCDC_FMTCFG_VPIF_FRQ_MASK);
829
830 info = omap3isp_video_format_info(ccdc->formats[CCDC_PAD_SINK].code);
831
832 switch (info->width) {
833 case 8:
834 case 10:
835 fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
836 break;
837 case 11:
838 fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
839 break;
840 case 12:
841 fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
842 break;
843 case 13:
844 fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
845 break;
846 }
847
848 if (pipe->input)
849 div = DIV_ROUND_UP(l3_ick, pipe->max_rate);
850 else if (pipe->external_rate)
851 div = l3_ick / pipe->external_rate;
852
853 div = clamp(div, 2U, max_div);
854 fmtcfg_vp |= (div - 2) << ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT;
855
856 isp_reg_writel(isp, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
857}
858
859/*
860 * ccdc_enable_vp - Enable Video Port.
861 * @ccdc: Pointer to ISP CCDC device.
862 * @enable: 0 Disables VP, 1 Enables VP
863 *
864 * This is needed for outputting image to Preview, H3A and HIST ISP submodules.
865 */
866static void ccdc_enable_vp(struct isp_ccdc_device *ccdc, u8 enable)
867{
868 struct isp_device *isp = to_isp_device(ccdc);
869
870 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
871 ISPCCDC_FMTCFG_VPEN, enable ? ISPCCDC_FMTCFG_VPEN : 0);
872}
873
874/*
875 * ccdc_config_outlineoffset - Configure memory saving output line offset
876 * @ccdc: Pointer to ISP CCDC device.
877 * @offset: Address offset to start a new line. Must be twice the
878 * Output width and aligned on 32 byte boundary
879 * @oddeven: Specifies the odd/even line pattern to be chosen to store the
880 * output.
881 * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
882 *
883 * - Configures the output line offset when stored in memory
884 * - Sets the odd/even line pattern to store the output
885 * (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
886 * - Configures the number of even and odd line fields in case of rearranging
887 * the lines.
888 */
889static void ccdc_config_outlineoffset(struct isp_ccdc_device *ccdc,
890 u32 offset, u8 oddeven, u8 numlines)
891{
892 struct isp_device *isp = to_isp_device(ccdc);
893
894 isp_reg_writel(isp, offset & 0xffff,
895 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF);
896
897 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
898 ISPCCDC_SDOFST_FINV);
899
900 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
901 ISPCCDC_SDOFST_FOFST_4L);
902
903 switch (oddeven) {
904 case EVENEVEN:
905 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
906 (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
907 break;
908 case ODDEVEN:
909 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
910 (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
911 break;
912 case EVENODD:
913 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
914 (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
915 break;
916 case ODDODD:
917 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
918 (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
919 break;
920 default:
921 break;
922 }
923}
924
925/*
926 * ccdc_set_outaddr - Set memory address to save output image
927 * @ccdc: Pointer to ISP CCDC device.
928 * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
929 *
930 * Sets the memory address where the output will be saved.
931 */
932static void ccdc_set_outaddr(struct isp_ccdc_device *ccdc, u32 addr)
933{
934 struct isp_device *isp = to_isp_device(ccdc);
935
936 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR);
937}
938
939/*
940 * omap3isp_ccdc_max_rate - Calculate maximum input data rate based on the input
941 * @ccdc: Pointer to ISP CCDC device.
942 * @max_rate: Maximum calculated data rate.
943 *
944 * Returns in *max_rate less value between calculated and passed
945 */
946void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
947 unsigned int *max_rate)
948{
949 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
950 unsigned int rate;
951
952 if (pipe == NULL)
953 return;
954
955 /*
956 * TRM says that for parallel sensors the maximum data rate
957 * should be 90% form L3/2 clock, otherwise just L3/2.
958 */
959 if (ccdc->input == CCDC_INPUT_PARALLEL)
960 rate = pipe->l3_ick / 2 * 9 / 10;
961 else
962 rate = pipe->l3_ick / 2;
963
964 *max_rate = min(*max_rate, rate);
965}
966
967/*
968 * ccdc_config_sync_if - Set CCDC sync interface configuration
969 * @ccdc: Pointer to ISP CCDC device.
970 * @pdata: Parallel interface platform data (may be NULL)
971 * @data_size: Data size
972 */
973static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
974 struct isp_parallel_platform_data *pdata,
975 unsigned int data_size)
976{
977 struct isp_device *isp = to_isp_device(ccdc);
978 const struct v4l2_mbus_framefmt *format;
979 u32 syn_mode = ISPCCDC_SYN_MODE_VDHDEN;
980
981 format = &ccdc->formats[CCDC_PAD_SINK];
982
983 if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
984 format->code == V4L2_MBUS_FMT_UYVY8_2X8) {
985 /* The bridge is enabled for YUV8 formats. Configure the input
986 * mode accordingly.
987 */
988 syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
989 }
990
991 switch (data_size) {
992 case 8:
993 syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
994 break;
995 case 10:
996 syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
997 break;
998 case 11:
999 syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
1000 break;
1001 case 12:
1002 syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
1003 break;
1004 }
1005
1006 if (pdata && pdata->data_pol)
1007 syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
1008
1009 if (pdata && pdata->hs_pol)
1010 syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
1011
1012 if (pdata && pdata->vs_pol)
1013 syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
1014
1015 isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
1016
1017 /* The CCDC_CFG.Y8POS bit is used in YCbCr8 input mode only. The
1018 * hardware seems to ignore it in all other input modes.
1019 */
1020 if (format->code == V4L2_MBUS_FMT_UYVY8_2X8)
1021 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
1022 ISPCCDC_CFG_Y8POS);
1023 else
1024 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
1025 ISPCCDC_CFG_Y8POS);
1026
1027 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
1028 ISPCCDC_REC656IF_R656ON);
1029}
1030
1031/* CCDC formats descriptions */
1032static const u32 ccdc_sgrbg_pattern =
1033 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1034 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1035 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1036 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1037 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1038 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1039 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1040 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1041 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1042 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1043 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1044 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1045 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1046 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1047 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1048 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1049
1050static const u32 ccdc_srggb_pattern =
1051 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1052 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1053 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1054 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1055 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1056 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1057 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1058 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1059 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1060 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1061 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1062 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1063 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1064 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1065 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1066 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1067
1068static const u32 ccdc_sbggr_pattern =
1069 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1070 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1071 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1072 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1073 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1074 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1075 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1076 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1077 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1078 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1079 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1080 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1081 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1082 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1083 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1084 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1085
1086static const u32 ccdc_sgbrg_pattern =
1087 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1088 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1089 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1090 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1091 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1092 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1093 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1094 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1095 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1096 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1097 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1098 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1099 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1100 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1101 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1102 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1103
1104static void ccdc_configure(struct isp_ccdc_device *ccdc)
1105{
1106 struct isp_device *isp = to_isp_device(ccdc);
1107 struct isp_parallel_platform_data *pdata = NULL;
1108 struct v4l2_subdev *sensor;
1109 struct v4l2_mbus_framefmt *format;
1110 const struct v4l2_rect *crop;
1111 const struct isp_format_info *fmt_info;
1112 struct v4l2_subdev_format fmt_src;
1113 unsigned int depth_out;
1114 unsigned int depth_in = 0;
1115 struct media_pad *pad;
1116 unsigned long flags;
1117 unsigned int bridge;
1118 unsigned int shift;
1119 u32 syn_mode;
1120 u32 ccdc_pattern;
1121
1122 pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
1123 sensor = media_entity_to_v4l2_subdev(pad->entity);
1124 if (ccdc->input == CCDC_INPUT_PARALLEL)
1125 pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
1126 ->bus.parallel;
1127
1128 /* Compute the lane shifter shift value and enable the bridge when the
1129 * input format is YUV.
1130 */
1131 fmt_src.pad = pad->index;
1132 fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1133 if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) {
1134 fmt_info = omap3isp_video_format_info(fmt_src.format.code);
1135 depth_in = fmt_info->width;
1136 }
1137
1138 fmt_info = omap3isp_video_format_info
1139 (isp->isp_ccdc.formats[CCDC_PAD_SINK].code);
1140 depth_out = fmt_info->width;
1141 shift = depth_in - depth_out;
1142
1143 if (fmt_info->code == V4L2_MBUS_FMT_YUYV8_2X8)
1144 bridge = ISPCTRL_PAR_BRIDGE_LENDIAN;
1145 else if (fmt_info->code == V4L2_MBUS_FMT_UYVY8_2X8)
1146 bridge = ISPCTRL_PAR_BRIDGE_BENDIAN;
1147 else
1148 bridge = ISPCTRL_PAR_BRIDGE_DISABLE;
1149
1150 omap3isp_configure_bridge(isp, ccdc->input, pdata, shift, bridge);
1151
1152 ccdc_config_sync_if(ccdc, pdata, depth_out);
1153
1154 syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
1155
1156 /* Use the raw, unprocessed data when writing to memory. The H3A and
1157 * histogram modules are still fed with lens shading corrected data.
1158 */
1159 syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
1160
1161 if (ccdc->output & CCDC_OUTPUT_MEMORY)
1162 syn_mode |= ISPCCDC_SYN_MODE_WEN;
1163 else
1164 syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
1165
1166 if (ccdc->output & CCDC_OUTPUT_RESIZER)
1167 syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
1168 else
1169 syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
1170
1171 /* CCDC_PAD_SINK */
1172 format = &ccdc->formats[CCDC_PAD_SINK];
1173
1174 /* Mosaic filter */
1175 switch (format->code) {
1176 case V4L2_MBUS_FMT_SRGGB10_1X10:
1177 case V4L2_MBUS_FMT_SRGGB12_1X12:
1178 ccdc_pattern = ccdc_srggb_pattern;
1179 break;
1180 case V4L2_MBUS_FMT_SBGGR10_1X10:
1181 case V4L2_MBUS_FMT_SBGGR12_1X12:
1182 ccdc_pattern = ccdc_sbggr_pattern;
1183 break;
1184 case V4L2_MBUS_FMT_SGBRG10_1X10:
1185 case V4L2_MBUS_FMT_SGBRG12_1X12:
1186 ccdc_pattern = ccdc_sgbrg_pattern;
1187 break;
1188 default:
1189 /* Use GRBG */
1190 ccdc_pattern = ccdc_sgrbg_pattern;
1191 break;
1192 }
1193 ccdc_config_imgattr(ccdc, ccdc_pattern);
1194
1195 /* Generate VD0 on the last line of the image and VD1 on the
1196 * 2/3 height line.
1197 */
1198 isp_reg_writel(isp, ((format->height - 2) << ISPCCDC_VDINT_0_SHIFT) |
1199 ((format->height * 2 / 3) << ISPCCDC_VDINT_1_SHIFT),
1200 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT);
1201
1202 /* CCDC_PAD_SOURCE_OF */
1203 format = &ccdc->formats[CCDC_PAD_SOURCE_OF];
1204 crop = &ccdc->crop;
1205
1206 isp_reg_writel(isp, (crop->left << ISPCCDC_HORZ_INFO_SPH_SHIFT) |
1207 ((crop->width - 1) << ISPCCDC_HORZ_INFO_NPH_SHIFT),
1208 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO);
1209 isp_reg_writel(isp, crop->top << ISPCCDC_VERT_START_SLV0_SHIFT,
1210 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START);
1211 isp_reg_writel(isp, (crop->height - 1)
1212 << ISPCCDC_VERT_LINES_NLV_SHIFT,
1213 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES);
1214
1215 ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, 0, 0);
1216
1217 /* The CCDC outputs data in UYVY order by default. Swap bytes to get
1218 * YUYV.
1219 */
1220 if (format->code == V4L2_MBUS_FMT_YUYV8_1X16)
1221 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
1222 ISPCCDC_CFG_BSWD);
1223 else
1224 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
1225 ISPCCDC_CFG_BSWD);
1226
1227 /* Use PACK8 mode for 1byte per pixel formats. */
1228 if (omap3isp_video_format_info(format->code)->width <= 8)
1229 syn_mode |= ISPCCDC_SYN_MODE_PACK8;
1230 else
1231 syn_mode &= ~ISPCCDC_SYN_MODE_PACK8;
1232
1233 isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
1234
1235 /* CCDC_PAD_SOURCE_VP */
1236 format = &ccdc->formats[CCDC_PAD_SOURCE_VP];
1237
1238 isp_reg_writel(isp, (0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
1239 (format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
1240 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ);
1241 isp_reg_writel(isp, (0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
1242 ((format->height + 1) << ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
1243 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT);
1244
1245 isp_reg_writel(isp, (format->width << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
1246 (format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
1247 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
1248
1249 /* Lens shading correction. */
1250 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
1251 if (ccdc->lsc.request == NULL)
1252 goto unlock;
1253
1254 WARN_ON(ccdc->lsc.active);
1255
1256 /* Get last good LSC configuration. If it is not supported for
1257 * the current active resolution discard it.
1258 */
1259 if (ccdc->lsc.active == NULL &&
1260 __ccdc_lsc_configure(ccdc, ccdc->lsc.request) == 0) {
1261 ccdc->lsc.active = ccdc->lsc.request;
1262 } else {
1263 list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue);
1264 schedule_work(&ccdc->lsc.table_work);
1265 }
1266
1267 ccdc->lsc.request = NULL;
1268
1269unlock:
1270 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
1271
1272 ccdc_apply_controls(ccdc);
1273}
1274
1275static void __ccdc_enable(struct isp_ccdc_device *ccdc, int enable)
1276{
1277 struct isp_device *isp = to_isp_device(ccdc);
1278
1279 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR,
1280 ISPCCDC_PCR_EN, enable ? ISPCCDC_PCR_EN : 0);
1281}
1282
1283static int ccdc_disable(struct isp_ccdc_device *ccdc)
1284{
1285 unsigned long flags;
1286 int ret = 0;
1287
1288 spin_lock_irqsave(&ccdc->lock, flags);
1289 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS)
1290 ccdc->stopping = CCDC_STOP_REQUEST;
1291 spin_unlock_irqrestore(&ccdc->lock, flags);
1292
1293 ret = wait_event_timeout(ccdc->wait,
1294 ccdc->stopping == CCDC_STOP_FINISHED,
1295 msecs_to_jiffies(2000));
1296 if (ret == 0) {
1297 ret = -ETIMEDOUT;
1298 dev_warn(to_device(ccdc), "CCDC stop timeout!\n");
1299 }
1300
1301 omap3isp_sbl_disable(to_isp_device(ccdc), OMAP3_ISP_SBL_CCDC_LSC_READ);
1302
1303 mutex_lock(&ccdc->ioctl_lock);
1304 ccdc_lsc_free_request(ccdc, ccdc->lsc.request);
1305 ccdc->lsc.request = ccdc->lsc.active;
1306 ccdc->lsc.active = NULL;
1307 cancel_work_sync(&ccdc->lsc.table_work);
1308 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
1309 mutex_unlock(&ccdc->ioctl_lock);
1310
1311 ccdc->stopping = CCDC_STOP_NOT_REQUESTED;
1312
1313 return ret > 0 ? 0 : ret;
1314}
1315
1316static void ccdc_enable(struct isp_ccdc_device *ccdc)
1317{
1318 if (ccdc_lsc_is_configured(ccdc))
1319 __ccdc_lsc_enable(ccdc, 1);
1320 __ccdc_enable(ccdc, 1);
1321}
1322
1323/* -----------------------------------------------------------------------------
1324 * Interrupt handling
1325 */
1326
1327/*
1328 * ccdc_sbl_busy - Poll idle state of CCDC and related SBL memory write bits
1329 * @ccdc: Pointer to ISP CCDC device.
1330 *
1331 * Returns zero if the CCDC is idle and the image has been written to
1332 * memory, too.
1333 */
1334static int ccdc_sbl_busy(struct isp_ccdc_device *ccdc)
1335{
1336 struct isp_device *isp = to_isp_device(ccdc);
1337
1338 return omap3isp_ccdc_busy(ccdc)
1339 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) &
1340 ISPSBL_CCDC_WR_0_DATA_READY)
1341 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) &
1342 ISPSBL_CCDC_WR_0_DATA_READY)
1343 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) &
1344 ISPSBL_CCDC_WR_0_DATA_READY)
1345 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) &
1346 ISPSBL_CCDC_WR_0_DATA_READY);
1347}
1348
1349/*
1350 * ccdc_sbl_wait_idle - Wait until the CCDC and related SBL are idle
1351 * @ccdc: Pointer to ISP CCDC device.
1352 * @max_wait: Max retry count in us for wait for idle/busy transition.
1353 */
1354static int ccdc_sbl_wait_idle(struct isp_ccdc_device *ccdc,
1355 unsigned int max_wait)
1356{
1357 unsigned int wait = 0;
1358
1359 if (max_wait == 0)
1360 max_wait = 10000; /* 10 ms */
1361
1362 for (wait = 0; wait <= max_wait; wait++) {
1363 if (!ccdc_sbl_busy(ccdc))
1364 return 0;
1365
1366 rmb();
1367 udelay(1);
1368 }
1369
1370 return -EBUSY;
1371}
1372
1373/* __ccdc_handle_stopping - Handle CCDC and/or LSC stopping sequence
1374 * @ccdc: Pointer to ISP CCDC device.
1375 * @event: Pointing which event trigger handler
1376 *
1377 * Return 1 when the event and stopping request combination is satisfied,
1378 * zero otherwise.
1379 */
1380static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
1381{
1382 int rval = 0;
1383
1384 switch ((ccdc->stopping & 3) | event) {
1385 case CCDC_STOP_REQUEST | CCDC_EVENT_VD1:
1386 if (ccdc->lsc.state != LSC_STATE_STOPPED)
1387 __ccdc_lsc_enable(ccdc, 0);
1388 __ccdc_enable(ccdc, 0);
1389 ccdc->stopping = CCDC_STOP_EXECUTED;
1390 return 1;
1391
1392 case CCDC_STOP_EXECUTED | CCDC_EVENT_VD0:
1393 ccdc->stopping |= CCDC_STOP_CCDC_FINISHED;
1394 if (ccdc->lsc.state == LSC_STATE_STOPPED)
1395 ccdc->stopping |= CCDC_STOP_LSC_FINISHED;
1396 rval = 1;
1397 break;
1398
1399 case CCDC_STOP_EXECUTED | CCDC_EVENT_LSC_DONE:
1400 ccdc->stopping |= CCDC_STOP_LSC_FINISHED;
1401 rval = 1;
1402 break;
1403
1404 case CCDC_STOP_EXECUTED | CCDC_EVENT_VD1:
1405 return 1;
1406 }
1407
1408 if (ccdc->stopping == CCDC_STOP_FINISHED) {
1409 wake_up(&ccdc->wait);
1410 rval = 1;
1411 }
1412
1413 return rval;
1414}
1415
1416static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
1417{
1418 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
1419 struct video_device *vdev = ccdc->subdev.devnode;
1420 struct v4l2_event event;
1421
1422 /* Frame number propagation */
1423 atomic_inc(&pipe->frame_number);
1424
1425 memset(&event, 0, sizeof(event));
1426 event.type = V4L2_EVENT_FRAME_SYNC;
1427 event.u.frame_sync.frame_sequence = atomic_read(&pipe->frame_number);
1428
1429 v4l2_event_queue(vdev, &event);
1430}
1431
1432/*
1433 * ccdc_lsc_isr - Handle LSC events
1434 * @ccdc: Pointer to ISP CCDC device.
1435 * @events: LSC events
1436 */
1437static void ccdc_lsc_isr(struct isp_ccdc_device *ccdc, u32 events)
1438{
1439 unsigned long flags;
1440
1441 if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) {
1442 struct isp_pipeline *pipe =
1443 to_isp_pipeline(&ccdc->subdev.entity);
1444
1445 ccdc_lsc_error_handler(ccdc);
1446 pipe->error = true;
1447 dev_dbg(to_device(ccdc), "lsc prefetch error\n");
1448 }
1449
1450 if (!(events & IRQ0STATUS_CCDC_LSC_DONE_IRQ))
1451 return;
1452
1453 /* LSC_DONE interrupt occur, there are two cases
1454 * 1. stopping for reconfiguration
1455 * 2. stopping because of STREAM OFF command
1456 */
1457 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
1458
1459 if (ccdc->lsc.state == LSC_STATE_STOPPING)
1460 ccdc->lsc.state = LSC_STATE_STOPPED;
1461
1462 if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_LSC_DONE))
1463 goto done;
1464
1465 if (ccdc->lsc.state != LSC_STATE_RECONFIG)
1466 goto done;
1467
1468 /* LSC is in STOPPING state, change to the new state */
1469 ccdc->lsc.state = LSC_STATE_STOPPED;
1470
1471 /* This is an exception. Start of frame and LSC_DONE interrupt
1472 * have been received on the same time. Skip this event and wait
1473 * for better times.
1474 */
1475 if (events & IRQ0STATUS_HS_VS_IRQ)
1476 goto done;
1477
1478 /* The LSC engine is stopped at this point. Enable it if there's a
1479 * pending request.
1480 */
1481 if (ccdc->lsc.request == NULL)
1482 goto done;
1483
1484 ccdc_lsc_enable(ccdc);
1485
1486done:
1487 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
1488}
1489
1490static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
1491{
1492 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
1493 struct isp_device *isp = to_isp_device(ccdc);
1494 struct isp_buffer *buffer;
1495 int restart = 0;
1496
1497 /* The CCDC generates VD0 interrupts even when disabled (the datasheet
1498 * doesn't explicitly state if that's supposed to happen or not, so it
1499 * can be considered as a hardware bug or as a feature, but we have to
1500 * deal with it anyway). Disabling the CCDC when no buffer is available
1501 * would thus not be enough, we need to handle the situation explicitly.
1502 */
1503 if (list_empty(&ccdc->video_out.dmaqueue))
1504 goto done;
1505
1506 /* We're in continuous mode, and memory writes were disabled due to a
1507 * buffer underrun. Reenable them now that we have a buffer. The buffer
1508 * address has been set in ccdc_video_queue.
1509 */
1510 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && ccdc->underrun) {
1511 restart = 1;
1512 ccdc->underrun = 0;
1513 goto done;
1514 }
1515
1516 if (ccdc_sbl_wait_idle(ccdc, 1000)) {
1517 dev_info(isp->dev, "CCDC won't become idle!\n");
1518 goto done;
1519 }
1520
1521 buffer = omap3isp_video_buffer_next(&ccdc->video_out);
1522 if (buffer != NULL) {
1523 ccdc_set_outaddr(ccdc, buffer->isp_addr);
1524 restart = 1;
1525 }
1526
1527 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
1528
1529 if (ccdc->state == ISP_PIPELINE_STREAM_SINGLESHOT &&
1530 isp_pipeline_ready(pipe))
1531 omap3isp_pipeline_set_stream(pipe,
1532 ISP_PIPELINE_STREAM_SINGLESHOT);
1533
1534done:
1535 return restart;
1536}
1537
1538/*
1539 * ccdc_vd0_isr - Handle VD0 event
1540 * @ccdc: Pointer to ISP CCDC device.
1541 *
1542 * Executes LSC deferred enablement before next frame starts.
1543 */
1544static void ccdc_vd0_isr(struct isp_ccdc_device *ccdc)
1545{
1546 unsigned long flags;
1547 int restart = 0;
1548
1549 if (ccdc->output & CCDC_OUTPUT_MEMORY)
1550 restart = ccdc_isr_buffer(ccdc);
1551
1552 spin_lock_irqsave(&ccdc->lock, flags);
1553 if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD0)) {
1554 spin_unlock_irqrestore(&ccdc->lock, flags);
1555 return;
1556 }
1557
1558 if (!ccdc->shadow_update)
1559 ccdc_apply_controls(ccdc);
1560 spin_unlock_irqrestore(&ccdc->lock, flags);
1561
1562 if (restart)
1563 ccdc_enable(ccdc);
1564}
1565
1566/*
1567 * ccdc_vd1_isr - Handle VD1 event
1568 * @ccdc: Pointer to ISP CCDC device.
1569 */
1570static void ccdc_vd1_isr(struct isp_ccdc_device *ccdc)
1571{
1572 unsigned long flags;
1573
1574 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
1575
1576 /*
1577 * Depending on the CCDC pipeline state, CCDC stopping should be
1578 * handled differently. In SINGLESHOT we emulate an internal CCDC
1579 * stopping because the CCDC hw works only in continuous mode.
1580 * When CONTINUOUS pipeline state is used and the CCDC writes it's
1581 * data to memory the CCDC and LSC are stopped immediately but
1582 * without change the CCDC stopping state machine. The CCDC
1583 * stopping state machine should be used only when user request
1584 * for stopping is received (SINGLESHOT is an exeption).
1585 */
1586 switch (ccdc->state) {
1587 case ISP_PIPELINE_STREAM_SINGLESHOT:
1588 ccdc->stopping = CCDC_STOP_REQUEST;
1589 break;
1590
1591 case ISP_PIPELINE_STREAM_CONTINUOUS:
1592 if (ccdc->output & CCDC_OUTPUT_MEMORY) {
1593 if (ccdc->lsc.state != LSC_STATE_STOPPED)
1594 __ccdc_lsc_enable(ccdc, 0);
1595 __ccdc_enable(ccdc, 0);
1596 }
1597 break;
1598
1599 case ISP_PIPELINE_STREAM_STOPPED:
1600 break;
1601 }
1602
1603 if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD1))
1604 goto done;
1605
1606 if (ccdc->lsc.request == NULL)
1607 goto done;
1608
1609 /*
1610 * LSC need to be reconfigured. Stop it here and on next LSC_DONE IRQ
1611 * do the appropriate changes in registers
1612 */
1613 if (ccdc->lsc.state == LSC_STATE_RUNNING) {
1614 __ccdc_lsc_enable(ccdc, 0);
1615 ccdc->lsc.state = LSC_STATE_RECONFIG;
1616 goto done;
1617 }
1618
1619 /* LSC has been in STOPPED state, enable it */
1620 if (ccdc->lsc.state == LSC_STATE_STOPPED)
1621 ccdc_lsc_enable(ccdc);
1622
1623done:
1624 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
1625}
1626
1627/*
1628 * omap3isp_ccdc_isr - Configure CCDC during interframe time.
1629 * @ccdc: Pointer to ISP CCDC device.
1630 * @events: CCDC events
1631 */
1632int omap3isp_ccdc_isr(struct isp_ccdc_device *ccdc, u32 events)
1633{
1634 if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED)
1635 return 0;
1636
1637 if (events & IRQ0STATUS_CCDC_VD1_IRQ)
1638 ccdc_vd1_isr(ccdc);
1639
1640 ccdc_lsc_isr(ccdc, events);
1641
1642 if (events & IRQ0STATUS_CCDC_VD0_IRQ)
1643 ccdc_vd0_isr(ccdc);
1644
1645 if (events & IRQ0STATUS_HS_VS_IRQ)
1646 ccdc_hs_vs_isr(ccdc);
1647
1648 return 0;
1649}
1650
1651/* -----------------------------------------------------------------------------
1652 * ISP video operations
1653 */
1654
1655static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
1656{
1657 struct isp_ccdc_device *ccdc = &video->isp->isp_ccdc;
1658
1659 if (!(ccdc->output & CCDC_OUTPUT_MEMORY))
1660 return -ENODEV;
1661
1662 ccdc_set_outaddr(ccdc, buffer->isp_addr);
1663
1664 /* We now have a buffer queued on the output, restart the pipeline
1665 * on the next CCDC interrupt if running in continuous mode (or when
1666 * starting the stream).
1667 */
1668 ccdc->underrun = 1;
1669
1670 return 0;
1671}
1672
1673static const struct isp_video_operations ccdc_video_ops = {
1674 .queue = ccdc_video_queue,
1675};
1676
1677/* -----------------------------------------------------------------------------
1678 * V4L2 subdev operations
1679 */
1680
1681/*
1682 * ccdc_ioctl - CCDC module private ioctl's
1683 * @sd: ISP CCDC V4L2 subdevice
1684 * @cmd: ioctl command
1685 * @arg: ioctl argument
1686 *
1687 * Return 0 on success or a negative error code otherwise.
1688 */
1689static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1690{
1691 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1692 int ret;
1693
1694 switch (cmd) {
1695 case VIDIOC_OMAP3ISP_CCDC_CFG:
1696 mutex_lock(&ccdc->ioctl_lock);
1697 ret = ccdc_config(ccdc, arg);
1698 mutex_unlock(&ccdc->ioctl_lock);
1699 break;
1700
1701 default:
1702 return -ENOIOCTLCMD;
1703 }
1704
1705 return ret;
1706}
1707
1708static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1709 const struct v4l2_event_subscription *sub)
1710{
1711 if (sub->type != V4L2_EVENT_FRAME_SYNC)
1712 return -EINVAL;
1713
1714 /* line number is zero at frame start */
1715 if (sub->id != 0)
1716 return -EINVAL;
1717
1718 return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS, NULL);
1719}
1720
1721static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1722 const struct v4l2_event_subscription *sub)
1723{
1724 return v4l2_event_unsubscribe(fh, sub);
1725}
1726
1727/*
1728 * ccdc_set_stream - Enable/Disable streaming on the CCDC module
1729 * @sd: ISP CCDC V4L2 subdevice
1730 * @enable: Enable/disable stream
1731 *
1732 * When writing to memory, the CCDC hardware can't be enabled without a memory
1733 * buffer to write to. As the s_stream operation is called in response to a
1734 * STREAMON call without any buffer queued yet, just update the enabled field
1735 * and return immediately. The CCDC will be enabled in ccdc_isr_buffer().
1736 *
1737 * When not writing to memory enable the CCDC immediately.
1738 */
1739static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
1740{
1741 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1742 struct isp_device *isp = to_isp_device(ccdc);
1743 int ret = 0;
1744
1745 if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) {
1746 if (enable == ISP_PIPELINE_STREAM_STOPPED)
1747 return 0;
1748
1749 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_CCDC);
1750 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
1751 ISPCCDC_CFG_VDLC);
1752
1753 ccdc_configure(ccdc);
1754
1755 /* TODO: Don't configure the video port if all of its output
1756 * links are inactive.
1757 */
1758 ccdc_config_vp(ccdc);
1759 ccdc_enable_vp(ccdc, 1);
1760 ccdc_print_status(ccdc);
1761 }
1762
1763 switch (enable) {
1764 case ISP_PIPELINE_STREAM_CONTINUOUS:
1765 if (ccdc->output & CCDC_OUTPUT_MEMORY)
1766 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
1767
1768 if (ccdc->underrun || !(ccdc->output & CCDC_OUTPUT_MEMORY))
1769 ccdc_enable(ccdc);
1770
1771 ccdc->underrun = 0;
1772 break;
1773
1774 case ISP_PIPELINE_STREAM_SINGLESHOT:
1775 if (ccdc->output & CCDC_OUTPUT_MEMORY &&
1776 ccdc->state != ISP_PIPELINE_STREAM_SINGLESHOT)
1777 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
1778
1779 ccdc_enable(ccdc);
1780 break;
1781
1782 case ISP_PIPELINE_STREAM_STOPPED:
1783 ret = ccdc_disable(ccdc);
1784 if (ccdc->output & CCDC_OUTPUT_MEMORY)
1785 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
1786 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_CCDC);
1787 ccdc->underrun = 0;
1788 break;
1789 }
1790
1791 ccdc->state = enable;
1792 return ret;
1793}
1794
1795static struct v4l2_mbus_framefmt *
1796__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
1797 unsigned int pad, enum v4l2_subdev_format_whence which)
1798{
1799 if (which == V4L2_SUBDEV_FORMAT_TRY)
1800 return v4l2_subdev_get_try_format(fh, pad);
1801 else
1802 return &ccdc->formats[pad];
1803}
1804
1805static struct v4l2_rect *
1806__ccdc_get_crop(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
1807 enum v4l2_subdev_format_whence which)
1808{
1809 if (which == V4L2_SUBDEV_FORMAT_TRY)
1810 return v4l2_subdev_get_try_crop(fh, CCDC_PAD_SOURCE_OF);
1811 else
1812 return &ccdc->crop;
1813}
1814
1815/*
1816 * ccdc_try_format - Try video format on a pad
1817 * @ccdc: ISP CCDC device
1818 * @fh : V4L2 subdev file handle
1819 * @pad: Pad number
1820 * @fmt: Format
1821 */
1822static void
1823ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
1824 unsigned int pad, struct v4l2_mbus_framefmt *fmt,
1825 enum v4l2_subdev_format_whence which)
1826{
1827 const struct isp_format_info *info;
1828 enum v4l2_mbus_pixelcode pixelcode;
1829 unsigned int width = fmt->width;
1830 unsigned int height = fmt->height;
1831 struct v4l2_rect *crop;
1832 unsigned int i;
1833
1834 switch (pad) {
1835 case CCDC_PAD_SINK:
1836 for (i = 0; i < ARRAY_SIZE(ccdc_fmts); i++) {
1837 if (fmt->code == ccdc_fmts[i])
1838 break;
1839 }
1840
1841 /* If not found, use SGRBG10 as default */
1842 if (i >= ARRAY_SIZE(ccdc_fmts))
1843 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
1844
1845 /* Clamp the input size. */
1846 fmt->width = clamp_t(u32, width, 32, 4096);
1847 fmt->height = clamp_t(u32, height, 32, 4096);
1848 break;
1849
1850 case CCDC_PAD_SOURCE_OF:
1851 pixelcode = fmt->code;
1852 *fmt = *__ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
1853
1854 /* YUV formats are converted from 2X8 to 1X16 by the bridge and
1855 * can be byte-swapped.
1856 */
1857 if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
1858 fmt->code == V4L2_MBUS_FMT_UYVY8_2X8) {
1859 /* Use the user requested format if YUV. */
1860 if (pixelcode == V4L2_MBUS_FMT_YUYV8_2X8 ||
1861 pixelcode == V4L2_MBUS_FMT_UYVY8_2X8 ||
1862 pixelcode == V4L2_MBUS_FMT_YUYV8_1X16 ||
1863 pixelcode == V4L2_MBUS_FMT_UYVY8_1X16)
1864 fmt->code = pixelcode;
1865
1866 if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8)
1867 fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
1868 else if (fmt->code == V4L2_MBUS_FMT_UYVY8_2X8)
1869 fmt->code = V4L2_MBUS_FMT_UYVY8_1X16;
1870 }
1871
1872 /* Hardcode the output size to the crop rectangle size. */
1873 crop = __ccdc_get_crop(ccdc, fh, which);
1874 fmt->width = crop->width;
1875 fmt->height = crop->height;
1876 break;
1877
1878 case CCDC_PAD_SOURCE_VP:
1879 *fmt = *__ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
1880
1881 /* The video port interface truncates the data to 10 bits. */
1882 info = omap3isp_video_format_info(fmt->code);
1883 fmt->code = info->truncated;
1884
1885 /* YUV formats are not supported by the video port. */
1886 if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
1887 fmt->code == V4L2_MBUS_FMT_UYVY8_2X8)
1888 fmt->code = 0;
1889
1890 /* The number of lines that can be clocked out from the video
1891 * port output must be at least one line less than the number
1892 * of input lines.
1893 */
1894 fmt->width = clamp_t(u32, width, 32, fmt->width);
1895 fmt->height = clamp_t(u32, height, 32, fmt->height - 1);
1896 break;
1897 }
1898
1899 /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is
1900 * stored on 2 bytes.
1901 */
1902 fmt->colorspace = V4L2_COLORSPACE_SRGB;
1903 fmt->field = V4L2_FIELD_NONE;
1904}
1905
1906/*
1907 * ccdc_try_crop - Validate a crop rectangle
1908 * @ccdc: ISP CCDC device
1909 * @sink: format on the sink pad
1910 * @crop: crop rectangle to be validated
1911 */
1912static void ccdc_try_crop(struct isp_ccdc_device *ccdc,
1913 const struct v4l2_mbus_framefmt *sink,
1914 struct v4l2_rect *crop)
1915{
1916 const struct isp_format_info *info;
1917 unsigned int max_width;
1918
1919 /* For Bayer formats, restrict left/top and width/height to even values
1920 * to keep the Bayer pattern.
1921 */
1922 info = omap3isp_video_format_info(sink->code);
1923 if (info->flavor != V4L2_MBUS_FMT_Y8_1X8) {
1924 crop->left &= ~1;
1925 crop->top &= ~1;
1926 }
1927
1928 crop->left = clamp_t(u32, crop->left, 0, sink->width - CCDC_MIN_WIDTH);
1929 crop->top = clamp_t(u32, crop->top, 0, sink->height - CCDC_MIN_HEIGHT);
1930
1931 /* The data formatter truncates the number of horizontal output pixels
1932 * to a multiple of 16. To avoid clipping data, allow callers to request
1933 * an output size bigger than the input size up to the nearest multiple
1934 * of 16.
1935 */
1936 max_width = (sink->width - crop->left + 15) & ~15;
1937 crop->width = clamp_t(u32, crop->width, CCDC_MIN_WIDTH, max_width)
1938 & ~15;
1939 crop->height = clamp_t(u32, crop->height, CCDC_MIN_HEIGHT,
1940 sink->height - crop->top);
1941
1942 /* Odd width/height values don't make sense for Bayer formats. */
1943 if (info->flavor != V4L2_MBUS_FMT_Y8_1X8) {
1944 crop->width &= ~1;
1945 crop->height &= ~1;
1946 }
1947}
1948
1949/*
1950 * ccdc_enum_mbus_code - Handle pixel format enumeration
1951 * @sd : pointer to v4l2 subdev structure
1952 * @fh : V4L2 subdev file handle
1953 * @code : pointer to v4l2_subdev_mbus_code_enum structure
1954 * return -EINVAL or zero on success
1955 */
1956static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
1957 struct v4l2_subdev_fh *fh,
1958 struct v4l2_subdev_mbus_code_enum *code)
1959{
1960 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1961 struct v4l2_mbus_framefmt *format;
1962
1963 switch (code->pad) {
1964 case CCDC_PAD_SINK:
1965 if (code->index >= ARRAY_SIZE(ccdc_fmts))
1966 return -EINVAL;
1967
1968 code->code = ccdc_fmts[code->index];
1969 break;
1970
1971 case CCDC_PAD_SOURCE_OF:
1972 format = __ccdc_get_format(ccdc, fh, code->pad,
1973 V4L2_SUBDEV_FORMAT_TRY);
1974
1975 if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
1976 format->code == V4L2_MBUS_FMT_UYVY8_2X8) {
1977 /* In YUV mode the CCDC can swap bytes. */
1978 if (code->index == 0)
1979 code->code = V4L2_MBUS_FMT_YUYV8_1X16;
1980 else if (code->index == 1)
1981 code->code = V4L2_MBUS_FMT_UYVY8_1X16;
1982 else
1983 return -EINVAL;
1984 } else {
1985 /* In raw mode, no configurable format confversion is
1986 * available.
1987 */
1988 if (code->index == 0)
1989 code->code = format->code;
1990 else
1991 return -EINVAL;
1992 }
1993 break;
1994
1995 case CCDC_PAD_SOURCE_VP:
1996 /* The CCDC supports no configurable format conversion
1997 * compatible with the video port. Enumerate a single output
1998 * format code.
1999 */
2000 if (code->index != 0)
2001 return -EINVAL;
2002
2003 format = __ccdc_get_format(ccdc, fh, code->pad,
2004 V4L2_SUBDEV_FORMAT_TRY);
2005
2006 /* A pixel code equal to 0 means that the video port doesn't
2007 * support the input format. Don't enumerate any pixel code.
2008 */
2009 if (format->code == 0)
2010 return -EINVAL;
2011
2012 code->code = format->code;
2013 break;
2014
2015 default:
2016 return -EINVAL;
2017 }
2018
2019 return 0;
2020}
2021
2022static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
2023 struct v4l2_subdev_fh *fh,
2024 struct v4l2_subdev_frame_size_enum *fse)
2025{
2026 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
2027 struct v4l2_mbus_framefmt format;
2028
2029 if (fse->index != 0)
2030 return -EINVAL;
2031
2032 format.code = fse->code;
2033 format.width = 1;
2034 format.height = 1;
2035 ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
2036 fse->min_width = format.width;
2037 fse->min_height = format.height;
2038
2039 if (format.code != fse->code)
2040 return -EINVAL;
2041
2042 format.code = fse->code;
2043 format.width = -1;
2044 format.height = -1;
2045 ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
2046 fse->max_width = format.width;
2047 fse->max_height = format.height;
2048
2049 return 0;
2050}
2051
2052/*
2053 * ccdc_get_selection - Retrieve a selection rectangle on a pad
2054 * @sd: ISP CCDC V4L2 subdevice
2055 * @fh: V4L2 subdev file handle
2056 * @sel: Selection rectangle
2057 *
2058 * The only supported rectangles are the crop rectangles on the output formatter
2059 * source pad.
2060 *
2061 * Return 0 on success or a negative error code otherwise.
2062 */
2063static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
2064 struct v4l2_subdev_selection *sel)
2065{
2066 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
2067 struct v4l2_mbus_framefmt *format;
2068
2069 if (sel->pad != CCDC_PAD_SOURCE_OF)
2070 return -EINVAL;
2071
2072 switch (sel->target) {
2073 case V4L2_SEL_TGT_CROP_BOUNDS:
2074 sel->r.left = 0;
2075 sel->r.top = 0;
2076 sel->r.width = INT_MAX;
2077 sel->r.height = INT_MAX;
2078
2079 format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, sel->which);
2080 ccdc_try_crop(ccdc, format, &sel->r);
2081 break;
2082
2083 case V4L2_SEL_TGT_CROP:
2084 sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
2085 break;
2086
2087 default:
2088 return -EINVAL;
2089 }
2090
2091 return 0;
2092}
2093
2094/*
2095 * ccdc_set_selection - Set a selection rectangle on a pad
2096 * @sd: ISP CCDC V4L2 subdevice
2097 * @fh: V4L2 subdev file handle
2098 * @sel: Selection rectangle
2099 *
2100 * The only supported rectangle is the actual crop rectangle on the output
2101 * formatter source pad.
2102 *
2103 * Return 0 on success or a negative error code otherwise.
2104 */
2105static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
2106 struct v4l2_subdev_selection *sel)
2107{
2108 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
2109 struct v4l2_mbus_framefmt *format;
2110
2111 if (sel->target != V4L2_SEL_TGT_CROP ||
2112 sel->pad != CCDC_PAD_SOURCE_OF)
2113 return -EINVAL;
2114
2115 /* The crop rectangle can't be changed while streaming. */
2116 if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED)
2117 return -EBUSY;
2118
2119 /* Modifying the crop rectangle always changes the format on the source
2120 * pad. If the KEEP_CONFIG flag is set, just return the current crop
2121 * rectangle.
2122 */
2123 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
2124 sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
2125 return 0;
2126 }
2127
2128 format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, sel->which);
2129 ccdc_try_crop(ccdc, format, &sel->r);
2130 *__ccdc_get_crop(ccdc, fh, sel->which) = sel->r;
2131
2132 /* Update the source format. */
2133 format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_OF, sel->which);
2134 ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_OF, format, sel->which);
2135
2136 return 0;
2137}
2138
2139/*
2140 * ccdc_get_format - Retrieve the video format on a pad
2141 * @sd : ISP CCDC V4L2 subdevice
2142 * @fh : V4L2 subdev file handle
2143 * @fmt: Format
2144 *
2145 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
2146 * to the format type.
2147 */
2148static int ccdc_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
2149 struct v4l2_subdev_format *fmt)
2150{
2151 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
2152 struct v4l2_mbus_framefmt *format;
2153
2154 format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
2155 if (format == NULL)
2156 return -EINVAL;
2157
2158 fmt->format = *format;
2159 return 0;
2160}
2161
2162/*
2163 * ccdc_set_format - Set the video format on a pad
2164 * @sd : ISP CCDC V4L2 subdevice
2165 * @fh : V4L2 subdev file handle
2166 * @fmt: Format
2167 *
2168 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
2169 * to the format type.
2170 */
2171static int ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
2172 struct v4l2_subdev_format *fmt)
2173{
2174 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
2175 struct v4l2_mbus_framefmt *format;
2176 struct v4l2_rect *crop;
2177
2178 format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
2179 if (format == NULL)
2180 return -EINVAL;
2181
2182 ccdc_try_format(ccdc, fh, fmt->pad, &fmt->format, fmt->which);
2183 *format = fmt->format;
2184
2185 /* Propagate the format from sink to source */
2186 if (fmt->pad == CCDC_PAD_SINK) {
2187 /* Reset the crop rectangle. */
2188 crop = __ccdc_get_crop(ccdc, fh, fmt->which);
2189 crop->left = 0;
2190 crop->top = 0;
2191 crop->width = fmt->format.width;
2192 crop->height = fmt->format.height;
2193
2194 ccdc_try_crop(ccdc, &fmt->format, crop);
2195
2196 /* Update the source formats. */
2197 format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_OF,
2198 fmt->which);
2199 *format = fmt->format;
2200 ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_OF, format,
2201 fmt->which);
2202
2203 format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_VP,
2204 fmt->which);
2205 *format = fmt->format;
2206 ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_VP, format,
2207 fmt->which);
2208 }
2209
2210 return 0;
2211}
2212
2213/*
2214 * Decide whether desired output pixel code can be obtained with
2215 * the lane shifter by shifting the input pixel code.
2216 * @in: input pixelcode to shifter
2217 * @out: output pixelcode from shifter
2218 * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
2219 *
2220 * return true if the combination is possible
2221 * return false otherwise
2222 */
2223static bool ccdc_is_shiftable(enum v4l2_mbus_pixelcode in,
2224 enum v4l2_mbus_pixelcode out,
2225 unsigned int additional_shift)
2226{
2227 const struct isp_format_info *in_info, *out_info;
2228
2229 if (in == out)
2230 return true;
2231
2232 in_info = omap3isp_video_format_info(in);
2233 out_info = omap3isp_video_format_info(out);
2234
2235 if ((in_info->flavor == 0) || (out_info->flavor == 0))
2236 return false;
2237
2238 if (in_info->flavor != out_info->flavor)
2239 return false;
2240
2241 return in_info->width - out_info->width + additional_shift <= 6;
2242}
2243
2244static int ccdc_link_validate(struct v4l2_subdev *sd,
2245 struct media_link *link,
2246 struct v4l2_subdev_format *source_fmt,
2247 struct v4l2_subdev_format *sink_fmt)
2248{
2249 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
2250 unsigned long parallel_shift;
2251
2252 /* Check if the two ends match */
2253 if (source_fmt->format.width != sink_fmt->format.width ||
2254 source_fmt->format.height != sink_fmt->format.height)
2255 return -EPIPE;
2256
2257 /* We've got a parallel sensor here. */
2258 if (ccdc->input == CCDC_INPUT_PARALLEL) {
2259 struct isp_parallel_platform_data *pdata =
2260 &((struct isp_v4l2_subdevs_group *)
2261 media_entity_to_v4l2_subdev(link->source->entity)
2262 ->host_priv)->bus.parallel;
2263 parallel_shift = pdata->data_lane_shift * 2;
2264 } else {
2265 parallel_shift = 0;
2266 }
2267
2268 /* Lane shifter may be used to drop bits on CCDC sink pad */
2269 if (!ccdc_is_shiftable(source_fmt->format.code,
2270 sink_fmt->format.code, parallel_shift))
2271 return -EPIPE;
2272
2273 return 0;
2274}
2275
2276/*
2277 * ccdc_init_formats - Initialize formats on all pads
2278 * @sd: ISP CCDC V4L2 subdevice
2279 * @fh: V4L2 subdev file handle
2280 *
2281 * Initialize all pad formats with default values. If fh is not NULL, try
2282 * formats are initialized on the file handle. Otherwise active formats are
2283 * initialized on the device.
2284 */
2285static int ccdc_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
2286{
2287 struct v4l2_subdev_format format;
2288
2289 memset(&format, 0, sizeof(format));
2290 format.pad = CCDC_PAD_SINK;
2291 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
2292 format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
2293 format.format.width = 4096;
2294 format.format.height = 4096;
2295 ccdc_set_format(sd, fh, &format);
2296
2297 return 0;
2298}
2299
2300/* V4L2 subdev core operations */
2301static const struct v4l2_subdev_core_ops ccdc_v4l2_core_ops = {
2302 .ioctl = ccdc_ioctl,
2303 .subscribe_event = ccdc_subscribe_event,
2304 .unsubscribe_event = ccdc_unsubscribe_event,
2305};
2306
2307/* V4L2 subdev video operations */
2308static const struct v4l2_subdev_video_ops ccdc_v4l2_video_ops = {
2309 .s_stream = ccdc_set_stream,
2310};
2311
2312/* V4L2 subdev pad operations */
2313static const struct v4l2_subdev_pad_ops ccdc_v4l2_pad_ops = {
2314 .enum_mbus_code = ccdc_enum_mbus_code,
2315 .enum_frame_size = ccdc_enum_frame_size,
2316 .get_fmt = ccdc_get_format,
2317 .set_fmt = ccdc_set_format,
2318 .get_selection = ccdc_get_selection,
2319 .set_selection = ccdc_set_selection,
2320 .link_validate = ccdc_link_validate,
2321};
2322
2323/* V4L2 subdev operations */
2324static const struct v4l2_subdev_ops ccdc_v4l2_ops = {
2325 .core = &ccdc_v4l2_core_ops,
2326 .video = &ccdc_v4l2_video_ops,
2327 .pad = &ccdc_v4l2_pad_ops,
2328};
2329
2330/* V4L2 subdev internal operations */
2331static const struct v4l2_subdev_internal_ops ccdc_v4l2_internal_ops = {
2332 .open = ccdc_init_formats,
2333};
2334
2335/* -----------------------------------------------------------------------------
2336 * Media entity operations
2337 */
2338
2339/*
2340 * ccdc_link_setup - Setup CCDC connections
2341 * @entity: CCDC media entity
2342 * @local: Pad at the local end of the link
2343 * @remote: Pad at the remote end of the link
2344 * @flags: Link flags
2345 *
2346 * return -EINVAL or zero on success
2347 */
2348static int ccdc_link_setup(struct media_entity *entity,
2349 const struct media_pad *local,
2350 const struct media_pad *remote, u32 flags)
2351{
2352 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
2353 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
2354 struct isp_device *isp = to_isp_device(ccdc);
2355
2356 switch (local->index | media_entity_type(remote->entity)) {
2357 case CCDC_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
2358 /* Read from the sensor (parallel interface), CCP2, CSI2a or
2359 * CSI2c.
2360 */
2361 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
2362 ccdc->input = CCDC_INPUT_NONE;
2363 break;
2364 }
2365
2366 if (ccdc->input != CCDC_INPUT_NONE)
2367 return -EBUSY;
2368
2369 if (remote->entity == &isp->isp_ccp2.subdev.entity)
2370 ccdc->input = CCDC_INPUT_CCP2B;
2371 else if (remote->entity == &isp->isp_csi2a.subdev.entity)
2372 ccdc->input = CCDC_INPUT_CSI2A;
2373 else if (remote->entity == &isp->isp_csi2c.subdev.entity)
2374 ccdc->input = CCDC_INPUT_CSI2C;
2375 else
2376 ccdc->input = CCDC_INPUT_PARALLEL;
2377
2378 break;
2379
2380 /*
2381 * The ISP core doesn't support pipelines with multiple video outputs.
2382 * Revisit this when it will be implemented, and return -EBUSY for now.
2383 */
2384
2385 case CCDC_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV:
2386 /* Write to preview engine, histogram and H3A. When none of
2387 * those links are active, the video port can be disabled.
2388 */
2389 if (flags & MEDIA_LNK_FL_ENABLED) {
2390 if (ccdc->output & ~CCDC_OUTPUT_PREVIEW)
2391 return -EBUSY;
2392 ccdc->output |= CCDC_OUTPUT_PREVIEW;
2393 } else {
2394 ccdc->output &= ~CCDC_OUTPUT_PREVIEW;
2395 }
2396 break;
2397
2398 case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_DEVNODE:
2399 /* Write to memory */
2400 if (flags & MEDIA_LNK_FL_ENABLED) {
2401 if (ccdc->output & ~CCDC_OUTPUT_MEMORY)
2402 return -EBUSY;
2403 ccdc->output |= CCDC_OUTPUT_MEMORY;
2404 } else {
2405 ccdc->output &= ~CCDC_OUTPUT_MEMORY;
2406 }
2407 break;
2408
2409 case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_V4L2_SUBDEV:
2410 /* Write to resizer */
2411 if (flags & MEDIA_LNK_FL_ENABLED) {
2412 if (ccdc->output & ~CCDC_OUTPUT_RESIZER)
2413 return -EBUSY;
2414 ccdc->output |= CCDC_OUTPUT_RESIZER;
2415 } else {
2416 ccdc->output &= ~CCDC_OUTPUT_RESIZER;
2417 }
2418 break;
2419
2420 default:
2421 return -EINVAL;
2422 }
2423
2424 return 0;
2425}
2426
2427/* media operations */
2428static const struct media_entity_operations ccdc_media_ops = {
2429 .link_setup = ccdc_link_setup,
2430 .link_validate = v4l2_subdev_link_validate,
2431};
2432
2433void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
2434{
2435 v4l2_device_unregister_subdev(&ccdc->subdev);
2436 omap3isp_video_unregister(&ccdc->video_out);
2437}
2438
2439int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
2440 struct v4l2_device *vdev)
2441{
2442 int ret;
2443
2444 /* Register the subdev and video node. */
2445 ret = v4l2_device_register_subdev(vdev, &ccdc->subdev);
2446 if (ret < 0)
2447 goto error;
2448
2449 ret = omap3isp_video_register(&ccdc->video_out, vdev);
2450 if (ret < 0)
2451 goto error;
2452
2453 return 0;
2454
2455error:
2456 omap3isp_ccdc_unregister_entities(ccdc);
2457 return ret;
2458}
2459
2460/* -----------------------------------------------------------------------------
2461 * ISP CCDC initialisation and cleanup
2462 */
2463
2464/*
2465 * ccdc_init_entities - Initialize V4L2 subdev and media entity
2466 * @ccdc: ISP CCDC module
2467 *
2468 * Return 0 on success and a negative error code on failure.
2469 */
2470static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
2471{
2472 struct v4l2_subdev *sd = &ccdc->subdev;
2473 struct media_pad *pads = ccdc->pads;
2474 struct media_entity *me = &sd->entity;
2475 int ret;
2476
2477 ccdc->input = CCDC_INPUT_NONE;
2478
2479 v4l2_subdev_init(sd, &ccdc_v4l2_ops);
2480 sd->internal_ops = &ccdc_v4l2_internal_ops;
2481 strlcpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name));
2482 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
2483 v4l2_set_subdevdata(sd, ccdc);
2484 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
2485
2486 pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
2487 pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
2488 pads[CCDC_PAD_SOURCE_OF].flags = MEDIA_PAD_FL_SOURCE;
2489
2490 me->ops = &ccdc_media_ops;
2491 ret = media_entity_init(me, CCDC_PADS_NUM, pads, 0);
2492 if (ret < 0)
2493 return ret;
2494
2495 ccdc_init_formats(sd, NULL);
2496
2497 ccdc->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2498 ccdc->video_out.ops = &ccdc_video_ops;
2499 ccdc->video_out.isp = to_isp_device(ccdc);
2500 ccdc->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
2501 ccdc->video_out.bpl_alignment = 32;
2502
2503 ret = omap3isp_video_init(&ccdc->video_out, "CCDC");
2504 if (ret < 0)
2505 goto error_video;
2506
2507 /* Connect the CCDC subdev to the video node. */
2508 ret = media_entity_create_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
2509 &ccdc->video_out.video.entity, 0, 0);
2510 if (ret < 0)
2511 goto error_link;
2512
2513 return 0;
2514
2515error_link:
2516 omap3isp_video_cleanup(&ccdc->video_out);
2517error_video:
2518 media_entity_cleanup(me);
2519 return ret;
2520}
2521
2522/*
2523 * omap3isp_ccdc_init - CCDC module initialization.
2524 * @dev: Device pointer specific to the OMAP3 ISP.
2525 *
2526 * TODO: Get the initialisation values from platform data.
2527 *
2528 * Return 0 on success or a negative error code otherwise.
2529 */
2530int omap3isp_ccdc_init(struct isp_device *isp)
2531{
2532 struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
2533 int ret;
2534
2535 spin_lock_init(&ccdc->lock);
2536 init_waitqueue_head(&ccdc->wait);
2537 mutex_init(&ccdc->ioctl_lock);
2538
2539 ccdc->stopping = CCDC_STOP_NOT_REQUESTED;
2540
2541 INIT_WORK(&ccdc->lsc.table_work, ccdc_lsc_free_table_work);
2542 ccdc->lsc.state = LSC_STATE_STOPPED;
2543 INIT_LIST_HEAD(&ccdc->lsc.free_queue);
2544 spin_lock_init(&ccdc->lsc.req_lock);
2545
2546 ccdc->clamp.oblen = 0;
2547 ccdc->clamp.dcsubval = 0;
2548
2549 ccdc->update = OMAP3ISP_CCDC_BLCLAMP;
2550 ccdc_apply_controls(ccdc);
2551
2552 ret = ccdc_init_entities(ccdc);
2553 if (ret < 0) {
2554 mutex_destroy(&ccdc->ioctl_lock);
2555 return ret;
2556 }
2557
2558 return 0;
2559}
2560
2561/*
2562 * omap3isp_ccdc_cleanup - CCDC module cleanup.
2563 * @dev: Device pointer specific to the OMAP3 ISP.
2564 */
2565void omap3isp_ccdc_cleanup(struct isp_device *isp)
2566{
2567 struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
2568
2569 omap3isp_video_cleanup(&ccdc->video_out);
2570 media_entity_cleanup(&ccdc->subdev.entity);
2571
2572 /* Free LSC requests. As the CCDC is stopped there's no active request,
2573 * so only the pending request and the free queue need to be handled.
2574 */
2575 ccdc_lsc_free_request(ccdc, ccdc->lsc.request);
2576 cancel_work_sync(&ccdc->lsc.table_work);
2577 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
2578
2579 if (ccdc->fpc.fpcaddr != 0)
2580 omap_iommu_vfree(isp->domain, isp->dev, ccdc->fpc.fpcaddr);
2581
2582 mutex_destroy(&ccdc->ioctl_lock);
2583}
diff --git a/drivers/media/platform/omap3isp/ispccdc.h b/drivers/media/platform/omap3isp/ispccdc.h
new file mode 100644
index 000000000000..a5da9e19edbf
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispccdc.h
@@ -0,0 +1,172 @@
1/*
2 * ispccdc.h
3 *
4 * TI OMAP3 ISP - CCDC module
5 *
6 * Copyright (C) 2009-2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#ifndef OMAP3_ISP_CCDC_H
28#define OMAP3_ISP_CCDC_H
29
30#include <linux/omap3isp.h>
31#include <linux/workqueue.h>
32
33#include "ispvideo.h"
34
35enum ccdc_input_entity {
36 CCDC_INPUT_NONE,
37 CCDC_INPUT_PARALLEL,
38 CCDC_INPUT_CSI2A,
39 CCDC_INPUT_CCP2B,
40 CCDC_INPUT_CSI2C
41};
42
43#define CCDC_OUTPUT_MEMORY (1 << 0)
44#define CCDC_OUTPUT_PREVIEW (1 << 1)
45#define CCDC_OUTPUT_RESIZER (1 << 2)
46
47#define OMAP3ISP_CCDC_NEVENTS 16
48
49enum ispccdc_lsc_state {
50 LSC_STATE_STOPPED = 0,
51 LSC_STATE_STOPPING = 1,
52 LSC_STATE_RUNNING = 2,
53 LSC_STATE_RECONFIG = 3,
54};
55
56struct ispccdc_lsc_config_req {
57 struct list_head list;
58 struct omap3isp_ccdc_lsc_config config;
59 unsigned char enable;
60 u32 table;
61 struct iovm_struct *iovm;
62};
63
64/*
65 * ispccdc_lsc - CCDC LSC parameters
66 * @update_config: Set when user changes config
67 * @request_enable: Whether LSC is requested to be enabled
68 * @config: LSC config set by user
69 * @update_table: Set when user provides a new LSC table to table_new
70 * @table_new: LSC table set by user, ISP address
71 * @table_inuse: LSC table currently in use, ISP address
72 */
73struct ispccdc_lsc {
74 enum ispccdc_lsc_state state;
75 struct work_struct table_work;
76
77 /* LSC queue of configurations */
78 spinlock_t req_lock;
79 struct ispccdc_lsc_config_req *request; /* requested configuration */
80 struct ispccdc_lsc_config_req *active; /* active configuration */
81 struct list_head free_queue; /* configurations for freeing */
82};
83
84#define CCDC_STOP_NOT_REQUESTED 0x00
85#define CCDC_STOP_REQUEST 0x01
86#define CCDC_STOP_EXECUTED (0x02 | CCDC_STOP_REQUEST)
87#define CCDC_STOP_CCDC_FINISHED 0x04
88#define CCDC_STOP_LSC_FINISHED 0x08
89#define CCDC_STOP_FINISHED \
90 (CCDC_STOP_EXECUTED | CCDC_STOP_CCDC_FINISHED | CCDC_STOP_LSC_FINISHED)
91
92#define CCDC_EVENT_VD1 0x10
93#define CCDC_EVENT_VD0 0x20
94#define CCDC_EVENT_LSC_DONE 0x40
95
96/* Sink and source CCDC pads */
97#define CCDC_PAD_SINK 0
98#define CCDC_PAD_SOURCE_OF 1
99#define CCDC_PAD_SOURCE_VP 2
100#define CCDC_PADS_NUM 3
101
102/*
103 * struct isp_ccdc_device - Structure for the CCDC module to store its own
104 * information
105 * @subdev: V4L2 subdevice
106 * @pads: Sink and source media entity pads
107 * @formats: Active video formats
108 * @crop: Active crop rectangle on the OF source pad
109 * @input: Active input
110 * @output: Active outputs
111 * @video_out: Output video node
112 * @alaw: A-law compression enabled (1) or disabled (0)
113 * @lpf: Low pass filter enabled (1) or disabled (0)
114 * @obclamp: Optical-black clamp enabled (1) or disabled (0)
115 * @fpc_en: Faulty pixels correction enabled (1) or disabled (0)
116 * @blcomp: Black level compensation configuration
117 * @clamp: Optical-black or digital clamp configuration
118 * @fpc: Faulty pixels correction configuration
119 * @lsc: Lens shading compensation configuration
120 * @update: Bitmask of controls to update during the next interrupt
121 * @shadow_update: Controls update in progress by userspace
122 * @underrun: A buffer underrun occurred and a new buffer has been queued
123 * @state: Streaming state
124 * @lock: Serializes shadow_update with interrupt handler
125 * @wait: Wait queue used to stop the module
126 * @stopping: Stopping state
127 * @ioctl_lock: Serializes ioctl calls and LSC requests freeing
128 */
129struct isp_ccdc_device {
130 struct v4l2_subdev subdev;
131 struct media_pad pads[CCDC_PADS_NUM];
132 struct v4l2_mbus_framefmt formats[CCDC_PADS_NUM];
133 struct v4l2_rect crop;
134
135 enum ccdc_input_entity input;
136 unsigned int output;
137 struct isp_video video_out;
138
139 unsigned int alaw:1,
140 lpf:1,
141 obclamp:1,
142 fpc_en:1;
143 struct omap3isp_ccdc_blcomp blcomp;
144 struct omap3isp_ccdc_bclamp clamp;
145 struct omap3isp_ccdc_fpc fpc;
146 struct ispccdc_lsc lsc;
147 unsigned int update;
148 unsigned int shadow_update;
149
150 unsigned int underrun:1;
151 enum isp_pipeline_stream_state state;
152 spinlock_t lock;
153 wait_queue_head_t wait;
154 unsigned int stopping;
155 struct mutex ioctl_lock;
156};
157
158struct isp_device;
159
160int omap3isp_ccdc_init(struct isp_device *isp);
161void omap3isp_ccdc_cleanup(struct isp_device *isp);
162int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
163 struct v4l2_device *vdev);
164void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc);
165
166int omap3isp_ccdc_busy(struct isp_ccdc_device *isp_ccdc);
167int omap3isp_ccdc_isr(struct isp_ccdc_device *isp_ccdc, u32 events);
168void omap3isp_ccdc_restore_context(struct isp_device *isp);
169void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
170 unsigned int *max_rate);
171
172#endif /* OMAP3_ISP_CCDC_H */
diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c
new file mode 100644
index 000000000000..85f0de85f37c
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispccp2.c
@@ -0,0 +1,1171 @@
1/*
2 * ispccp2.c
3 *
4 * TI OMAP3 ISP - CCP2 module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2010 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#include <linux/delay.h>
28#include <linux/device.h>
29#include <linux/mm.h>
30#include <linux/module.h>
31#include <linux/mutex.h>
32#include <linux/uaccess.h>
33#include <linux/regulator/consumer.h>
34
35#include "isp.h"
36#include "ispreg.h"
37#include "ispccp2.h"
38
39/* Number of LCX channels */
40#define CCP2_LCx_CHANS_NUM 3
41/* Max/Min size for CCP2 video port */
42#define ISPCCP2_DAT_START_MIN 0
43#define ISPCCP2_DAT_START_MAX 4095
44#define ISPCCP2_DAT_SIZE_MIN 0
45#define ISPCCP2_DAT_SIZE_MAX 4095
46#define ISPCCP2_VPCLK_FRACDIV 65536
47#define ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP 0x12
48#define ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP 0x16
49/* Max/Min size for CCP2 memory channel */
50#define ISPCCP2_LCM_HSIZE_COUNT_MIN 16
51#define ISPCCP2_LCM_HSIZE_COUNT_MAX 8191
52#define ISPCCP2_LCM_HSIZE_SKIP_MIN 0
53#define ISPCCP2_LCM_HSIZE_SKIP_MAX 8191
54#define ISPCCP2_LCM_VSIZE_MIN 1
55#define ISPCCP2_LCM_VSIZE_MAX 8191
56#define ISPCCP2_LCM_HWORDS_MIN 1
57#define ISPCCP2_LCM_HWORDS_MAX 4095
58#define ISPCCP2_LCM_CTRL_BURST_SIZE_32X 5
59#define ISPCCP2_LCM_CTRL_READ_THROTTLE_FULL 0
60#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10 2
61#define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8 2
62#define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10 3
63#define ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10 3
64#define ISPCCP2_LCM_CTRL_DST_PORT_VP 0
65#define ISPCCP2_LCM_CTRL_DST_PORT_MEM 1
66
67/* Set only the required bits */
68#define BIT_SET(var, shift, mask, val) \
69 do { \
70 var = ((var) & ~((mask) << (shift))) \
71 | ((val) << (shift)); \
72 } while (0)
73
74/*
75 * ccp2_print_status - Print current CCP2 module register values.
76 */
77#define CCP2_PRINT_REGISTER(isp, name)\
78 dev_dbg(isp->dev, "###CCP2 " #name "=0x%08x\n", \
79 isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_##name))
80
81static void ccp2_print_status(struct isp_ccp2_device *ccp2)
82{
83 struct isp_device *isp = to_isp_device(ccp2);
84
85 dev_dbg(isp->dev, "-------------CCP2 Register dump-------------\n");
86
87 CCP2_PRINT_REGISTER(isp, SYSCONFIG);
88 CCP2_PRINT_REGISTER(isp, SYSSTATUS);
89 CCP2_PRINT_REGISTER(isp, LC01_IRQENABLE);
90 CCP2_PRINT_REGISTER(isp, LC01_IRQSTATUS);
91 CCP2_PRINT_REGISTER(isp, LC23_IRQENABLE);
92 CCP2_PRINT_REGISTER(isp, LC23_IRQSTATUS);
93 CCP2_PRINT_REGISTER(isp, LCM_IRQENABLE);
94 CCP2_PRINT_REGISTER(isp, LCM_IRQSTATUS);
95 CCP2_PRINT_REGISTER(isp, CTRL);
96 CCP2_PRINT_REGISTER(isp, LCx_CTRL(0));
97 CCP2_PRINT_REGISTER(isp, LCx_CODE(0));
98 CCP2_PRINT_REGISTER(isp, LCx_STAT_START(0));
99 CCP2_PRINT_REGISTER(isp, LCx_STAT_SIZE(0));
100 CCP2_PRINT_REGISTER(isp, LCx_SOF_ADDR(0));
101 CCP2_PRINT_REGISTER(isp, LCx_EOF_ADDR(0));
102 CCP2_PRINT_REGISTER(isp, LCx_DAT_START(0));
103 CCP2_PRINT_REGISTER(isp, LCx_DAT_SIZE(0));
104 CCP2_PRINT_REGISTER(isp, LCx_DAT_PING_ADDR(0));
105 CCP2_PRINT_REGISTER(isp, LCx_DAT_PONG_ADDR(0));
106 CCP2_PRINT_REGISTER(isp, LCx_DAT_OFST(0));
107 CCP2_PRINT_REGISTER(isp, LCM_CTRL);
108 CCP2_PRINT_REGISTER(isp, LCM_VSIZE);
109 CCP2_PRINT_REGISTER(isp, LCM_HSIZE);
110 CCP2_PRINT_REGISTER(isp, LCM_PREFETCH);
111 CCP2_PRINT_REGISTER(isp, LCM_SRC_ADDR);
112 CCP2_PRINT_REGISTER(isp, LCM_SRC_OFST);
113 CCP2_PRINT_REGISTER(isp, LCM_DST_ADDR);
114 CCP2_PRINT_REGISTER(isp, LCM_DST_OFST);
115
116 dev_dbg(isp->dev, "--------------------------------------------\n");
117}
118
119/*
120 * ccp2_reset - Reset the CCP2
121 * @ccp2: pointer to ISP CCP2 device
122 */
123static void ccp2_reset(struct isp_ccp2_device *ccp2)
124{
125 struct isp_device *isp = to_isp_device(ccp2);
126 int i = 0;
127
128 /* Reset the CSI1/CCP2B and wait for reset to complete */
129 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG,
130 ISPCCP2_SYSCONFIG_SOFT_RESET);
131 while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSSTATUS) &
132 ISPCCP2_SYSSTATUS_RESET_DONE)) {
133 udelay(10);
134 if (i++ > 10) { /* try read 10 times */
135 dev_warn(isp->dev,
136 "omap3_isp: timeout waiting for ccp2 reset\n");
137 break;
138 }
139 }
140}
141
142/*
143 * ccp2_pwr_cfg - Configure the power mode settings
144 * @ccp2: pointer to ISP CCP2 device
145 */
146static void ccp2_pwr_cfg(struct isp_ccp2_device *ccp2)
147{
148 struct isp_device *isp = to_isp_device(ccp2);
149
150 isp_reg_writel(isp, ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SMART |
151 ((isp->revision == ISP_REVISION_15_0 && isp->autoidle) ?
152 ISPCCP2_SYSCONFIG_AUTO_IDLE : 0),
153 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG);
154}
155
156/*
157 * ccp2_if_enable - Enable CCP2 interface.
158 * @ccp2: pointer to ISP CCP2 device
159 * @enable: enable/disable flag
160 */
161static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable)
162{
163 struct isp_device *isp = to_isp_device(ccp2);
164 int i;
165
166 if (enable && ccp2->vdds_csib)
167 regulator_enable(ccp2->vdds_csib);
168
169 /* Enable/Disable all the LCx channels */
170 for (i = 0; i < CCP2_LCx_CHANS_NUM; i++)
171 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i),
172 ISPCCP2_LCx_CTRL_CHAN_EN,
173 enable ? ISPCCP2_LCx_CTRL_CHAN_EN : 0);
174
175 /* Enable/Disable ccp2 interface in ccp2 mode */
176 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
177 ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN,
178 enable ? (ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN) : 0);
179
180 if (!enable && ccp2->vdds_csib)
181 regulator_disable(ccp2->vdds_csib);
182}
183
184/*
185 * ccp2_mem_enable - Enable CCP2 memory interface.
186 * @ccp2: pointer to ISP CCP2 device
187 * @enable: enable/disable flag
188 */
189static void ccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable)
190{
191 struct isp_device *isp = to_isp_device(ccp2);
192
193 if (enable)
194 ccp2_if_enable(ccp2, 0);
195
196 /* Enable/Disable ccp2 interface in ccp2 mode */
197 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
198 ISPCCP2_CTRL_MODE, enable ? ISPCCP2_CTRL_MODE : 0);
199
200 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL,
201 ISPCCP2_LCM_CTRL_CHAN_EN,
202 enable ? ISPCCP2_LCM_CTRL_CHAN_EN : 0);
203}
204
205/*
206 * ccp2_phyif_config - Initialize CCP2 phy interface config
207 * @ccp2: Pointer to ISP CCP2 device
208 * @config: CCP2 platform data
209 *
210 * Configure the CCP2 physical interface module from platform data.
211 *
212 * Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success.
213 */
214static int ccp2_phyif_config(struct isp_ccp2_device *ccp2,
215 const struct isp_ccp2_platform_data *pdata)
216{
217 struct isp_device *isp = to_isp_device(ccp2);
218 u32 val;
219
220 /* CCP2B mode */
221 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL) |
222 ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE;
223 /* Data/strobe physical layer */
224 BIT_SET(val, ISPCCP2_CTRL_PHY_SEL_SHIFT, ISPCCP2_CTRL_PHY_SEL_MASK,
225 pdata->phy_layer);
226 BIT_SET(val, ISPCCP2_CTRL_INV_SHIFT, ISPCCP2_CTRL_INV_MASK,
227 pdata->strobe_clk_pol);
228 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
229
230 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
231 if (!(val & ISPCCP2_CTRL_MODE)) {
232 if (pdata->ccp2_mode == ISP_CCP2_MODE_CCP2)
233 dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");
234 if (pdata->phy_layer == ISP_CCP2_PHY_DATA_STROBE)
235 /* Strobe mode requires CCP2 */
236 return -EIO;
237 }
238
239 return 0;
240}
241
242/*
243 * ccp2_vp_config - Initialize CCP2 video port interface.
244 * @ccp2: Pointer to ISP CCP2 device
245 * @vpclk_div: Video port divisor
246 *
247 * Configure the CCP2 video port with the given clock divisor. The valid divisor
248 * values depend on the ISP revision:
249 *
250 * - revision 1.0 and 2.0 1 to 4
251 * - revision 15.0 1 to 65536
252 *
253 * The exact divisor value used might differ from the requested value, as ISP
254 * revision 15.0 represent the divisor by 65536 divided by an integer.
255 */
256static void ccp2_vp_config(struct isp_ccp2_device *ccp2,
257 unsigned int vpclk_div)
258{
259 struct isp_device *isp = to_isp_device(ccp2);
260 u32 val;
261
262 /* ISPCCP2_CTRL Video port */
263 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
264 val |= ISPCCP2_CTRL_VP_ONLY_EN; /* Disable the memory write port */
265
266 if (isp->revision == ISP_REVISION_15_0) {
267 vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 65536);
268 vpclk_div = min(ISPCCP2_VPCLK_FRACDIV / vpclk_div, 65535U);
269 BIT_SET(val, ISPCCP2_CTRL_VPCLK_DIV_SHIFT,
270 ISPCCP2_CTRL_VPCLK_DIV_MASK, vpclk_div);
271 } else {
272 vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 4);
273 BIT_SET(val, ISPCCP2_CTRL_VP_OUT_CTRL_SHIFT,
274 ISPCCP2_CTRL_VP_OUT_CTRL_MASK, vpclk_div - 1);
275 }
276
277 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
278}
279
280/*
281 * ccp2_lcx_config - Initialize CCP2 logical channel interface.
282 * @ccp2: Pointer to ISP CCP2 device
283 * @config: Pointer to ISP LCx config structure.
284 *
285 * This will analyze the parameters passed by the interface config
286 * and configure CSI1/CCP2 logical channel
287 *
288 */
289static void ccp2_lcx_config(struct isp_ccp2_device *ccp2,
290 struct isp_interface_lcx_config *config)
291{
292 struct isp_device *isp = to_isp_device(ccp2);
293 u32 val, format;
294
295 switch (config->format) {
296 case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
297 format = ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP;
298 break;
299 case V4L2_MBUS_FMT_SGRBG10_1X10:
300 default:
301 format = ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP; /* RAW10+VP */
302 break;
303 }
304 /* ISPCCP2_LCx_CTRL logical channel #0 */
305 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0))
306 | (ISPCCP2_LCx_CTRL_REGION_EN); /* Region */
307
308 if (isp->revision == ISP_REVISION_15_0) {
309 /* CRC */
310 BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT_15_0,
311 ISPCCP2_LCx_CTRL_CRC_MASK,
312 config->crc);
313 /* Format = RAW10+VP or RAW8+DPCM10+VP*/
314 BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT_15_0,
315 ISPCCP2_LCx_CTRL_FORMAT_MASK_15_0, format);
316 } else {
317 BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT,
318 ISPCCP2_LCx_CTRL_CRC_MASK,
319 config->crc);
320
321 BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT,
322 ISPCCP2_LCx_CTRL_FORMAT_MASK, format);
323 }
324 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0));
325
326 /* ISPCCP2_DAT_START for logical channel #0 */
327 isp_reg_writel(isp, config->data_start << ISPCCP2_LCx_DAT_SHIFT,
328 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_START(0));
329
330 /* ISPCCP2_DAT_SIZE for logical channel #0 */
331 isp_reg_writel(isp, config->data_size << ISPCCP2_LCx_DAT_SHIFT,
332 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_SIZE(0));
333
334 /* Enable error IRQs for logical channel #0 */
335 val = ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
336 ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
337 ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |
338 ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |
339 ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |
340 ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;
341
342 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQSTATUS);
343 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, val);
344}
345
346/*
347 * ccp2_if_configure - Configure ccp2 with data from sensor
348 * @ccp2: Pointer to ISP CCP2 device
349 *
350 * Return 0 on success or a negative error code
351 */
352static int ccp2_if_configure(struct isp_ccp2_device *ccp2)
353{
354 const struct isp_v4l2_subdevs_group *pdata;
355 struct v4l2_mbus_framefmt *format;
356 struct media_pad *pad;
357 struct v4l2_subdev *sensor;
358 u32 lines = 0;
359 int ret;
360
361 ccp2_pwr_cfg(ccp2);
362
363 pad = media_entity_remote_source(&ccp2->pads[CCP2_PAD_SINK]);
364 sensor = media_entity_to_v4l2_subdev(pad->entity);
365 pdata = sensor->host_priv;
366
367 ret = ccp2_phyif_config(ccp2, &pdata->bus.ccp2);
368 if (ret < 0)
369 return ret;
370
371 ccp2_vp_config(ccp2, pdata->bus.ccp2.vpclk_div + 1);
372
373 v4l2_subdev_call(sensor, sensor, g_skip_top_lines, &lines);
374
375 format = &ccp2->formats[CCP2_PAD_SINK];
376
377 ccp2->if_cfg.data_start = lines;
378 ccp2->if_cfg.crc = pdata->bus.ccp2.crc;
379 ccp2->if_cfg.format = format->code;
380 ccp2->if_cfg.data_size = format->height;
381
382 ccp2_lcx_config(ccp2, &ccp2->if_cfg);
383
384 return 0;
385}
386
387static int ccp2_adjust_bandwidth(struct isp_ccp2_device *ccp2)
388{
389 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
390 struct isp_device *isp = to_isp_device(ccp2);
391 const struct v4l2_mbus_framefmt *ofmt = &ccp2->formats[CCP2_PAD_SOURCE];
392 unsigned long l3_ick = pipe->l3_ick;
393 struct v4l2_fract *timeperframe;
394 unsigned int vpclk_div = 2;
395 unsigned int value;
396 u64 bound;
397 u64 area;
398
399 /* Compute the minimum clock divisor, based on the pipeline maximum
400 * data rate. This is an absolute lower bound if we don't want SBL
401 * overflows, so round the value up.
402 */
403 vpclk_div = max_t(unsigned int, DIV_ROUND_UP(l3_ick, pipe->max_rate),
404 vpclk_div);
405
406 /* Compute the maximum clock divisor, based on the requested frame rate.
407 * This is a soft lower bound to achieve a frame rate equal or higher
408 * than the requested value, so round the value down.
409 */
410 timeperframe = &pipe->max_timeperframe;
411
412 if (timeperframe->numerator) {
413 area = ofmt->width * ofmt->height;
414 bound = div_u64(area * timeperframe->denominator,
415 timeperframe->numerator);
416 value = min_t(u64, bound, l3_ick);
417 vpclk_div = max_t(unsigned int, l3_ick / value, vpclk_div);
418 }
419
420 dev_dbg(isp->dev, "%s: minimum clock divisor = %u\n", __func__,
421 vpclk_div);
422
423 return vpclk_div;
424}
425
426/*
427 * ccp2_mem_configure - Initialize CCP2 memory input/output interface
428 * @ccp2: Pointer to ISP CCP2 device
429 * @config: Pointer to ISP mem interface config structure
430 *
431 * This will analyze the parameters passed by the interface config
432 * structure, and configure the respective registers for proper
433 * CSI1/CCP2 memory input.
434 */
435static void ccp2_mem_configure(struct isp_ccp2_device *ccp2,
436 struct isp_interface_mem_config *config)
437{
438 struct isp_device *isp = to_isp_device(ccp2);
439 u32 sink_pixcode = ccp2->formats[CCP2_PAD_SINK].code;
440 u32 source_pixcode = ccp2->formats[CCP2_PAD_SOURCE].code;
441 unsigned int dpcm_decompress = 0;
442 u32 val, hwords;
443
444 if (sink_pixcode != source_pixcode &&
445 sink_pixcode == V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
446 dpcm_decompress = 1;
447
448 ccp2_pwr_cfg(ccp2);
449
450 /* Hsize, Skip */
451 isp_reg_writel(isp, ISPCCP2_LCM_HSIZE_SKIP_MIN |
452 (config->hsize_count << ISPCCP2_LCM_HSIZE_SHIFT),
453 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_HSIZE);
454
455 /* Vsize, no. of lines */
456 isp_reg_writel(isp, config->vsize_count << ISPCCP2_LCM_VSIZE_SHIFT,
457 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_VSIZE);
458
459 if (ccp2->video_in.bpl_padding == 0)
460 config->src_ofst = 0;
461 else
462 config->src_ofst = ccp2->video_in.bpl_value;
463
464 isp_reg_writel(isp, config->src_ofst, OMAP3_ISP_IOMEM_CCP2,
465 ISPCCP2_LCM_SRC_OFST);
466
467 /* Source and Destination formats */
468 val = ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10 <<
469 ISPCCP2_LCM_CTRL_DST_FORMAT_SHIFT;
470
471 if (dpcm_decompress) {
472 /* source format is RAW8 */
473 val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8 <<
474 ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;
475
476 /* RAW8 + DPCM10 - simple predictor */
477 val |= ISPCCP2_LCM_CTRL_SRC_DPCM_PRED;
478
479 /* enable source DPCM decompression */
480 val |= ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10 <<
481 ISPCCP2_LCM_CTRL_SRC_DECOMPR_SHIFT;
482 } else {
483 /* source format is RAW10 */
484 val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10 <<
485 ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;
486 }
487
488 /* Burst size to 32x64 */
489 val |= ISPCCP2_LCM_CTRL_BURST_SIZE_32X <<
490 ISPCCP2_LCM_CTRL_BURST_SIZE_SHIFT;
491
492 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL);
493
494 /* Prefetch setup */
495 if (dpcm_decompress)
496 hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +
497 config->hsize_count) >> 3;
498 else
499 hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +
500 config->hsize_count) >> 2;
501
502 isp_reg_writel(isp, hwords << ISPCCP2_LCM_PREFETCH_SHIFT,
503 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_PREFETCH);
504
505 /* Video port */
506 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
507 ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE);
508 ccp2_vp_config(ccp2, ccp2_adjust_bandwidth(ccp2));
509
510 /* Clear LCM interrupts */
511 isp_reg_writel(isp, ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ |
512 ISPCCP2_LCM_IRQSTATUS_EOF_IRQ,
513 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQSTATUS);
514
515 /* Enable LCM interupts */
516 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQENABLE,
517 ISPCCP2_LCM_IRQSTATUS_EOF_IRQ |
518 ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ);
519}
520
521/*
522 * ccp2_set_inaddr - Sets memory address of input frame.
523 * @ccp2: Pointer to ISP CCP2 device
524 * @addr: 32bit memory address aligned on 32byte boundary.
525 *
526 * Configures the memory address from which the input frame is to be read.
527 */
528static void ccp2_set_inaddr(struct isp_ccp2_device *ccp2, u32 addr)
529{
530 struct isp_device *isp = to_isp_device(ccp2);
531
532 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_SRC_ADDR);
533}
534
535/* -----------------------------------------------------------------------------
536 * Interrupt handling
537 */
538
539static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
540{
541 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
542 struct isp_buffer *buffer;
543
544 buffer = omap3isp_video_buffer_next(&ccp2->video_in);
545 if (buffer != NULL)
546 ccp2_set_inaddr(ccp2, buffer->isp_addr);
547
548 pipe->state |= ISP_PIPELINE_IDLE_INPUT;
549
550 if (ccp2->state == ISP_PIPELINE_STREAM_SINGLESHOT) {
551 if (isp_pipeline_ready(pipe))
552 omap3isp_pipeline_set_stream(pipe,
553 ISP_PIPELINE_STREAM_SINGLESHOT);
554 }
555}
556
557/*
558 * omap3isp_ccp2_isr - Handle ISP CCP2 interrupts
559 * @ccp2: Pointer to ISP CCP2 device
560 *
561 * This will handle the CCP2 interrupts
562 */
563void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
564{
565 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
566 struct isp_device *isp = to_isp_device(ccp2);
567 static const u32 ISPCCP2_LC01_ERROR =
568 ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
569 ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
570 ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |
571 ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |
572 ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |
573 ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;
574 u32 lcx_irqstatus, lcm_irqstatus;
575
576 /* First clear the interrupts */
577 lcx_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,
578 ISPCCP2_LC01_IRQSTATUS);
579 isp_reg_writel(isp, lcx_irqstatus, OMAP3_ISP_IOMEM_CCP2,
580 ISPCCP2_LC01_IRQSTATUS);
581
582 lcm_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,
583 ISPCCP2_LCM_IRQSTATUS);
584 isp_reg_writel(isp, lcm_irqstatus, OMAP3_ISP_IOMEM_CCP2,
585 ISPCCP2_LCM_IRQSTATUS);
586 /* Errors */
587 if (lcx_irqstatus & ISPCCP2_LC01_ERROR) {
588 pipe->error = true;
589 dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus);
590 return;
591 }
592
593 if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) {
594 pipe->error = true;
595 dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus);
596 }
597
598 if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping))
599 return;
600
601 /* Handle queued buffers on frame end interrupts */
602 if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ)
603 ccp2_isr_buffer(ccp2);
604}
605
606/* -----------------------------------------------------------------------------
607 * V4L2 subdev operations
608 */
609
610static const unsigned int ccp2_fmts[] = {
611 V4L2_MBUS_FMT_SGRBG10_1X10,
612 V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
613};
614
615/*
616 * __ccp2_get_format - helper function for getting ccp2 format
617 * @ccp2 : Pointer to ISP CCP2 device
618 * @fh : V4L2 subdev file handle
619 * @pad : pad number
620 * @which : wanted subdev format
621 * return format structure or NULL on error
622 */
623static struct v4l2_mbus_framefmt *
624__ccp2_get_format(struct isp_ccp2_device *ccp2, struct v4l2_subdev_fh *fh,
625 unsigned int pad, enum v4l2_subdev_format_whence which)
626{
627 if (which == V4L2_SUBDEV_FORMAT_TRY)
628 return v4l2_subdev_get_try_format(fh, pad);
629 else
630 return &ccp2->formats[pad];
631}
632
633/*
634 * ccp2_try_format - Handle try format by pad subdev method
635 * @ccp2 : Pointer to ISP CCP2 device
636 * @fh : V4L2 subdev file handle
637 * @pad : pad num
638 * @fmt : pointer to v4l2 mbus format structure
639 * @which : wanted subdev format
640 */
641static void ccp2_try_format(struct isp_ccp2_device *ccp2,
642 struct v4l2_subdev_fh *fh, unsigned int pad,
643 struct v4l2_mbus_framefmt *fmt,
644 enum v4l2_subdev_format_whence which)
645{
646 struct v4l2_mbus_framefmt *format;
647
648 switch (pad) {
649 case CCP2_PAD_SINK:
650 if (fmt->code != V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
651 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
652
653 if (ccp2->input == CCP2_INPUT_SENSOR) {
654 fmt->width = clamp_t(u32, fmt->width,
655 ISPCCP2_DAT_START_MIN,
656 ISPCCP2_DAT_START_MAX);
657 fmt->height = clamp_t(u32, fmt->height,
658 ISPCCP2_DAT_SIZE_MIN,
659 ISPCCP2_DAT_SIZE_MAX);
660 } else if (ccp2->input == CCP2_INPUT_MEMORY) {
661 fmt->width = clamp_t(u32, fmt->width,
662 ISPCCP2_LCM_HSIZE_COUNT_MIN,
663 ISPCCP2_LCM_HSIZE_COUNT_MAX);
664 fmt->height = clamp_t(u32, fmt->height,
665 ISPCCP2_LCM_VSIZE_MIN,
666 ISPCCP2_LCM_VSIZE_MAX);
667 }
668 break;
669
670 case CCP2_PAD_SOURCE:
671 /* Source format - copy sink format and change pixel code
672 * to SGRBG10_1X10 as we don't support CCP2 write to memory.
673 * When CCP2 write to memory feature will be added this
674 * should be changed properly.
675 */
676 format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK, which);
677 memcpy(fmt, format, sizeof(*fmt));
678 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
679 break;
680 }
681
682 fmt->field = V4L2_FIELD_NONE;
683 fmt->colorspace = V4L2_COLORSPACE_SRGB;
684}
685
686/*
687 * ccp2_enum_mbus_code - Handle pixel format enumeration
688 * @sd : pointer to v4l2 subdev structure
689 * @fh : V4L2 subdev file handle
690 * @code : pointer to v4l2_subdev_mbus_code_enum structure
691 * return -EINVAL or zero on success
692 */
693static int ccp2_enum_mbus_code(struct v4l2_subdev *sd,
694 struct v4l2_subdev_fh *fh,
695 struct v4l2_subdev_mbus_code_enum *code)
696{
697 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
698 struct v4l2_mbus_framefmt *format;
699
700 if (code->pad == CCP2_PAD_SINK) {
701 if (code->index >= ARRAY_SIZE(ccp2_fmts))
702 return -EINVAL;
703
704 code->code = ccp2_fmts[code->index];
705 } else {
706 if (code->index != 0)
707 return -EINVAL;
708
709 format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK,
710 V4L2_SUBDEV_FORMAT_TRY);
711 code->code = format->code;
712 }
713
714 return 0;
715}
716
717static int ccp2_enum_frame_size(struct v4l2_subdev *sd,
718 struct v4l2_subdev_fh *fh,
719 struct v4l2_subdev_frame_size_enum *fse)
720{
721 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
722 struct v4l2_mbus_framefmt format;
723
724 if (fse->index != 0)
725 return -EINVAL;
726
727 format.code = fse->code;
728 format.width = 1;
729 format.height = 1;
730 ccp2_try_format(ccp2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
731 fse->min_width = format.width;
732 fse->min_height = format.height;
733
734 if (format.code != fse->code)
735 return -EINVAL;
736
737 format.code = fse->code;
738 format.width = -1;
739 format.height = -1;
740 ccp2_try_format(ccp2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
741 fse->max_width = format.width;
742 fse->max_height = format.height;
743
744 return 0;
745}
746
747/*
748 * ccp2_get_format - Handle get format by pads subdev method
749 * @sd : pointer to v4l2 subdev structure
750 * @fh : V4L2 subdev file handle
751 * @fmt : pointer to v4l2 subdev format structure
752 * return -EINVAL or zero on success
753 */
754static int ccp2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
755 struct v4l2_subdev_format *fmt)
756{
757 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
758 struct v4l2_mbus_framefmt *format;
759
760 format = __ccp2_get_format(ccp2, fh, fmt->pad, fmt->which);
761 if (format == NULL)
762 return -EINVAL;
763
764 fmt->format = *format;
765 return 0;
766}
767
768/*
769 * ccp2_set_format - Handle set format by pads subdev method
770 * @sd : pointer to v4l2 subdev structure
771 * @fh : V4L2 subdev file handle
772 * @fmt : pointer to v4l2 subdev format structure
773 * returns zero
774 */
775static int ccp2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
776 struct v4l2_subdev_format *fmt)
777{
778 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
779 struct v4l2_mbus_framefmt *format;
780
781 format = __ccp2_get_format(ccp2, fh, fmt->pad, fmt->which);
782 if (format == NULL)
783 return -EINVAL;
784
785 ccp2_try_format(ccp2, fh, fmt->pad, &fmt->format, fmt->which);
786 *format = fmt->format;
787
788 /* Propagate the format from sink to source */
789 if (fmt->pad == CCP2_PAD_SINK) {
790 format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SOURCE,
791 fmt->which);
792 *format = fmt->format;
793 ccp2_try_format(ccp2, fh, CCP2_PAD_SOURCE, format, fmt->which);
794 }
795
796 return 0;
797}
798
799/*
800 * ccp2_init_formats - Initialize formats on all pads
801 * @sd: ISP CCP2 V4L2 subdevice
802 * @fh: V4L2 subdev file handle
803 *
804 * Initialize all pad formats with default values. If fh is not NULL, try
805 * formats are initialized on the file handle. Otherwise active formats are
806 * initialized on the device.
807 */
808static int ccp2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
809{
810 struct v4l2_subdev_format format;
811
812 memset(&format, 0, sizeof(format));
813 format.pad = CCP2_PAD_SINK;
814 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
815 format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
816 format.format.width = 4096;
817 format.format.height = 4096;
818 ccp2_set_format(sd, fh, &format);
819
820 return 0;
821}
822
823/*
824 * ccp2_s_stream - Enable/Disable streaming on ccp2 subdev
825 * @sd : pointer to v4l2 subdev structure
826 * @enable: 1 == Enable, 0 == Disable
827 * return zero
828 */
829static int ccp2_s_stream(struct v4l2_subdev *sd, int enable)
830{
831 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
832 struct isp_device *isp = to_isp_device(ccp2);
833 struct device *dev = to_device(ccp2);
834 int ret;
835
836 if (ccp2->state == ISP_PIPELINE_STREAM_STOPPED) {
837 if (enable == ISP_PIPELINE_STREAM_STOPPED)
838 return 0;
839 atomic_set(&ccp2->stopping, 0);
840 }
841
842 switch (enable) {
843 case ISP_PIPELINE_STREAM_CONTINUOUS:
844 if (ccp2->phy) {
845 ret = omap3isp_csiphy_acquire(ccp2->phy);
846 if (ret < 0)
847 return ret;
848 }
849
850 ccp2_if_configure(ccp2);
851 ccp2_print_status(ccp2);
852
853 /* Enable CSI1/CCP2 interface */
854 ccp2_if_enable(ccp2, 1);
855 break;
856
857 case ISP_PIPELINE_STREAM_SINGLESHOT:
858 if (ccp2->state != ISP_PIPELINE_STREAM_SINGLESHOT) {
859 struct v4l2_mbus_framefmt *format;
860
861 format = &ccp2->formats[CCP2_PAD_SINK];
862
863 ccp2->mem_cfg.hsize_count = format->width;
864 ccp2->mem_cfg.vsize_count = format->height;
865 ccp2->mem_cfg.src_ofst = 0;
866
867 ccp2_mem_configure(ccp2, &ccp2->mem_cfg);
868 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI1_READ);
869 ccp2_print_status(ccp2);
870 }
871 ccp2_mem_enable(ccp2, 1);
872 break;
873
874 case ISP_PIPELINE_STREAM_STOPPED:
875 if (omap3isp_module_sync_idle(&sd->entity, &ccp2->wait,
876 &ccp2->stopping))
877 dev_dbg(dev, "%s: module stop timeout.\n", sd->name);
878 if (ccp2->input == CCP2_INPUT_MEMORY) {
879 ccp2_mem_enable(ccp2, 0);
880 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI1_READ);
881 } else if (ccp2->input == CCP2_INPUT_SENSOR) {
882 /* Disable CSI1/CCP2 interface */
883 ccp2_if_enable(ccp2, 0);
884 if (ccp2->phy)
885 omap3isp_csiphy_release(ccp2->phy);
886 }
887 break;
888 }
889
890 ccp2->state = enable;
891 return 0;
892}
893
894/* subdev video operations */
895static const struct v4l2_subdev_video_ops ccp2_sd_video_ops = {
896 .s_stream = ccp2_s_stream,
897};
898
899/* subdev pad operations */
900static const struct v4l2_subdev_pad_ops ccp2_sd_pad_ops = {
901 .enum_mbus_code = ccp2_enum_mbus_code,
902 .enum_frame_size = ccp2_enum_frame_size,
903 .get_fmt = ccp2_get_format,
904 .set_fmt = ccp2_set_format,
905};
906
907/* subdev operations */
908static const struct v4l2_subdev_ops ccp2_sd_ops = {
909 .video = &ccp2_sd_video_ops,
910 .pad = &ccp2_sd_pad_ops,
911};
912
913/* subdev internal operations */
914static const struct v4l2_subdev_internal_ops ccp2_sd_internal_ops = {
915 .open = ccp2_init_formats,
916};
917
918/* --------------------------------------------------------------------------
919 * ISP ccp2 video device node
920 */
921
922/*
923 * ccp2_video_queue - Queue video buffer.
924 * @video : Pointer to isp video structure
925 * @buffer: Pointer to isp_buffer structure
926 * return -EIO or zero on success
927 */
928static int ccp2_video_queue(struct isp_video *video, struct isp_buffer *buffer)
929{
930 struct isp_ccp2_device *ccp2 = &video->isp->isp_ccp2;
931
932 ccp2_set_inaddr(ccp2, buffer->isp_addr);
933 return 0;
934}
935
936static const struct isp_video_operations ccp2_video_ops = {
937 .queue = ccp2_video_queue,
938};
939
940/* -----------------------------------------------------------------------------
941 * Media entity operations
942 */
943
944/*
945 * ccp2_link_setup - Setup ccp2 connections.
946 * @entity : Pointer to media entity structure
947 * @local : Pointer to local pad array
948 * @remote : Pointer to remote pad array
949 * @flags : Link flags
950 * return -EINVAL on error or zero on success
951 */
952static int ccp2_link_setup(struct media_entity *entity,
953 const struct media_pad *local,
954 const struct media_pad *remote, u32 flags)
955{
956 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
957 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
958
959 switch (local->index | media_entity_type(remote->entity)) {
960 case CCP2_PAD_SINK | MEDIA_ENT_T_DEVNODE:
961 /* read from memory */
962 if (flags & MEDIA_LNK_FL_ENABLED) {
963 if (ccp2->input == CCP2_INPUT_SENSOR)
964 return -EBUSY;
965 ccp2->input = CCP2_INPUT_MEMORY;
966 } else {
967 if (ccp2->input == CCP2_INPUT_MEMORY)
968 ccp2->input = CCP2_INPUT_NONE;
969 }
970 break;
971
972 case CCP2_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
973 /* read from sensor/phy */
974 if (flags & MEDIA_LNK_FL_ENABLED) {
975 if (ccp2->input == CCP2_INPUT_MEMORY)
976 return -EBUSY;
977 ccp2->input = CCP2_INPUT_SENSOR;
978 } else {
979 if (ccp2->input == CCP2_INPUT_SENSOR)
980 ccp2->input = CCP2_INPUT_NONE;
981 } break;
982
983 case CCP2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
984 /* write to video port/ccdc */
985 if (flags & MEDIA_LNK_FL_ENABLED)
986 ccp2->output = CCP2_OUTPUT_CCDC;
987 else
988 ccp2->output = CCP2_OUTPUT_NONE;
989 break;
990
991 default:
992 return -EINVAL;
993 }
994
995 return 0;
996}
997
998/* media operations */
999static const struct media_entity_operations ccp2_media_ops = {
1000 .link_setup = ccp2_link_setup,
1001 .link_validate = v4l2_subdev_link_validate,
1002};
1003
1004/*
1005 * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev
1006 * @ccp2: Pointer to ISP CCP2 device
1007 */
1008void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)
1009{
1010 v4l2_device_unregister_subdev(&ccp2->subdev);
1011 omap3isp_video_unregister(&ccp2->video_in);
1012}
1013
1014/*
1015 * omap3isp_ccp2_register_entities - Register the subdev media entity
1016 * @ccp2: Pointer to ISP CCP2 device
1017 * @vdev: Pointer to v4l device
1018 * return negative error code or zero on success
1019 */
1020
1021int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
1022 struct v4l2_device *vdev)
1023{
1024 int ret;
1025
1026 /* Register the subdev and video nodes. */
1027 ret = v4l2_device_register_subdev(vdev, &ccp2->subdev);
1028 if (ret < 0)
1029 goto error;
1030
1031 ret = omap3isp_video_register(&ccp2->video_in, vdev);
1032 if (ret < 0)
1033 goto error;
1034
1035 return 0;
1036
1037error:
1038 omap3isp_ccp2_unregister_entities(ccp2);
1039 return ret;
1040}
1041
1042/* -----------------------------------------------------------------------------
1043 * ISP ccp2 initialisation and cleanup
1044 */
1045
1046/*
1047 * ccp2_init_entities - Initialize ccp2 subdev and media entity.
1048 * @ccp2: Pointer to ISP CCP2 device
1049 * return negative error code or zero on success
1050 */
1051static int ccp2_init_entities(struct isp_ccp2_device *ccp2)
1052{
1053 struct v4l2_subdev *sd = &ccp2->subdev;
1054 struct media_pad *pads = ccp2->pads;
1055 struct media_entity *me = &sd->entity;
1056 int ret;
1057
1058 ccp2->input = CCP2_INPUT_NONE;
1059 ccp2->output = CCP2_OUTPUT_NONE;
1060
1061 v4l2_subdev_init(sd, &ccp2_sd_ops);
1062 sd->internal_ops = &ccp2_sd_internal_ops;
1063 strlcpy(sd->name, "OMAP3 ISP CCP2", sizeof(sd->name));
1064 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
1065 v4l2_set_subdevdata(sd, ccp2);
1066 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1067
1068 pads[CCP2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1069 pads[CCP2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1070
1071 me->ops = &ccp2_media_ops;
1072 ret = media_entity_init(me, CCP2_PADS_NUM, pads, 0);
1073 if (ret < 0)
1074 return ret;
1075
1076 ccp2_init_formats(sd, NULL);
1077
1078 /*
1079 * The CCP2 has weird line alignment requirements, possibly caused by
1080 * DPCM8 decompression. Line length for data read from memory must be a
1081 * multiple of 128 bits (16 bytes) in continuous mode (when no padding
1082 * is present at end of lines). Additionally, if padding is used, the
1083 * padded line length must be a multiple of 32 bytes. To simplify the
1084 * implementation we use a fixed 32 bytes alignment regardless of the
1085 * input format and width. If strict 128 bits alignment support is
1086 * required ispvideo will need to be made aware of this special dual
1087 * alignement requirements.
1088 */
1089 ccp2->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1090 ccp2->video_in.bpl_alignment = 32;
1091 ccp2->video_in.bpl_max = 0xffffffe0;
1092 ccp2->video_in.isp = to_isp_device(ccp2);
1093 ccp2->video_in.ops = &ccp2_video_ops;
1094 ccp2->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
1095
1096 ret = omap3isp_video_init(&ccp2->video_in, "CCP2");
1097 if (ret < 0)
1098 goto error_video;
1099
1100 /* Connect the video node to the ccp2 subdev. */
1101 ret = media_entity_create_link(&ccp2->video_in.video.entity, 0,
1102 &ccp2->subdev.entity, CCP2_PAD_SINK, 0);
1103 if (ret < 0)
1104 goto error_link;
1105
1106 return 0;
1107
1108error_link:
1109 omap3isp_video_cleanup(&ccp2->video_in);
1110error_video:
1111 media_entity_cleanup(&ccp2->subdev.entity);
1112 return ret;
1113}
1114
1115/*
1116 * omap3isp_ccp2_init - CCP2 initialization.
1117 * @isp : Pointer to ISP device
1118 * return negative error code or zero on success
1119 */
1120int omap3isp_ccp2_init(struct isp_device *isp)
1121{
1122 struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
1123 int ret;
1124
1125 init_waitqueue_head(&ccp2->wait);
1126
1127 /*
1128 * On the OMAP34xx the CSI1 receiver is operated in the CSIb IO
1129 * complex, which is powered by vdds_csib power rail. Hence the
1130 * request for the regulator.
1131 *
1132 * On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with
1133 * the CSI2c or CSI2a receivers. The PHY then needs to be explicitly
1134 * configured.
1135 *
1136 * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c).
1137 */
1138 if (isp->revision == ISP_REVISION_2_0) {
1139 ccp2->vdds_csib = regulator_get(isp->dev, "vdds_csib");
1140 if (IS_ERR(ccp2->vdds_csib)) {
1141 dev_dbg(isp->dev,
1142 "Could not get regulator vdds_csib\n");
1143 ccp2->vdds_csib = NULL;
1144 }
1145 } else if (isp->revision == ISP_REVISION_15_0) {
1146 ccp2->phy = &isp->isp_csiphy1;
1147 }
1148
1149 ret = ccp2_init_entities(ccp2);
1150 if (ret < 0) {
1151 regulator_put(ccp2->vdds_csib);
1152 return ret;
1153 }
1154
1155 ccp2_reset(ccp2);
1156 return 0;
1157}
1158
1159/*
1160 * omap3isp_ccp2_cleanup - CCP2 un-initialization
1161 * @isp : Pointer to ISP device
1162 */
1163void omap3isp_ccp2_cleanup(struct isp_device *isp)
1164{
1165 struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
1166
1167 omap3isp_video_cleanup(&ccp2->video_in);
1168 media_entity_cleanup(&ccp2->subdev.entity);
1169
1170 regulator_put(ccp2->vdds_csib);
1171}
diff --git a/drivers/media/platform/omap3isp/ispccp2.h b/drivers/media/platform/omap3isp/ispccp2.h
new file mode 100644
index 000000000000..76d65f4576ef
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispccp2.h
@@ -0,0 +1,98 @@
1/*
2 * ispccp2.h
3 *
4 * TI OMAP3 ISP - CCP2 module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2010 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#ifndef OMAP3_ISP_CCP2_H
28#define OMAP3_ISP_CCP2_H
29
30#include <linux/videodev2.h>
31
32struct isp_device;
33struct isp_csiphy;
34
35/* Sink and source ccp2 pads */
36#define CCP2_PAD_SINK 0
37#define CCP2_PAD_SOURCE 1
38#define CCP2_PADS_NUM 2
39
40/* CCP2 input media entity */
41enum ccp2_input_entity {
42 CCP2_INPUT_NONE,
43 CCP2_INPUT_SENSOR,
44 CCP2_INPUT_MEMORY,
45};
46
47/* CCP2 output media entity */
48enum ccp2_output_entity {
49 CCP2_OUTPUT_NONE,
50 CCP2_OUTPUT_CCDC,
51 CCP2_OUTPUT_MEMORY,
52};
53
54
55/* Logical channel configuration */
56struct isp_interface_lcx_config {
57 int crc;
58 u32 data_start;
59 u32 data_size;
60 u32 format;
61};
62
63/* Memory channel configuration */
64struct isp_interface_mem_config {
65 u32 dst_port;
66 u32 vsize_count;
67 u32 hsize_count;
68 u32 src_ofst;
69 u32 dst_ofst;
70};
71
72/* CCP2 device */
73struct isp_ccp2_device {
74 struct v4l2_subdev subdev;
75 struct v4l2_mbus_framefmt formats[CCP2_PADS_NUM];
76 struct media_pad pads[CCP2_PADS_NUM];
77
78 enum ccp2_input_entity input;
79 enum ccp2_output_entity output;
80 struct isp_interface_lcx_config if_cfg;
81 struct isp_interface_mem_config mem_cfg;
82 struct isp_video video_in;
83 struct isp_csiphy *phy;
84 struct regulator *vdds_csib;
85 enum isp_pipeline_stream_state state;
86 wait_queue_head_t wait;
87 atomic_t stopping;
88};
89
90/* Function declarations */
91int omap3isp_ccp2_init(struct isp_device *isp);
92void omap3isp_ccp2_cleanup(struct isp_device *isp);
93int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
94 struct v4l2_device *vdev);
95void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2);
96void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
97
98#endif /* OMAP3_ISP_CCP2_H */
diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c
new file mode 100644
index 000000000000..6a3ff792af7d
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispcsi2.c
@@ -0,0 +1,1328 @@
1/*
2 * ispcsi2.c
3 *
4 * TI OMAP3 ISP - CSI2 module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26#include <linux/delay.h>
27#include <media/v4l2-common.h>
28#include <linux/v4l2-mediabus.h>
29#include <linux/mm.h>
30
31#include "isp.h"
32#include "ispreg.h"
33#include "ispcsi2.h"
34
35/*
36 * csi2_if_enable - Enable CSI2 Receiver interface.
37 * @enable: enable flag
38 *
39 */
40static void csi2_if_enable(struct isp_device *isp,
41 struct isp_csi2_device *csi2, u8 enable)
42{
43 struct isp_csi2_ctrl_cfg *currctrl = &csi2->ctrl;
44
45 isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_CTRL, ISPCSI2_CTRL_IF_EN,
46 enable ? ISPCSI2_CTRL_IF_EN : 0);
47
48 currctrl->if_enable = enable;
49}
50
51/*
52 * csi2_recv_config - CSI2 receiver module configuration.
53 * @currctrl: isp_csi2_ctrl_cfg structure
54 *
55 */
56static void csi2_recv_config(struct isp_device *isp,
57 struct isp_csi2_device *csi2,
58 struct isp_csi2_ctrl_cfg *currctrl)
59{
60 u32 reg;
61
62 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTRL);
63
64 if (currctrl->frame_mode)
65 reg |= ISPCSI2_CTRL_FRAME;
66 else
67 reg &= ~ISPCSI2_CTRL_FRAME;
68
69 if (currctrl->vp_clk_enable)
70 reg |= ISPCSI2_CTRL_VP_CLK_EN;
71 else
72 reg &= ~ISPCSI2_CTRL_VP_CLK_EN;
73
74 if (currctrl->vp_only_enable)
75 reg |= ISPCSI2_CTRL_VP_ONLY_EN;
76 else
77 reg &= ~ISPCSI2_CTRL_VP_ONLY_EN;
78
79 reg &= ~ISPCSI2_CTRL_VP_OUT_CTRL_MASK;
80 reg |= currctrl->vp_out_ctrl << ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT;
81
82 if (currctrl->ecc_enable)
83 reg |= ISPCSI2_CTRL_ECC_EN;
84 else
85 reg &= ~ISPCSI2_CTRL_ECC_EN;
86
87 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTRL);
88}
89
90static const unsigned int csi2_input_fmts[] = {
91 V4L2_MBUS_FMT_SGRBG10_1X10,
92 V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
93 V4L2_MBUS_FMT_SRGGB10_1X10,
94 V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
95 V4L2_MBUS_FMT_SBGGR10_1X10,
96 V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
97 V4L2_MBUS_FMT_SGBRG10_1X10,
98 V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
99 V4L2_MBUS_FMT_YUYV8_2X8,
100};
101
102/* To set the format on the CSI2 requires a mapping function that takes
103 * the following inputs:
104 * - 3 different formats (at this time)
105 * - 2 destinations (mem, vp+mem) (vp only handled separately)
106 * - 2 decompression options (on, off)
107 * - 2 isp revisions (certain format must be handled differently on OMAP3630)
108 * Output should be CSI2 frame format code
109 * Array indices as follows: [format][dest][decompr][is_3630]
110 * Not all combinations are valid. 0 means invalid.
111 */
112static const u16 __csi2_fmt_map[3][2][2][2] = {
113 /* RAW10 formats */
114 {
115 /* Output to memory */
116 {
117 /* No DPCM decompression */
118 { CSI2_PIX_FMT_RAW10_EXP16, CSI2_PIX_FMT_RAW10_EXP16 },
119 /* DPCM decompression */
120 { 0, 0 },
121 },
122 /* Output to both */
123 {
124 /* No DPCM decompression */
125 { CSI2_PIX_FMT_RAW10_EXP16_VP,
126 CSI2_PIX_FMT_RAW10_EXP16_VP },
127 /* DPCM decompression */
128 { 0, 0 },
129 },
130 },
131 /* RAW10 DPCM8 formats */
132 {
133 /* Output to memory */
134 {
135 /* No DPCM decompression */
136 { CSI2_PIX_FMT_RAW8, CSI2_USERDEF_8BIT_DATA1 },
137 /* DPCM decompression */
138 { CSI2_PIX_FMT_RAW8_DPCM10_EXP16,
139 CSI2_USERDEF_8BIT_DATA1_DPCM10 },
140 },
141 /* Output to both */
142 {
143 /* No DPCM decompression */
144 { CSI2_PIX_FMT_RAW8_VP,
145 CSI2_PIX_FMT_RAW8_VP },
146 /* DPCM decompression */
147 { CSI2_PIX_FMT_RAW8_DPCM10_VP,
148 CSI2_USERDEF_8BIT_DATA1_DPCM10_VP },
149 },
150 },
151 /* YUYV8 2X8 formats */
152 {
153 /* Output to memory */
154 {
155 /* No DPCM decompression */
156 { CSI2_PIX_FMT_YUV422_8BIT,
157 CSI2_PIX_FMT_YUV422_8BIT },
158 /* DPCM decompression */
159 { 0, 0 },
160 },
161 /* Output to both */
162 {
163 /* No DPCM decompression */
164 { CSI2_PIX_FMT_YUV422_8BIT_VP,
165 CSI2_PIX_FMT_YUV422_8BIT_VP },
166 /* DPCM decompression */
167 { 0, 0 },
168 },
169 },
170};
171
172/*
173 * csi2_ctx_map_format - Map CSI2 sink media bus format to CSI2 format ID
174 * @csi2: ISP CSI2 device
175 *
176 * Returns CSI2 physical format id
177 */
178static u16 csi2_ctx_map_format(struct isp_csi2_device *csi2)
179{
180 const struct v4l2_mbus_framefmt *fmt = &csi2->formats[CSI2_PAD_SINK];
181 int fmtidx, destidx, is_3630;
182
183 switch (fmt->code) {
184 case V4L2_MBUS_FMT_SGRBG10_1X10:
185 case V4L2_MBUS_FMT_SRGGB10_1X10:
186 case V4L2_MBUS_FMT_SBGGR10_1X10:
187 case V4L2_MBUS_FMT_SGBRG10_1X10:
188 fmtidx = 0;
189 break;
190 case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
191 case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
192 case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
193 case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
194 fmtidx = 1;
195 break;
196 case V4L2_MBUS_FMT_YUYV8_2X8:
197 fmtidx = 2;
198 break;
199 default:
200 WARN(1, KERN_ERR "CSI2: pixel format %08x unsupported!\n",
201 fmt->code);
202 return 0;
203 }
204
205 if (!(csi2->output & CSI2_OUTPUT_CCDC) &&
206 !(csi2->output & CSI2_OUTPUT_MEMORY)) {
207 /* Neither output enabled is a valid combination */
208 return CSI2_PIX_FMT_OTHERS;
209 }
210
211 /* If we need to skip frames at the beginning of the stream disable the
212 * video port to avoid sending the skipped frames to the CCDC.
213 */
214 destidx = csi2->frame_skip ? 0 : !!(csi2->output & CSI2_OUTPUT_CCDC);
215 is_3630 = csi2->isp->revision == ISP_REVISION_15_0;
216
217 return __csi2_fmt_map[fmtidx][destidx][csi2->dpcm_decompress][is_3630];
218}
219
220/*
221 * csi2_set_outaddr - Set memory address to save output image
222 * @csi2: Pointer to ISP CSI2a device.
223 * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
224 *
225 * Sets the memory address where the output will be saved.
226 *
227 * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
228 * boundary.
229 */
230static void csi2_set_outaddr(struct isp_csi2_device *csi2, u32 addr)
231{
232 struct isp_device *isp = csi2->isp;
233 struct isp_csi2_ctx_cfg *ctx = &csi2->contexts[0];
234
235 ctx->ping_addr = addr;
236 ctx->pong_addr = addr;
237 isp_reg_writel(isp, ctx->ping_addr,
238 csi2->regs1, ISPCSI2_CTX_DAT_PING_ADDR(ctx->ctxnum));
239 isp_reg_writel(isp, ctx->pong_addr,
240 csi2->regs1, ISPCSI2_CTX_DAT_PONG_ADDR(ctx->ctxnum));
241}
242
243/*
244 * is_usr_def_mapping - Checks whether USER_DEF_MAPPING should
245 * be enabled by CSI2.
246 * @format_id: mapped format id
247 *
248 */
249static inline int is_usr_def_mapping(u32 format_id)
250{
251 return (format_id & 0x40) ? 1 : 0;
252}
253
254/*
255 * csi2_ctx_enable - Enable specified CSI2 context
256 * @ctxnum: Context number, valid between 0 and 7 values.
257 * @enable: enable
258 *
259 */
260static void csi2_ctx_enable(struct isp_device *isp,
261 struct isp_csi2_device *csi2, u8 ctxnum, u8 enable)
262{
263 struct isp_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum];
264 unsigned int skip = 0;
265 u32 reg;
266
267 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL1(ctxnum));
268
269 if (enable) {
270 if (csi2->frame_skip)
271 skip = csi2->frame_skip;
272 else if (csi2->output & CSI2_OUTPUT_MEMORY)
273 skip = 1;
274
275 reg &= ~ISPCSI2_CTX_CTRL1_COUNT_MASK;
276 reg |= ISPCSI2_CTX_CTRL1_COUNT_UNLOCK
277 | (skip << ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
278 | ISPCSI2_CTX_CTRL1_CTX_EN;
279 } else {
280 reg &= ~ISPCSI2_CTX_CTRL1_CTX_EN;
281 }
282
283 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL1(ctxnum));
284 ctx->enabled = enable;
285}
286
287/*
288 * csi2_ctx_config - CSI2 context configuration.
289 * @ctx: context configuration
290 *
291 */
292static void csi2_ctx_config(struct isp_device *isp,
293 struct isp_csi2_device *csi2,
294 struct isp_csi2_ctx_cfg *ctx)
295{
296 u32 reg;
297
298 /* Set up CSI2_CTx_CTRL1 */
299 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL1(ctx->ctxnum));
300
301 if (ctx->eof_enabled)
302 reg |= ISPCSI2_CTX_CTRL1_EOF_EN;
303 else
304 reg &= ~ISPCSI2_CTX_CTRL1_EOF_EN;
305
306 if (ctx->eol_enabled)
307 reg |= ISPCSI2_CTX_CTRL1_EOL_EN;
308 else
309 reg &= ~ISPCSI2_CTX_CTRL1_EOL_EN;
310
311 if (ctx->checksum_enabled)
312 reg |= ISPCSI2_CTX_CTRL1_CS_EN;
313 else
314 reg &= ~ISPCSI2_CTX_CTRL1_CS_EN;
315
316 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL1(ctx->ctxnum));
317
318 /* Set up CSI2_CTx_CTRL2 */
319 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL2(ctx->ctxnum));
320
321 reg &= ~(ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK);
322 reg |= ctx->virtual_id << ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
323
324 reg &= ~(ISPCSI2_CTX_CTRL2_FORMAT_MASK);
325 reg |= ctx->format_id << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT;
326
327 if (ctx->dpcm_decompress) {
328 if (ctx->dpcm_predictor)
329 reg |= ISPCSI2_CTX_CTRL2_DPCM_PRED;
330 else
331 reg &= ~ISPCSI2_CTX_CTRL2_DPCM_PRED;
332 }
333
334 if (is_usr_def_mapping(ctx->format_id)) {
335 reg &= ~ISPCSI2_CTX_CTRL2_USER_DEF_MAP_MASK;
336 reg |= 2 << ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT;
337 }
338
339 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL2(ctx->ctxnum));
340
341 /* Set up CSI2_CTx_CTRL3 */
342 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL3(ctx->ctxnum));
343 reg &= ~(ISPCSI2_CTX_CTRL3_ALPHA_MASK);
344 reg |= (ctx->alpha << ISPCSI2_CTX_CTRL3_ALPHA_SHIFT);
345
346 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL3(ctx->ctxnum));
347
348 /* Set up CSI2_CTx_DAT_OFST */
349 reg = isp_reg_readl(isp, csi2->regs1,
350 ISPCSI2_CTX_DAT_OFST(ctx->ctxnum));
351 reg &= ~ISPCSI2_CTX_DAT_OFST_OFST_MASK;
352 reg |= ctx->data_offset << ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
353 isp_reg_writel(isp, reg, csi2->regs1,
354 ISPCSI2_CTX_DAT_OFST(ctx->ctxnum));
355
356 isp_reg_writel(isp, ctx->ping_addr,
357 csi2->regs1, ISPCSI2_CTX_DAT_PING_ADDR(ctx->ctxnum));
358
359 isp_reg_writel(isp, ctx->pong_addr,
360 csi2->regs1, ISPCSI2_CTX_DAT_PONG_ADDR(ctx->ctxnum));
361}
362
363/*
364 * csi2_timing_config - CSI2 timing configuration.
365 * @timing: csi2_timing_cfg structure
366 */
367static void csi2_timing_config(struct isp_device *isp,
368 struct isp_csi2_device *csi2,
369 struct isp_csi2_timing_cfg *timing)
370{
371 u32 reg;
372
373 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_TIMING);
374
375 if (timing->force_rx_mode)
376 reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO(timing->ionum);
377 else
378 reg &= ~ISPCSI2_TIMING_FORCE_RX_MODE_IO(timing->ionum);
379
380 if (timing->stop_state_16x)
381 reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO(timing->ionum);
382 else
383 reg &= ~ISPCSI2_TIMING_STOP_STATE_X16_IO(timing->ionum);
384
385 if (timing->stop_state_4x)
386 reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO(timing->ionum);
387 else
388 reg &= ~ISPCSI2_TIMING_STOP_STATE_X4_IO(timing->ionum);
389
390 reg &= ~ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(timing->ionum);
391 reg |= timing->stop_state_counter <<
392 ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(timing->ionum);
393
394 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_TIMING);
395}
396
397/*
398 * csi2_irq_ctx_set - Enables CSI2 Context IRQs.
399 * @enable: Enable/disable CSI2 Context interrupts
400 */
401static void csi2_irq_ctx_set(struct isp_device *isp,
402 struct isp_csi2_device *csi2, int enable)
403{
404 int i;
405
406 for (i = 0; i < 8; i++) {
407 isp_reg_writel(isp, ISPCSI2_CTX_IRQSTATUS_FE_IRQ, csi2->regs1,
408 ISPCSI2_CTX_IRQSTATUS(i));
409 if (enable)
410 isp_reg_set(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
411 ISPCSI2_CTX_IRQSTATUS_FE_IRQ);
412 else
413 isp_reg_clr(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
414 ISPCSI2_CTX_IRQSTATUS_FE_IRQ);
415 }
416}
417
418/*
419 * csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
420 * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
421 */
422static void csi2_irq_complexio1_set(struct isp_device *isp,
423 struct isp_csi2_device *csi2, int enable)
424{
425 u32 reg;
426 reg = ISPCSI2_PHY_IRQENABLE_STATEALLULPMEXIT |
427 ISPCSI2_PHY_IRQENABLE_STATEALLULPMENTER |
428 ISPCSI2_PHY_IRQENABLE_STATEULPM5 |
429 ISPCSI2_PHY_IRQENABLE_ERRCONTROL5 |
430 ISPCSI2_PHY_IRQENABLE_ERRESC5 |
431 ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS5 |
432 ISPCSI2_PHY_IRQENABLE_ERRSOTHS5 |
433 ISPCSI2_PHY_IRQENABLE_STATEULPM4 |
434 ISPCSI2_PHY_IRQENABLE_ERRCONTROL4 |
435 ISPCSI2_PHY_IRQENABLE_ERRESC4 |
436 ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS4 |
437 ISPCSI2_PHY_IRQENABLE_ERRSOTHS4 |
438 ISPCSI2_PHY_IRQENABLE_STATEULPM3 |
439 ISPCSI2_PHY_IRQENABLE_ERRCONTROL3 |
440 ISPCSI2_PHY_IRQENABLE_ERRESC3 |
441 ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS3 |
442 ISPCSI2_PHY_IRQENABLE_ERRSOTHS3 |
443 ISPCSI2_PHY_IRQENABLE_STATEULPM2 |
444 ISPCSI2_PHY_IRQENABLE_ERRCONTROL2 |
445 ISPCSI2_PHY_IRQENABLE_ERRESC2 |
446 ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS2 |
447 ISPCSI2_PHY_IRQENABLE_ERRSOTHS2 |
448 ISPCSI2_PHY_IRQENABLE_STATEULPM1 |
449 ISPCSI2_PHY_IRQENABLE_ERRCONTROL1 |
450 ISPCSI2_PHY_IRQENABLE_ERRESC1 |
451 ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS1 |
452 ISPCSI2_PHY_IRQENABLE_ERRSOTHS1;
453 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
454 if (enable)
455 reg |= isp_reg_readl(isp, csi2->regs1, ISPCSI2_PHY_IRQENABLE);
456 else
457 reg = 0;
458 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_PHY_IRQENABLE);
459}
460
461/*
462 * csi2_irq_status_set - Enables CSI2 Status IRQs.
463 * @enable: Enable/disable CSI2 Status interrupts
464 */
465static void csi2_irq_status_set(struct isp_device *isp,
466 struct isp_csi2_device *csi2, int enable)
467{
468 u32 reg;
469 reg = ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
470 ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
471 ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ |
472 ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
473 ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
474 ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ |
475 ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ |
476 ISPCSI2_IRQSTATUS_CONTEXT(0);
477 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_IRQSTATUS);
478 if (enable)
479 reg |= isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQENABLE);
480 else
481 reg = 0;
482
483 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_IRQENABLE);
484}
485
486/*
487 * omap3isp_csi2_reset - Resets the CSI2 module.
488 *
489 * Must be called with the phy lock held.
490 *
491 * Returns 0 if successful, or -EBUSY if power command didn't respond.
492 */
493int omap3isp_csi2_reset(struct isp_csi2_device *csi2)
494{
495 struct isp_device *isp = csi2->isp;
496 u8 soft_reset_retries = 0;
497 u32 reg;
498 int i;
499
500 if (!csi2->available)
501 return -ENODEV;
502
503 if (csi2->phy->phy_in_use)
504 return -EBUSY;
505
506 isp_reg_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
507 ISPCSI2_SYSCONFIG_SOFT_RESET);
508
509 do {
510 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_SYSSTATUS) &
511 ISPCSI2_SYSSTATUS_RESET_DONE;
512 if (reg == ISPCSI2_SYSSTATUS_RESET_DONE)
513 break;
514 soft_reset_retries++;
515 if (soft_reset_retries < 5)
516 udelay(100);
517 } while (soft_reset_retries < 5);
518
519 if (soft_reset_retries == 5) {
520 printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
521 return -EBUSY;
522 }
523
524 if (isp->revision == ISP_REVISION_15_0)
525 isp_reg_set(isp, csi2->regs1, ISPCSI2_PHY_CFG,
526 ISPCSI2_PHY_CFG_RESET_CTRL);
527
528 i = 100;
529 do {
530 reg = isp_reg_readl(isp, csi2->phy->phy_regs, ISPCSIPHY_REG1)
531 & ISPCSIPHY_REG1_RESET_DONE_CTRLCLK;
532 if (reg == ISPCSIPHY_REG1_RESET_DONE_CTRLCLK)
533 break;
534 udelay(100);
535 } while (--i > 0);
536
537 if (i == 0) {
538 printk(KERN_ERR
539 "CSI2: Reset for CSI2_96M_FCLK domain Failed!\n");
540 return -EBUSY;
541 }
542
543 if (isp->autoidle)
544 isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
545 ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
546 ISPCSI2_SYSCONFIG_AUTO_IDLE,
547 ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART |
548 ((isp->revision == ISP_REVISION_15_0) ?
549 ISPCSI2_SYSCONFIG_AUTO_IDLE : 0));
550 else
551 isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
552 ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
553 ISPCSI2_SYSCONFIG_AUTO_IDLE,
554 ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO);
555
556 return 0;
557}
558
559static int csi2_configure(struct isp_csi2_device *csi2)
560{
561 const struct isp_v4l2_subdevs_group *pdata;
562 struct isp_device *isp = csi2->isp;
563 struct isp_csi2_timing_cfg *timing = &csi2->timing[0];
564 struct v4l2_subdev *sensor;
565 struct media_pad *pad;
566
567 /*
568 * CSI2 fields that can be updated while the context has
569 * been enabled or the interface has been enabled are not
570 * updated dynamically currently. So we do not allow to
571 * reconfigure if either has been enabled
572 */
573 if (csi2->contexts[0].enabled || csi2->ctrl.if_enable)
574 return -EBUSY;
575
576 pad = media_entity_remote_source(&csi2->pads[CSI2_PAD_SINK]);
577 sensor = media_entity_to_v4l2_subdev(pad->entity);
578 pdata = sensor->host_priv;
579
580 csi2->frame_skip = 0;
581 v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);
582
583 csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div;
584 csi2->ctrl.frame_mode = ISP_CSI2_FRAME_IMMEDIATE;
585 csi2->ctrl.ecc_enable = pdata->bus.csi2.crc;
586
587 timing->ionum = 1;
588 timing->force_rx_mode = 1;
589 timing->stop_state_16x = 1;
590 timing->stop_state_4x = 1;
591 timing->stop_state_counter = 0x1FF;
592
593 /*
594 * The CSI2 receiver can't do any format conversion except DPCM
595 * decompression, so every set_format call configures both pads
596 * and enables DPCM decompression as a special case:
597 */
598 if (csi2->formats[CSI2_PAD_SINK].code !=
599 csi2->formats[CSI2_PAD_SOURCE].code)
600 csi2->dpcm_decompress = true;
601 else
602 csi2->dpcm_decompress = false;
603
604 csi2->contexts[0].format_id = csi2_ctx_map_format(csi2);
605
606 if (csi2->video_out.bpl_padding == 0)
607 csi2->contexts[0].data_offset = 0;
608 else
609 csi2->contexts[0].data_offset = csi2->video_out.bpl_value;
610
611 /*
612 * Enable end of frame and end of line signals generation for
613 * context 0. These signals are generated from CSI2 receiver to
614 * qualify the last pixel of a frame and the last pixel of a line.
615 * Without enabling the signals CSI2 receiver writes data to memory
616 * beyond buffer size and/or data line offset is not handled correctly.
617 */
618 csi2->contexts[0].eof_enabled = 1;
619 csi2->contexts[0].eol_enabled = 1;
620
621 csi2_irq_complexio1_set(isp, csi2, 1);
622 csi2_irq_ctx_set(isp, csi2, 1);
623 csi2_irq_status_set(isp, csi2, 1);
624
625 /* Set configuration (timings, format and links) */
626 csi2_timing_config(isp, csi2, timing);
627 csi2_recv_config(isp, csi2, &csi2->ctrl);
628 csi2_ctx_config(isp, csi2, &csi2->contexts[0]);
629
630 return 0;
631}
632
633/*
634 * csi2_print_status - Prints CSI2 debug information.
635 */
636#define CSI2_PRINT_REGISTER(isp, regs, name)\
637 dev_dbg(isp->dev, "###CSI2 " #name "=0x%08x\n", \
638 isp_reg_readl(isp, regs, ISPCSI2_##name))
639
640static void csi2_print_status(struct isp_csi2_device *csi2)
641{
642 struct isp_device *isp = csi2->isp;
643
644 if (!csi2->available)
645 return;
646
647 dev_dbg(isp->dev, "-------------CSI2 Register dump-------------\n");
648
649 CSI2_PRINT_REGISTER(isp, csi2->regs1, SYSCONFIG);
650 CSI2_PRINT_REGISTER(isp, csi2->regs1, SYSSTATUS);
651 CSI2_PRINT_REGISTER(isp, csi2->regs1, IRQENABLE);
652 CSI2_PRINT_REGISTER(isp, csi2->regs1, IRQSTATUS);
653 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTRL);
654 CSI2_PRINT_REGISTER(isp, csi2->regs1, DBG_H);
655 CSI2_PRINT_REGISTER(isp, csi2->regs1, GNQ);
656 CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_CFG);
657 CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_IRQSTATUS);
658 CSI2_PRINT_REGISTER(isp, csi2->regs1, SHORT_PACKET);
659 CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_IRQENABLE);
660 CSI2_PRINT_REGISTER(isp, csi2->regs1, DBG_P);
661 CSI2_PRINT_REGISTER(isp, csi2->regs1, TIMING);
662 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL1(0));
663 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL2(0));
664 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_OFST(0));
665 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_PING_ADDR(0));
666 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_PONG_ADDR(0));
667 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_IRQENABLE(0));
668 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_IRQSTATUS(0));
669 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL3(0));
670
671 dev_dbg(isp->dev, "--------------------------------------------\n");
672}
673
674/* -----------------------------------------------------------------------------
675 * Interrupt handling
676 */
677
678/*
679 * csi2_isr_buffer - Does buffer handling at end-of-frame
680 * when writing to memory.
681 */
682static void csi2_isr_buffer(struct isp_csi2_device *csi2)
683{
684 struct isp_device *isp = csi2->isp;
685 struct isp_buffer *buffer;
686
687 csi2_ctx_enable(isp, csi2, 0, 0);
688
689 buffer = omap3isp_video_buffer_next(&csi2->video_out);
690
691 /*
692 * Let video queue operation restart engine if there is an underrun
693 * condition.
694 */
695 if (buffer == NULL)
696 return;
697
698 csi2_set_outaddr(csi2, buffer->isp_addr);
699 csi2_ctx_enable(isp, csi2, 0, 1);
700}
701
702static void csi2_isr_ctx(struct isp_csi2_device *csi2,
703 struct isp_csi2_ctx_cfg *ctx)
704{
705 struct isp_device *isp = csi2->isp;
706 unsigned int n = ctx->ctxnum;
707 u32 status;
708
709 status = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));
710 isp_reg_writel(isp, status, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));
711
712 if (!(status & ISPCSI2_CTX_IRQSTATUS_FE_IRQ))
713 return;
714
715 /* Skip interrupts until we reach the frame skip count. The CSI2 will be
716 * automatically disabled, as the frame skip count has been programmed
717 * in the CSI2_CTx_CTRL1::COUNT field, so reenable it.
718 *
719 * It would have been nice to rely on the FRAME_NUMBER interrupt instead
720 * but it turned out that the interrupt is only generated when the CSI2
721 * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased
722 * correctly and reaches 0 when data is forwarded to the video port only
723 * but no interrupt arrives). Maybe a CSI2 hardware bug.
724 */
725 if (csi2->frame_skip) {
726 csi2->frame_skip--;
727 if (csi2->frame_skip == 0) {
728 ctx->format_id = csi2_ctx_map_format(csi2);
729 csi2_ctx_config(isp, csi2, ctx);
730 csi2_ctx_enable(isp, csi2, n, 1);
731 }
732 return;
733 }
734
735 if (csi2->output & CSI2_OUTPUT_MEMORY)
736 csi2_isr_buffer(csi2);
737}
738
739/*
740 * omap3isp_csi2_isr - CSI2 interrupt handling.
741 */
742void omap3isp_csi2_isr(struct isp_csi2_device *csi2)
743{
744 struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
745 u32 csi2_irqstatus, cpxio1_irqstatus;
746 struct isp_device *isp = csi2->isp;
747
748 if (!csi2->available)
749 return;
750
751 csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS);
752 isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS);
753
754 /* Failure Cases */
755 if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ) {
756 cpxio1_irqstatus = isp_reg_readl(isp, csi2->regs1,
757 ISPCSI2_PHY_IRQSTATUS);
758 isp_reg_writel(isp, cpxio1_irqstatus,
759 csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
760 dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ "
761 "%x\n", cpxio1_irqstatus);
762 pipe->error = true;
763 }
764
765 if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
766 ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
767 ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
768 ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
769 ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)) {
770 dev_dbg(isp->dev, "CSI2 Err:"
771 " OCP:%d,"
772 " Short_pack:%d,"
773 " ECC:%d,"
774 " CPXIO2:%d,"
775 " FIFO_OVF:%d,"
776 "\n",
777 (csi2_irqstatus &
778 ISPCSI2_IRQSTATUS_OCP_ERR_IRQ) ? 1 : 0,
779 (csi2_irqstatus &
780 ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ) ? 1 : 0,
781 (csi2_irqstatus &
782 ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ) ? 1 : 0,
783 (csi2_irqstatus &
784 ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0,
785 (csi2_irqstatus &
786 ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0);
787 pipe->error = true;
788 }
789
790 if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
791 return;
792
793 /* Successful cases */
794 if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0))
795 csi2_isr_ctx(csi2, &csi2->contexts[0]);
796
797 if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
798 dev_dbg(isp->dev, "CSI2: ECC correction done\n");
799}
800
801/* -----------------------------------------------------------------------------
802 * ISP video operations
803 */
804
805/*
806 * csi2_queue - Queues the first buffer when using memory output
807 * @video: The video node
808 * @buffer: buffer to queue
809 */
810static int csi2_queue(struct isp_video *video, struct isp_buffer *buffer)
811{
812 struct isp_device *isp = video->isp;
813 struct isp_csi2_device *csi2 = &isp->isp_csi2a;
814
815 csi2_set_outaddr(csi2, buffer->isp_addr);
816
817 /*
818 * If streaming was enabled before there was a buffer queued
819 * or underrun happened in the ISR, the hardware was not enabled
820 * and DMA queue flag ISP_VIDEO_DMAQUEUE_UNDERRUN is still set.
821 * Enable it now.
822 */
823 if (csi2->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
824 /* Enable / disable context 0 and IRQs */
825 csi2_if_enable(isp, csi2, 1);
826 csi2_ctx_enable(isp, csi2, 0, 1);
827 isp_video_dmaqueue_flags_clr(&csi2->video_out);
828 }
829
830 return 0;
831}
832
833static const struct isp_video_operations csi2_ispvideo_ops = {
834 .queue = csi2_queue,
835};
836
837/* -----------------------------------------------------------------------------
838 * V4L2 subdev operations
839 */
840
841static struct v4l2_mbus_framefmt *
842__csi2_get_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
843 unsigned int pad, enum v4l2_subdev_format_whence which)
844{
845 if (which == V4L2_SUBDEV_FORMAT_TRY)
846 return v4l2_subdev_get_try_format(fh, pad);
847 else
848 return &csi2->formats[pad];
849}
850
851static void
852csi2_try_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
853 unsigned int pad, struct v4l2_mbus_framefmt *fmt,
854 enum v4l2_subdev_format_whence which)
855{
856 enum v4l2_mbus_pixelcode pixelcode;
857 struct v4l2_mbus_framefmt *format;
858 const struct isp_format_info *info;
859 unsigned int i;
860
861 switch (pad) {
862 case CSI2_PAD_SINK:
863 /* Clamp the width and height to valid range (1-8191). */
864 for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) {
865 if (fmt->code == csi2_input_fmts[i])
866 break;
867 }
868
869 /* If not found, use SGRBG10 as default */
870 if (i >= ARRAY_SIZE(csi2_input_fmts))
871 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
872
873 fmt->width = clamp_t(u32, fmt->width, 1, 8191);
874 fmt->height = clamp_t(u32, fmt->height, 1, 8191);
875 break;
876
877 case CSI2_PAD_SOURCE:
878 /* Source format same as sink format, except for DPCM
879 * compression.
880 */
881 pixelcode = fmt->code;
882 format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which);
883 memcpy(fmt, format, sizeof(*fmt));
884
885 /*
886 * Only Allow DPCM decompression, and check that the
887 * pattern is preserved
888 */
889 info = omap3isp_video_format_info(fmt->code);
890 if (info->uncompressed == pixelcode)
891 fmt->code = pixelcode;
892 break;
893 }
894
895 /* RGB, non-interlaced */
896 fmt->colorspace = V4L2_COLORSPACE_SRGB;
897 fmt->field = V4L2_FIELD_NONE;
898}
899
900/*
901 * csi2_enum_mbus_code - Handle pixel format enumeration
902 * @sd : pointer to v4l2 subdev structure
903 * @fh : V4L2 subdev file handle
904 * @code : pointer to v4l2_subdev_mbus_code_enum structure
905 * return -EINVAL or zero on success
906 */
907static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
908 struct v4l2_subdev_fh *fh,
909 struct v4l2_subdev_mbus_code_enum *code)
910{
911 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
912 struct v4l2_mbus_framefmt *format;
913 const struct isp_format_info *info;
914
915 if (code->pad == CSI2_PAD_SINK) {
916 if (code->index >= ARRAY_SIZE(csi2_input_fmts))
917 return -EINVAL;
918
919 code->code = csi2_input_fmts[code->index];
920 } else {
921 format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK,
922 V4L2_SUBDEV_FORMAT_TRY);
923 switch (code->index) {
924 case 0:
925 /* Passthrough sink pad code */
926 code->code = format->code;
927 break;
928 case 1:
929 /* Uncompressed code */
930 info = omap3isp_video_format_info(format->code);
931 if (info->uncompressed == format->code)
932 return -EINVAL;
933
934 code->code = info->uncompressed;
935 break;
936 default:
937 return -EINVAL;
938 }
939 }
940
941 return 0;
942}
943
944static int csi2_enum_frame_size(struct v4l2_subdev *sd,
945 struct v4l2_subdev_fh *fh,
946 struct v4l2_subdev_frame_size_enum *fse)
947{
948 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
949 struct v4l2_mbus_framefmt format;
950
951 if (fse->index != 0)
952 return -EINVAL;
953
954 format.code = fse->code;
955 format.width = 1;
956 format.height = 1;
957 csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
958 fse->min_width = format.width;
959 fse->min_height = format.height;
960
961 if (format.code != fse->code)
962 return -EINVAL;
963
964 format.code = fse->code;
965 format.width = -1;
966 format.height = -1;
967 csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
968 fse->max_width = format.width;
969 fse->max_height = format.height;
970
971 return 0;
972}
973
974/*
975 * csi2_get_format - Handle get format by pads subdev method
976 * @sd : pointer to v4l2 subdev structure
977 * @fh : V4L2 subdev file handle
978 * @fmt: pointer to v4l2 subdev format structure
979 * return -EINVAL or zero on success
980 */
981static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
982 struct v4l2_subdev_format *fmt)
983{
984 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
985 struct v4l2_mbus_framefmt *format;
986
987 format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
988 if (format == NULL)
989 return -EINVAL;
990
991 fmt->format = *format;
992 return 0;
993}
994
995/*
996 * csi2_set_format - Handle set format by pads subdev method
997 * @sd : pointer to v4l2 subdev structure
998 * @fh : V4L2 subdev file handle
999 * @fmt: pointer to v4l2 subdev format structure
1000 * return -EINVAL or zero on success
1001 */
1002static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1003 struct v4l2_subdev_format *fmt)
1004{
1005 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
1006 struct v4l2_mbus_framefmt *format;
1007
1008 format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
1009 if (format == NULL)
1010 return -EINVAL;
1011
1012 csi2_try_format(csi2, fh, fmt->pad, &fmt->format, fmt->which);
1013 *format = fmt->format;
1014
1015 /* Propagate the format from sink to source */
1016 if (fmt->pad == CSI2_PAD_SINK) {
1017 format = __csi2_get_format(csi2, fh, CSI2_PAD_SOURCE,
1018 fmt->which);
1019 *format = fmt->format;
1020 csi2_try_format(csi2, fh, CSI2_PAD_SOURCE, format, fmt->which);
1021 }
1022
1023 return 0;
1024}
1025
1026/*
1027 * csi2_init_formats - Initialize formats on all pads
1028 * @sd: ISP CSI2 V4L2 subdevice
1029 * @fh: V4L2 subdev file handle
1030 *
1031 * Initialize all pad formats with default values. If fh is not NULL, try
1032 * formats are initialized on the file handle. Otherwise active formats are
1033 * initialized on the device.
1034 */
1035static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1036{
1037 struct v4l2_subdev_format format;
1038
1039 memset(&format, 0, sizeof(format));
1040 format.pad = CSI2_PAD_SINK;
1041 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1042 format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
1043 format.format.width = 4096;
1044 format.format.height = 4096;
1045 csi2_set_format(sd, fh, &format);
1046
1047 return 0;
1048}
1049
1050/*
1051 * csi2_set_stream - Enable/Disable streaming on the CSI2 module
1052 * @sd: ISP CSI2 V4L2 subdevice
1053 * @enable: ISP pipeline stream state
1054 *
1055 * Return 0 on success or a negative error code otherwise.
1056 */
1057static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
1058{
1059 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
1060 struct isp_device *isp = csi2->isp;
1061 struct isp_video *video_out = &csi2->video_out;
1062
1063 switch (enable) {
1064 case ISP_PIPELINE_STREAM_CONTINUOUS:
1065 if (omap3isp_csiphy_acquire(csi2->phy) < 0)
1066 return -ENODEV;
1067 if (csi2->output & CSI2_OUTPUT_MEMORY)
1068 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI2A_WRITE);
1069 csi2_configure(csi2);
1070 csi2_print_status(csi2);
1071
1072 /*
1073 * When outputting to memory with no buffer available, let the
1074 * buffer queue handler start the hardware. A DMA queue flag
1075 * ISP_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
1076 * a buffer available.
1077 */
1078 if (csi2->output & CSI2_OUTPUT_MEMORY &&
1079 !(video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED))
1080 break;
1081 /* Enable context 0 and IRQs */
1082 atomic_set(&csi2->stopping, 0);
1083 csi2_ctx_enable(isp, csi2, 0, 1);
1084 csi2_if_enable(isp, csi2, 1);
1085 isp_video_dmaqueue_flags_clr(video_out);
1086 break;
1087
1088 case ISP_PIPELINE_STREAM_STOPPED:
1089 if (csi2->state == ISP_PIPELINE_STREAM_STOPPED)
1090 return 0;
1091 if (omap3isp_module_sync_idle(&sd->entity, &csi2->wait,
1092 &csi2->stopping))
1093 dev_dbg(isp->dev, "%s: module stop timeout.\n",
1094 sd->name);
1095 csi2_ctx_enable(isp, csi2, 0, 0);
1096 csi2_if_enable(isp, csi2, 0);
1097 csi2_irq_ctx_set(isp, csi2, 0);
1098 omap3isp_csiphy_release(csi2->phy);
1099 isp_video_dmaqueue_flags_clr(video_out);
1100 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI2A_WRITE);
1101 break;
1102 }
1103
1104 csi2->state = enable;
1105 return 0;
1106}
1107
1108/* subdev video operations */
1109static const struct v4l2_subdev_video_ops csi2_video_ops = {
1110 .s_stream = csi2_set_stream,
1111};
1112
1113/* subdev pad operations */
1114static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
1115 .enum_mbus_code = csi2_enum_mbus_code,
1116 .enum_frame_size = csi2_enum_frame_size,
1117 .get_fmt = csi2_get_format,
1118 .set_fmt = csi2_set_format,
1119};
1120
1121/* subdev operations */
1122static const struct v4l2_subdev_ops csi2_ops = {
1123 .video = &csi2_video_ops,
1124 .pad = &csi2_pad_ops,
1125};
1126
1127/* subdev internal operations */
1128static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
1129 .open = csi2_init_formats,
1130};
1131
1132/* -----------------------------------------------------------------------------
1133 * Media entity operations
1134 */
1135
1136/*
1137 * csi2_link_setup - Setup CSI2 connections.
1138 * @entity : Pointer to media entity structure
1139 * @local : Pointer to local pad array
1140 * @remote : Pointer to remote pad array
1141 * @flags : Link flags
1142 * return -EINVAL or zero on success
1143 */
1144static int csi2_link_setup(struct media_entity *entity,
1145 const struct media_pad *local,
1146 const struct media_pad *remote, u32 flags)
1147{
1148 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1149 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
1150 struct isp_csi2_ctrl_cfg *ctrl = &csi2->ctrl;
1151
1152 /*
1153 * The ISP core doesn't support pipelines with multiple video outputs.
1154 * Revisit this when it will be implemented, and return -EBUSY for now.
1155 */
1156
1157 switch (local->index | media_entity_type(remote->entity)) {
1158 case CSI2_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
1159 if (flags & MEDIA_LNK_FL_ENABLED) {
1160 if (csi2->output & ~CSI2_OUTPUT_MEMORY)
1161 return -EBUSY;
1162 csi2->output |= CSI2_OUTPUT_MEMORY;
1163 } else {
1164 csi2->output &= ~CSI2_OUTPUT_MEMORY;
1165 }
1166 break;
1167
1168 case CSI2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
1169 if (flags & MEDIA_LNK_FL_ENABLED) {
1170 if (csi2->output & ~CSI2_OUTPUT_CCDC)
1171 return -EBUSY;
1172 csi2->output |= CSI2_OUTPUT_CCDC;
1173 } else {
1174 csi2->output &= ~CSI2_OUTPUT_CCDC;
1175 }
1176 break;
1177
1178 default:
1179 /* Link from camera to CSI2 is fixed... */
1180 return -EINVAL;
1181 }
1182
1183 ctrl->vp_only_enable =
1184 (csi2->output & CSI2_OUTPUT_MEMORY) ? false : true;
1185 ctrl->vp_clk_enable = !!(csi2->output & CSI2_OUTPUT_CCDC);
1186
1187 return 0;
1188}
1189
1190/* media operations */
1191static const struct media_entity_operations csi2_media_ops = {
1192 .link_setup = csi2_link_setup,
1193 .link_validate = v4l2_subdev_link_validate,
1194};
1195
1196void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2)
1197{
1198 v4l2_device_unregister_subdev(&csi2->subdev);
1199 omap3isp_video_unregister(&csi2->video_out);
1200}
1201
1202int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
1203 struct v4l2_device *vdev)
1204{
1205 int ret;
1206
1207 /* Register the subdev and video nodes. */
1208 ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
1209 if (ret < 0)
1210 goto error;
1211
1212 ret = omap3isp_video_register(&csi2->video_out, vdev);
1213 if (ret < 0)
1214 goto error;
1215
1216 return 0;
1217
1218error:
1219 omap3isp_csi2_unregister_entities(csi2);
1220 return ret;
1221}
1222
1223/* -----------------------------------------------------------------------------
1224 * ISP CSI2 initialisation and cleanup
1225 */
1226
1227/*
1228 * csi2_init_entities - Initialize subdev and media entity.
1229 * @csi2: Pointer to csi2 structure.
1230 * return -ENOMEM or zero on success
1231 */
1232static int csi2_init_entities(struct isp_csi2_device *csi2)
1233{
1234 struct v4l2_subdev *sd = &csi2->subdev;
1235 struct media_pad *pads = csi2->pads;
1236 struct media_entity *me = &sd->entity;
1237 int ret;
1238
1239 v4l2_subdev_init(sd, &csi2_ops);
1240 sd->internal_ops = &csi2_internal_ops;
1241 strlcpy(sd->name, "OMAP3 ISP CSI2a", sizeof(sd->name));
1242
1243 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
1244 v4l2_set_subdevdata(sd, csi2);
1245 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1246
1247 pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1248 pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1249
1250 me->ops = &csi2_media_ops;
1251 ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0);
1252 if (ret < 0)
1253 return ret;
1254
1255 csi2_init_formats(sd, NULL);
1256
1257 /* Video device node */
1258 csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1259 csi2->video_out.ops = &csi2_ispvideo_ops;
1260 csi2->video_out.bpl_alignment = 32;
1261 csi2->video_out.bpl_zero_padding = 1;
1262 csi2->video_out.bpl_max = 0x1ffe0;
1263 csi2->video_out.isp = csi2->isp;
1264 csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
1265
1266 ret = omap3isp_video_init(&csi2->video_out, "CSI2a");
1267 if (ret < 0)
1268 goto error_video;
1269
1270 /* Connect the CSI2 subdev to the video node. */
1271 ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
1272 &csi2->video_out.video.entity, 0, 0);
1273 if (ret < 0)
1274 goto error_link;
1275
1276 return 0;
1277
1278error_link:
1279 omap3isp_video_cleanup(&csi2->video_out);
1280error_video:
1281 media_entity_cleanup(&csi2->subdev.entity);
1282 return ret;
1283}
1284
1285/*
1286 * omap3isp_csi2_init - Routine for module driver init
1287 */
1288int omap3isp_csi2_init(struct isp_device *isp)
1289{
1290 struct isp_csi2_device *csi2a = &isp->isp_csi2a;
1291 struct isp_csi2_device *csi2c = &isp->isp_csi2c;
1292 int ret;
1293
1294 csi2a->isp = isp;
1295 csi2a->available = 1;
1296 csi2a->regs1 = OMAP3_ISP_IOMEM_CSI2A_REGS1;
1297 csi2a->regs2 = OMAP3_ISP_IOMEM_CSI2A_REGS2;
1298 csi2a->phy = &isp->isp_csiphy2;
1299 csi2a->state = ISP_PIPELINE_STREAM_STOPPED;
1300 init_waitqueue_head(&csi2a->wait);
1301
1302 ret = csi2_init_entities(csi2a);
1303 if (ret < 0)
1304 return ret;
1305
1306 if (isp->revision == ISP_REVISION_15_0) {
1307 csi2c->isp = isp;
1308 csi2c->available = 1;
1309 csi2c->regs1 = OMAP3_ISP_IOMEM_CSI2C_REGS1;
1310 csi2c->regs2 = OMAP3_ISP_IOMEM_CSI2C_REGS2;
1311 csi2c->phy = &isp->isp_csiphy1;
1312 csi2c->state = ISP_PIPELINE_STREAM_STOPPED;
1313 init_waitqueue_head(&csi2c->wait);
1314 }
1315
1316 return 0;
1317}
1318
1319/*
1320 * omap3isp_csi2_cleanup - Routine for module driver cleanup
1321 */
1322void omap3isp_csi2_cleanup(struct isp_device *isp)
1323{
1324 struct isp_csi2_device *csi2a = &isp->isp_csi2a;
1325
1326 omap3isp_video_cleanup(&csi2a->video_out);
1327 media_entity_cleanup(&csi2a->subdev.entity);
1328}
diff --git a/drivers/media/platform/omap3isp/ispcsi2.h b/drivers/media/platform/omap3isp/ispcsi2.h
new file mode 100644
index 000000000000..c57729b7e86e
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispcsi2.h
@@ -0,0 +1,165 @@
1/*
2 * ispcsi2.h
3 *
4 * TI OMAP3 ISP - CSI2 module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#ifndef OMAP3_ISP_CSI2_H
28#define OMAP3_ISP_CSI2_H
29
30#include <linux/types.h>
31#include <linux/videodev2.h>
32
33struct isp_csiphy;
34
35/* This is not an exhaustive list */
36enum isp_csi2_pix_formats {
37 CSI2_PIX_FMT_OTHERS = 0,
38 CSI2_PIX_FMT_YUV422_8BIT = 0x1e,
39 CSI2_PIX_FMT_YUV422_8BIT_VP = 0x9e,
40 CSI2_PIX_FMT_RAW10_EXP16 = 0xab,
41 CSI2_PIX_FMT_RAW10_EXP16_VP = 0x12f,
42 CSI2_PIX_FMT_RAW8 = 0x2a,
43 CSI2_PIX_FMT_RAW8_DPCM10_EXP16 = 0x2aa,
44 CSI2_PIX_FMT_RAW8_DPCM10_VP = 0x32a,
45 CSI2_PIX_FMT_RAW8_VP = 0x12a,
46 CSI2_USERDEF_8BIT_DATA1_DPCM10_VP = 0x340,
47 CSI2_USERDEF_8BIT_DATA1_DPCM10 = 0x2c0,
48 CSI2_USERDEF_8BIT_DATA1 = 0x40,
49};
50
51enum isp_csi2_irqevents {
52 OCP_ERR_IRQ = 0x4000,
53 SHORT_PACKET_IRQ = 0x2000,
54 ECC_CORRECTION_IRQ = 0x1000,
55 ECC_NO_CORRECTION_IRQ = 0x800,
56 COMPLEXIO2_ERR_IRQ = 0x400,
57 COMPLEXIO1_ERR_IRQ = 0x200,
58 FIFO_OVF_IRQ = 0x100,
59 CONTEXT7 = 0x80,
60 CONTEXT6 = 0x40,
61 CONTEXT5 = 0x20,
62 CONTEXT4 = 0x10,
63 CONTEXT3 = 0x8,
64 CONTEXT2 = 0x4,
65 CONTEXT1 = 0x2,
66 CONTEXT0 = 0x1,
67};
68
69enum isp_csi2_ctx_irqevents {
70 CTX_ECC_CORRECTION = 0x100,
71 CTX_LINE_NUMBER = 0x80,
72 CTX_FRAME_NUMBER = 0x40,
73 CTX_CS = 0x20,
74 CTX_LE = 0x8,
75 CTX_LS = 0x4,
76 CTX_FE = 0x2,
77 CTX_FS = 0x1,
78};
79
80enum isp_csi2_frame_mode {
81 ISP_CSI2_FRAME_IMMEDIATE,
82 ISP_CSI2_FRAME_AFTERFEC,
83};
84
85#define ISP_CSI2_MAX_CTX_NUM 7
86
87struct isp_csi2_ctx_cfg {
88 u8 ctxnum; /* context number 0 - 7 */
89 u8 dpcm_decompress;
90
91 /* Fields in CSI2_CTx_CTRL2 - locked by CSI2_CTx_CTRL1.CTX_EN */
92 u8 virtual_id;
93 u16 format_id; /* as in CSI2_CTx_CTRL2[9:0] */
94 u8 dpcm_predictor; /* 1: simple, 0: advanced */
95
96 /* Fields in CSI2_CTx_CTRL1/3 - Shadowed */
97 u16 alpha;
98 u16 data_offset;
99 u32 ping_addr;
100 u32 pong_addr;
101 u8 eof_enabled;
102 u8 eol_enabled;
103 u8 checksum_enabled;
104 u8 enabled;
105};
106
107struct isp_csi2_timing_cfg {
108 u8 ionum; /* IO1 or IO2 as in CSI2_TIMING */
109 unsigned force_rx_mode:1;
110 unsigned stop_state_16x:1;
111 unsigned stop_state_4x:1;
112 u16 stop_state_counter;
113};
114
115struct isp_csi2_ctrl_cfg {
116 bool vp_clk_enable;
117 bool vp_only_enable;
118 u8 vp_out_ctrl;
119 enum isp_csi2_frame_mode frame_mode;
120 bool ecc_enable;
121 bool if_enable;
122};
123
124#define CSI2_PAD_SINK 0
125#define CSI2_PAD_SOURCE 1
126#define CSI2_PADS_NUM 2
127
128#define CSI2_OUTPUT_CCDC (1 << 0)
129#define CSI2_OUTPUT_MEMORY (1 << 1)
130
131struct isp_csi2_device {
132 struct v4l2_subdev subdev;
133 struct media_pad pads[CSI2_PADS_NUM];
134 struct v4l2_mbus_framefmt formats[CSI2_PADS_NUM];
135
136 struct isp_video video_out;
137 struct isp_device *isp;
138
139 u8 available; /* Is the IP present on the silicon? */
140
141 /* mem resources - enums as defined in enum isp_mem_resources */
142 u8 regs1;
143 u8 regs2;
144
145 u32 output; /* output to CCDC, memory or both? */
146 bool dpcm_decompress;
147 unsigned int frame_skip;
148
149 struct isp_csiphy *phy;
150 struct isp_csi2_ctx_cfg contexts[ISP_CSI2_MAX_CTX_NUM + 1];
151 struct isp_csi2_timing_cfg timing[2];
152 struct isp_csi2_ctrl_cfg ctrl;
153 enum isp_pipeline_stream_state state;
154 wait_queue_head_t wait;
155 atomic_t stopping;
156};
157
158void omap3isp_csi2_isr(struct isp_csi2_device *csi2);
159int omap3isp_csi2_reset(struct isp_csi2_device *csi2);
160int omap3isp_csi2_init(struct isp_device *isp);
161void omap3isp_csi2_cleanup(struct isp_device *isp);
162void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2);
163int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
164 struct v4l2_device *vdev);
165#endif /* OMAP3_ISP_CSI2_H */
diff --git a/drivers/media/platform/omap3isp/ispcsiphy.c b/drivers/media/platform/omap3isp/ispcsiphy.c
new file mode 100644
index 000000000000..348f67ebbbc9
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispcsiphy.c
@@ -0,0 +1,249 @@
1/*
2 * ispcsiphy.c
3 *
4 * TI OMAP3 ISP - CSI PHY module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#include <linux/delay.h>
28#include <linux/device.h>
29#include <linux/regulator/consumer.h>
30
31#include "isp.h"
32#include "ispreg.h"
33#include "ispcsiphy.h"
34
35/*
36 * csiphy_lanes_config - Configuration of CSIPHY lanes.
37 *
38 * Updates HW configuration.
39 * Called with phy->mutex taken.
40 */
41static void csiphy_lanes_config(struct isp_csiphy *phy)
42{
43 unsigned int i;
44 u32 reg;
45
46 reg = isp_reg_readl(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG);
47
48 for (i = 0; i < phy->num_data_lanes; i++) {
49 reg &= ~(ISPCSI2_PHY_CFG_DATA_POL_MASK(i + 1) |
50 ISPCSI2_PHY_CFG_DATA_POSITION_MASK(i + 1));
51 reg |= (phy->lanes.data[i].pol <<
52 ISPCSI2_PHY_CFG_DATA_POL_SHIFT(i + 1));
53 reg |= (phy->lanes.data[i].pos <<
54 ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(i + 1));
55 }
56
57 reg &= ~(ISPCSI2_PHY_CFG_CLOCK_POL_MASK |
58 ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK);
59 reg |= phy->lanes.clk.pol << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT;
60 reg |= phy->lanes.clk.pos << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT;
61
62 isp_reg_writel(phy->isp, reg, phy->cfg_regs, ISPCSI2_PHY_CFG);
63}
64
65/*
66 * csiphy_power_autoswitch_enable
67 * @enable: Sets or clears the autoswitch function enable flag.
68 */
69static void csiphy_power_autoswitch_enable(struct isp_csiphy *phy, bool enable)
70{
71 isp_reg_clr_set(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG,
72 ISPCSI2_PHY_CFG_PWR_AUTO,
73 enable ? ISPCSI2_PHY_CFG_PWR_AUTO : 0);
74}
75
76/*
77 * csiphy_set_power
78 * @power: Power state to be set.
79 *
80 * Returns 0 if successful, or -EBUSY if the retry count is exceeded.
81 */
82static int csiphy_set_power(struct isp_csiphy *phy, u32 power)
83{
84 u32 reg;
85 u8 retry_count;
86
87 isp_reg_clr_set(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG,
88 ISPCSI2_PHY_CFG_PWR_CMD_MASK, power);
89
90 retry_count = 0;
91 do {
92 udelay(50);
93 reg = isp_reg_readl(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG) &
94 ISPCSI2_PHY_CFG_PWR_STATUS_MASK;
95
96 if (reg != power >> 2)
97 retry_count++;
98
99 } while ((reg != power >> 2) && (retry_count < 100));
100
101 if (retry_count == 100) {
102 printk(KERN_ERR "CSI2 CIO set power failed!\n");
103 return -EBUSY;
104 }
105
106 return 0;
107}
108
109/*
110 * csiphy_dphy_config - Configure CSI2 D-PHY parameters.
111 *
112 * Called with phy->mutex taken.
113 */
114static void csiphy_dphy_config(struct isp_csiphy *phy)
115{
116 u32 reg;
117
118 /* Set up ISPCSIPHY_REG0 */
119 reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG0);
120
121 reg &= ~(ISPCSIPHY_REG0_THS_TERM_MASK |
122 ISPCSIPHY_REG0_THS_SETTLE_MASK);
123 reg |= phy->dphy.ths_term << ISPCSIPHY_REG0_THS_TERM_SHIFT;
124 reg |= phy->dphy.ths_settle << ISPCSIPHY_REG0_THS_SETTLE_SHIFT;
125
126 isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG0);
127
128 /* Set up ISPCSIPHY_REG1 */
129 reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG1);
130
131 reg &= ~(ISPCSIPHY_REG1_TCLK_TERM_MASK |
132 ISPCSIPHY_REG1_TCLK_MISS_MASK |
133 ISPCSIPHY_REG1_TCLK_SETTLE_MASK);
134 reg |= phy->dphy.tclk_term << ISPCSIPHY_REG1_TCLK_TERM_SHIFT;
135 reg |= phy->dphy.tclk_miss << ISPCSIPHY_REG1_TCLK_MISS_SHIFT;
136 reg |= phy->dphy.tclk_settle << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT;
137
138 isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG1);
139}
140
141static int csiphy_config(struct isp_csiphy *phy,
142 struct isp_csiphy_dphy_cfg *dphy,
143 struct isp_csiphy_lanes_cfg *lanes)
144{
145 unsigned int used_lanes = 0;
146 unsigned int i;
147
148 /* Clock and data lanes verification */
149 for (i = 0; i < phy->num_data_lanes; i++) {
150 if (lanes->data[i].pol > 1 || lanes->data[i].pos > 3)
151 return -EINVAL;
152
153 if (used_lanes & (1 << lanes->data[i].pos))
154 return -EINVAL;
155
156 used_lanes |= 1 << lanes->data[i].pos;
157 }
158
159 if (lanes->clk.pol > 1 || lanes->clk.pos > 3)
160 return -EINVAL;
161
162 if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos))
163 return -EINVAL;
164
165 mutex_lock(&phy->mutex);
166 phy->dphy = *dphy;
167 phy->lanes = *lanes;
168 mutex_unlock(&phy->mutex);
169
170 return 0;
171}
172
173int omap3isp_csiphy_acquire(struct isp_csiphy *phy)
174{
175 int rval;
176
177 if (phy->vdd == NULL) {
178 dev_err(phy->isp->dev, "Power regulator for CSI PHY not "
179 "available\n");
180 return -ENODEV;
181 }
182
183 mutex_lock(&phy->mutex);
184
185 rval = regulator_enable(phy->vdd);
186 if (rval < 0)
187 goto done;
188
189 rval = omap3isp_csi2_reset(phy->csi2);
190 if (rval < 0)
191 goto done;
192
193 csiphy_dphy_config(phy);
194 csiphy_lanes_config(phy);
195
196 rval = csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_ON);
197 if (rval) {
198 regulator_disable(phy->vdd);
199 goto done;
200 }
201
202 csiphy_power_autoswitch_enable(phy, true);
203 phy->phy_in_use = 1;
204
205done:
206 mutex_unlock(&phy->mutex);
207 return rval;
208}
209
210void omap3isp_csiphy_release(struct isp_csiphy *phy)
211{
212 mutex_lock(&phy->mutex);
213 if (phy->phy_in_use) {
214 csiphy_power_autoswitch_enable(phy, false);
215 csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_OFF);
216 regulator_disable(phy->vdd);
217 phy->phy_in_use = 0;
218 }
219 mutex_unlock(&phy->mutex);
220}
221
222/*
223 * omap3isp_csiphy_init - Initialize the CSI PHY frontends
224 */
225int omap3isp_csiphy_init(struct isp_device *isp)
226{
227 struct isp_csiphy *phy1 = &isp->isp_csiphy1;
228 struct isp_csiphy *phy2 = &isp->isp_csiphy2;
229
230 isp->platform_cb.csiphy_config = csiphy_config;
231
232 phy2->isp = isp;
233 phy2->csi2 = &isp->isp_csi2a;
234 phy2->num_data_lanes = ISP_CSIPHY2_NUM_DATA_LANES;
235 phy2->cfg_regs = OMAP3_ISP_IOMEM_CSI2A_REGS1;
236 phy2->phy_regs = OMAP3_ISP_IOMEM_CSIPHY2;
237 mutex_init(&phy2->mutex);
238
239 if (isp->revision == ISP_REVISION_15_0) {
240 phy1->isp = isp;
241 phy1->csi2 = &isp->isp_csi2c;
242 phy1->num_data_lanes = ISP_CSIPHY1_NUM_DATA_LANES;
243 phy1->cfg_regs = OMAP3_ISP_IOMEM_CSI2C_REGS1;
244 phy1->phy_regs = OMAP3_ISP_IOMEM_CSIPHY1;
245 mutex_init(&phy1->mutex);
246 }
247
248 return 0;
249}
diff --git a/drivers/media/platform/omap3isp/ispcsiphy.h b/drivers/media/platform/omap3isp/ispcsiphy.h
new file mode 100644
index 000000000000..e93a661e65d9
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispcsiphy.h
@@ -0,0 +1,63 @@
1/*
2 * ispcsiphy.h
3 *
4 * TI OMAP3 ISP - CSI PHY module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#ifndef OMAP3_ISP_CSI_PHY_H
28#define OMAP3_ISP_CSI_PHY_H
29
30#include <media/omap3isp.h>
31
32struct isp_csi2_device;
33struct regulator;
34
35struct isp_csiphy_dphy_cfg {
36 u8 ths_term;
37 u8 ths_settle;
38 u8 tclk_term;
39 unsigned tclk_miss:1;
40 u8 tclk_settle;
41};
42
43struct isp_csiphy {
44 struct isp_device *isp;
45 struct mutex mutex; /* serialize csiphy configuration */
46 u8 phy_in_use;
47 struct isp_csi2_device *csi2;
48 struct regulator *vdd;
49
50 /* mem resources - enums as defined in enum isp_mem_resources */
51 unsigned int cfg_regs;
52 unsigned int phy_regs;
53
54 u8 num_data_lanes; /* number of CSI2 Data Lanes supported */
55 struct isp_csiphy_lanes_cfg lanes;
56 struct isp_csiphy_dphy_cfg dphy;
57};
58
59int omap3isp_csiphy_acquire(struct isp_csiphy *phy);
60void omap3isp_csiphy_release(struct isp_csiphy *phy);
61int omap3isp_csiphy_init(struct isp_device *isp);
62
63#endif /* OMAP3_ISP_CSI_PHY_H */
diff --git a/drivers/media/platform/omap3isp/isph3a.h b/drivers/media/platform/omap3isp/isph3a.h
new file mode 100644
index 000000000000..fb09fd4ca755
--- /dev/null
+++ b/drivers/media/platform/omap3isp/isph3a.h
@@ -0,0 +1,117 @@
1/*
2 * isph3a.h
3 *
4 * TI OMAP3 ISP - H3A AF module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: David Cohen <dacohen@gmail.com>
10 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11 * Sakari Ailus <sakari.ailus@iki.fi>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 * 02110-1301 USA
26 */
27
28#ifndef OMAP3_ISP_H3A_H
29#define OMAP3_ISP_H3A_H
30
31#include <linux/omap3isp.h>
32
33/*
34 * ----------
35 * -H3A AEWB-
36 * ----------
37 */
38
39#define AEWB_PACKET_SIZE 16
40#define AEWB_SATURATION_LIMIT 0x3ff
41
42/* Flags for changed registers */
43#define PCR_CHNG (1 << 0)
44#define AEWWIN1_CHNG (1 << 1)
45#define AEWINSTART_CHNG (1 << 2)
46#define AEWINBLK_CHNG (1 << 3)
47#define AEWSUBWIN_CHNG (1 << 4)
48#define PRV_WBDGAIN_CHNG (1 << 5)
49#define PRV_WBGAIN_CHNG (1 << 6)
50
51/* ISPH3A REGISTERS bits */
52#define ISPH3A_PCR_AF_EN (1 << 0)
53#define ISPH3A_PCR_AF_ALAW_EN (1 << 1)
54#define ISPH3A_PCR_AF_MED_EN (1 << 2)
55#define ISPH3A_PCR_AF_BUSY (1 << 15)
56#define ISPH3A_PCR_AEW_EN (1 << 16)
57#define ISPH3A_PCR_AEW_ALAW_EN (1 << 17)
58#define ISPH3A_PCR_AEW_BUSY (1 << 18)
59#define ISPH3A_PCR_AEW_MASK (ISPH3A_PCR_AEW_ALAW_EN | \
60 ISPH3A_PCR_AEW_AVE2LMT_MASK)
61
62/*
63 * --------
64 * -H3A AF-
65 * --------
66 */
67
68/* Peripheral Revision */
69#define AFPID 0x0
70
71#define AFCOEF_OFFSET 0x00000004 /* COEF base address */
72
73/* PCR fields */
74#define AF_BUSYAF (1 << 15)
75#define AF_FVMODE (1 << 14)
76#define AF_RGBPOS (0x7 << 11)
77#define AF_MED_TH (0xFF << 3)
78#define AF_MED_EN (1 << 2)
79#define AF_ALAW_EN (1 << 1)
80#define AF_EN (1 << 0)
81#define AF_PCR_MASK (AF_FVMODE | AF_RGBPOS | AF_MED_TH | \
82 AF_MED_EN | AF_ALAW_EN)
83
84/* AFPAX1 fields */
85#define AF_PAXW (0x7F << 16)
86#define AF_PAXH 0x7F
87
88/* AFPAX2 fields */
89#define AF_AFINCV (0xF << 13)
90#define AF_PAXVC (0x7F << 6)
91#define AF_PAXHC 0x3F
92
93/* AFPAXSTART fields */
94#define AF_PAXSH (0xFFF<<16)
95#define AF_PAXSV 0xFFF
96
97/* COEFFICIENT MASK */
98#define AF_COEF_MASK0 0xFFF
99#define AF_COEF_MASK1 (0xFFF<<16)
100
101/* BIT SHIFTS */
102#define AF_RGBPOS_SHIFT 11
103#define AF_MED_TH_SHIFT 3
104#define AF_PAXW_SHIFT 16
105#define AF_LINE_INCR_SHIFT 13
106#define AF_VT_COUNT_SHIFT 6
107#define AF_HZ_START_SHIFT 16
108#define AF_COEF_SHIFT 16
109
110/* Init and cleanup functions */
111int omap3isp_h3a_aewb_init(struct isp_device *isp);
112int omap3isp_h3a_af_init(struct isp_device *isp);
113
114void omap3isp_h3a_aewb_cleanup(struct isp_device *isp);
115void omap3isp_h3a_af_cleanup(struct isp_device *isp);
116
117#endif /* OMAP3_ISP_H3A_H */
diff --git a/drivers/media/platform/omap3isp/isph3a_aewb.c b/drivers/media/platform/omap3isp/isph3a_aewb.c
new file mode 100644
index 000000000000..036e9961d027
--- /dev/null
+++ b/drivers/media/platform/omap3isp/isph3a_aewb.c
@@ -0,0 +1,368 @@
1/*
2 * isph3a.c
3 *
4 * TI OMAP3 ISP - H3A module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: David Cohen <dacohen@gmail.com>
10 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11 * Sakari Ailus <sakari.ailus@iki.fi>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 * 02110-1301 USA
26 */
27
28#include <linux/slab.h>
29#include <linux/uaccess.h>
30
31#include "isp.h"
32#include "isph3a.h"
33#include "ispstat.h"
34
35/*
36 * h3a_aewb_update_regs - Helper function to update h3a registers.
37 */
38static void h3a_aewb_setup_regs(struct ispstat *aewb, void *priv)
39{
40 struct omap3isp_h3a_aewb_config *conf = priv;
41 u32 pcr;
42 u32 win1;
43 u32 start;
44 u32 blk;
45 u32 subwin;
46
47 if (aewb->state == ISPSTAT_DISABLED)
48 return;
49
50 isp_reg_writel(aewb->isp, aewb->active_buf->iommu_addr,
51 OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST);
52
53 if (!aewb->update)
54 return;
55
56 /* Converting config metadata into reg values */
57 pcr = conf->saturation_limit << ISPH3A_PCR_AEW_AVE2LMT_SHIFT;
58 pcr |= !!conf->alaw_enable << ISPH3A_PCR_AEW_ALAW_EN_SHIFT;
59
60 win1 = ((conf->win_height >> 1) - 1) << ISPH3A_AEWWIN1_WINH_SHIFT;
61 win1 |= ((conf->win_width >> 1) - 1) << ISPH3A_AEWWIN1_WINW_SHIFT;
62 win1 |= (conf->ver_win_count - 1) << ISPH3A_AEWWIN1_WINVC_SHIFT;
63 win1 |= (conf->hor_win_count - 1) << ISPH3A_AEWWIN1_WINHC_SHIFT;
64
65 start = conf->hor_win_start << ISPH3A_AEWINSTART_WINSH_SHIFT;
66 start |= conf->ver_win_start << ISPH3A_AEWINSTART_WINSV_SHIFT;
67
68 blk = conf->blk_ver_win_start << ISPH3A_AEWINBLK_WINSV_SHIFT;
69 blk |= ((conf->blk_win_height >> 1) - 1) << ISPH3A_AEWINBLK_WINH_SHIFT;
70
71 subwin = ((conf->subsample_ver_inc >> 1) - 1) <<
72 ISPH3A_AEWSUBWIN_AEWINCV_SHIFT;
73 subwin |= ((conf->subsample_hor_inc >> 1) - 1) <<
74 ISPH3A_AEWSUBWIN_AEWINCH_SHIFT;
75
76 isp_reg_writel(aewb->isp, win1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1);
77 isp_reg_writel(aewb->isp, start, OMAP3_ISP_IOMEM_H3A,
78 ISPH3A_AEWINSTART);
79 isp_reg_writel(aewb->isp, blk, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK);
80 isp_reg_writel(aewb->isp, subwin, OMAP3_ISP_IOMEM_H3A,
81 ISPH3A_AEWSUBWIN);
82 isp_reg_clr_set(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
83 ISPH3A_PCR_AEW_MASK, pcr);
84
85 aewb->update = 0;
86 aewb->config_counter += aewb->inc_config;
87 aewb->inc_config = 0;
88 aewb->buf_size = conf->buf_size;
89}
90
91static void h3a_aewb_enable(struct ispstat *aewb, int enable)
92{
93 if (enable) {
94 isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
95 ISPH3A_PCR_AEW_EN);
96 omap3isp_subclk_enable(aewb->isp, OMAP3_ISP_SUBCLK_AEWB);
97 } else {
98 isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
99 ISPH3A_PCR_AEW_EN);
100 omap3isp_subclk_disable(aewb->isp, OMAP3_ISP_SUBCLK_AEWB);
101 }
102}
103
104static int h3a_aewb_busy(struct ispstat *aewb)
105{
106 return isp_reg_readl(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
107 & ISPH3A_PCR_BUSYAEAWB;
108}
109
110static u32 h3a_aewb_get_buf_size(struct omap3isp_h3a_aewb_config *conf)
111{
112 /* Number of configured windows + extra row for black data */
113 u32 win_count = (conf->ver_win_count + 1) * conf->hor_win_count;
114
115 /*
116 * Unsaturated block counts for each 8 windows.
117 * 1 extra for the last (win_count % 8) windows if win_count is not
118 * divisible by 8.
119 */
120 win_count += (win_count + 7) / 8;
121
122 return win_count * AEWB_PACKET_SIZE;
123}
124
125static int h3a_aewb_validate_params(struct ispstat *aewb, void *new_conf)
126{
127 struct omap3isp_h3a_aewb_config *user_cfg = new_conf;
128 u32 buf_size;
129
130 if (unlikely(user_cfg->saturation_limit >
131 OMAP3ISP_AEWB_MAX_SATURATION_LIM))
132 return -EINVAL;
133
134 if (unlikely(user_cfg->win_height < OMAP3ISP_AEWB_MIN_WIN_H ||
135 user_cfg->win_height > OMAP3ISP_AEWB_MAX_WIN_H ||
136 user_cfg->win_height & 0x01))
137 return -EINVAL;
138
139 if (unlikely(user_cfg->win_width < OMAP3ISP_AEWB_MIN_WIN_W ||
140 user_cfg->win_width > OMAP3ISP_AEWB_MAX_WIN_W ||
141 user_cfg->win_width & 0x01))
142 return -EINVAL;
143
144 if (unlikely(user_cfg->ver_win_count < OMAP3ISP_AEWB_MIN_WINVC ||
145 user_cfg->ver_win_count > OMAP3ISP_AEWB_MAX_WINVC))
146 return -EINVAL;
147
148 if (unlikely(user_cfg->hor_win_count < OMAP3ISP_AEWB_MIN_WINHC ||
149 user_cfg->hor_win_count > OMAP3ISP_AEWB_MAX_WINHC))
150 return -EINVAL;
151
152 if (unlikely(user_cfg->ver_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
153 return -EINVAL;
154
155 if (unlikely(user_cfg->hor_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
156 return -EINVAL;
157
158 if (unlikely(user_cfg->blk_ver_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
159 return -EINVAL;
160
161 if (unlikely(user_cfg->blk_win_height < OMAP3ISP_AEWB_MIN_WIN_H ||
162 user_cfg->blk_win_height > OMAP3ISP_AEWB_MAX_WIN_H ||
163 user_cfg->blk_win_height & 0x01))
164 return -EINVAL;
165
166 if (unlikely(user_cfg->subsample_ver_inc < OMAP3ISP_AEWB_MIN_SUB_INC ||
167 user_cfg->subsample_ver_inc > OMAP3ISP_AEWB_MAX_SUB_INC ||
168 user_cfg->subsample_ver_inc & 0x01))
169 return -EINVAL;
170
171 if (unlikely(user_cfg->subsample_hor_inc < OMAP3ISP_AEWB_MIN_SUB_INC ||
172 user_cfg->subsample_hor_inc > OMAP3ISP_AEWB_MAX_SUB_INC ||
173 user_cfg->subsample_hor_inc & 0x01))
174 return -EINVAL;
175
176 buf_size = h3a_aewb_get_buf_size(user_cfg);
177 if (buf_size > user_cfg->buf_size)
178 user_cfg->buf_size = buf_size;
179 else if (user_cfg->buf_size > OMAP3ISP_AEWB_MAX_BUF_SIZE)
180 user_cfg->buf_size = OMAP3ISP_AEWB_MAX_BUF_SIZE;
181
182 return 0;
183}
184
185/*
186 * h3a_aewb_set_params - Helper function to check & store user given params.
187 * @new_conf: Pointer to AE and AWB parameters struct.
188 *
189 * As most of them are busy-lock registers, need to wait until AEW_BUSY = 0 to
190 * program them during ISR.
191 */
192static void h3a_aewb_set_params(struct ispstat *aewb, void *new_conf)
193{
194 struct omap3isp_h3a_aewb_config *user_cfg = new_conf;
195 struct omap3isp_h3a_aewb_config *cur_cfg = aewb->priv;
196 int update = 0;
197
198 if (cur_cfg->saturation_limit != user_cfg->saturation_limit) {
199 cur_cfg->saturation_limit = user_cfg->saturation_limit;
200 update = 1;
201 }
202 if (cur_cfg->alaw_enable != user_cfg->alaw_enable) {
203 cur_cfg->alaw_enable = user_cfg->alaw_enable;
204 update = 1;
205 }
206 if (cur_cfg->win_height != user_cfg->win_height) {
207 cur_cfg->win_height = user_cfg->win_height;
208 update = 1;
209 }
210 if (cur_cfg->win_width != user_cfg->win_width) {
211 cur_cfg->win_width = user_cfg->win_width;
212 update = 1;
213 }
214 if (cur_cfg->ver_win_count != user_cfg->ver_win_count) {
215 cur_cfg->ver_win_count = user_cfg->ver_win_count;
216 update = 1;
217 }
218 if (cur_cfg->hor_win_count != user_cfg->hor_win_count) {
219 cur_cfg->hor_win_count = user_cfg->hor_win_count;
220 update = 1;
221 }
222 if (cur_cfg->ver_win_start != user_cfg->ver_win_start) {
223 cur_cfg->ver_win_start = user_cfg->ver_win_start;
224 update = 1;
225 }
226 if (cur_cfg->hor_win_start != user_cfg->hor_win_start) {
227 cur_cfg->hor_win_start = user_cfg->hor_win_start;
228 update = 1;
229 }
230 if (cur_cfg->blk_ver_win_start != user_cfg->blk_ver_win_start) {
231 cur_cfg->blk_ver_win_start = user_cfg->blk_ver_win_start;
232 update = 1;
233 }
234 if (cur_cfg->blk_win_height != user_cfg->blk_win_height) {
235 cur_cfg->blk_win_height = user_cfg->blk_win_height;
236 update = 1;
237 }
238 if (cur_cfg->subsample_ver_inc != user_cfg->subsample_ver_inc) {
239 cur_cfg->subsample_ver_inc = user_cfg->subsample_ver_inc;
240 update = 1;
241 }
242 if (cur_cfg->subsample_hor_inc != user_cfg->subsample_hor_inc) {
243 cur_cfg->subsample_hor_inc = user_cfg->subsample_hor_inc;
244 update = 1;
245 }
246
247 if (update || !aewb->configured) {
248 aewb->inc_config++;
249 aewb->update = 1;
250 cur_cfg->buf_size = h3a_aewb_get_buf_size(cur_cfg);
251 }
252}
253
254static long h3a_aewb_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
255{
256 struct ispstat *stat = v4l2_get_subdevdata(sd);
257
258 switch (cmd) {
259 case VIDIOC_OMAP3ISP_AEWB_CFG:
260 return omap3isp_stat_config(stat, arg);
261 case VIDIOC_OMAP3ISP_STAT_REQ:
262 return omap3isp_stat_request_statistics(stat, arg);
263 case VIDIOC_OMAP3ISP_STAT_EN: {
264 unsigned long *en = arg;
265 return omap3isp_stat_enable(stat, !!*en);
266 }
267 }
268
269 return -ENOIOCTLCMD;
270}
271
272static const struct ispstat_ops h3a_aewb_ops = {
273 .validate_params = h3a_aewb_validate_params,
274 .set_params = h3a_aewb_set_params,
275 .setup_regs = h3a_aewb_setup_regs,
276 .enable = h3a_aewb_enable,
277 .busy = h3a_aewb_busy,
278};
279
280static const struct v4l2_subdev_core_ops h3a_aewb_subdev_core_ops = {
281 .ioctl = h3a_aewb_ioctl,
282 .subscribe_event = omap3isp_stat_subscribe_event,
283 .unsubscribe_event = omap3isp_stat_unsubscribe_event,
284};
285
286static const struct v4l2_subdev_video_ops h3a_aewb_subdev_video_ops = {
287 .s_stream = omap3isp_stat_s_stream,
288};
289
290static const struct v4l2_subdev_ops h3a_aewb_subdev_ops = {
291 .core = &h3a_aewb_subdev_core_ops,
292 .video = &h3a_aewb_subdev_video_ops,
293};
294
295/*
296 * omap3isp_h3a_aewb_init - Module Initialisation.
297 */
298int omap3isp_h3a_aewb_init(struct isp_device *isp)
299{
300 struct ispstat *aewb = &isp->isp_aewb;
301 struct omap3isp_h3a_aewb_config *aewb_cfg;
302 struct omap3isp_h3a_aewb_config *aewb_recover_cfg;
303 int ret;
304
305 aewb_cfg = kzalloc(sizeof(*aewb_cfg), GFP_KERNEL);
306 if (!aewb_cfg)
307 return -ENOMEM;
308
309 memset(aewb, 0, sizeof(*aewb));
310 aewb->ops = &h3a_aewb_ops;
311 aewb->priv = aewb_cfg;
312 aewb->dma_ch = -1;
313 aewb->event_type = V4L2_EVENT_OMAP3ISP_AEWB;
314 aewb->isp = isp;
315
316 /* Set recover state configuration */
317 aewb_recover_cfg = kzalloc(sizeof(*aewb_recover_cfg), GFP_KERNEL);
318 if (!aewb_recover_cfg) {
319 dev_err(aewb->isp->dev, "AEWB: cannot allocate memory for "
320 "recover configuration.\n");
321 ret = -ENOMEM;
322 goto err_recover_alloc;
323 }
324
325 aewb_recover_cfg->saturation_limit = OMAP3ISP_AEWB_MAX_SATURATION_LIM;
326 aewb_recover_cfg->win_height = OMAP3ISP_AEWB_MIN_WIN_H;
327 aewb_recover_cfg->win_width = OMAP3ISP_AEWB_MIN_WIN_W;
328 aewb_recover_cfg->ver_win_count = OMAP3ISP_AEWB_MIN_WINVC;
329 aewb_recover_cfg->hor_win_count = OMAP3ISP_AEWB_MIN_WINHC;
330 aewb_recover_cfg->blk_ver_win_start = aewb_recover_cfg->ver_win_start +
331 aewb_recover_cfg->win_height * aewb_recover_cfg->ver_win_count;
332 aewb_recover_cfg->blk_win_height = OMAP3ISP_AEWB_MIN_WIN_H;
333 aewb_recover_cfg->subsample_ver_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
334 aewb_recover_cfg->subsample_hor_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
335
336 if (h3a_aewb_validate_params(aewb, aewb_recover_cfg)) {
337 dev_err(aewb->isp->dev, "AEWB: recover configuration is "
338 "invalid.\n");
339 ret = -EINVAL;
340 goto err_conf;
341 }
342
343 aewb_recover_cfg->buf_size = h3a_aewb_get_buf_size(aewb_recover_cfg);
344 aewb->recover_priv = aewb_recover_cfg;
345
346 ret = omap3isp_stat_init(aewb, "AEWB", &h3a_aewb_subdev_ops);
347 if (ret)
348 goto err_conf;
349
350 return 0;
351
352err_conf:
353 kfree(aewb_recover_cfg);
354err_recover_alloc:
355 kfree(aewb_cfg);
356
357 return ret;
358}
359
360/*
361 * omap3isp_h3a_aewb_cleanup - Module exit.
362 */
363void omap3isp_h3a_aewb_cleanup(struct isp_device *isp)
364{
365 kfree(isp->isp_aewb.priv);
366 kfree(isp->isp_aewb.recover_priv);
367 omap3isp_stat_cleanup(&isp->isp_aewb);
368}
diff --git a/drivers/media/platform/omap3isp/isph3a_af.c b/drivers/media/platform/omap3isp/isph3a_af.c
new file mode 100644
index 000000000000..42ccce318d5d
--- /dev/null
+++ b/drivers/media/platform/omap3isp/isph3a_af.c
@@ -0,0 +1,423 @@
1/*
2 * isph3a_af.c
3 *
4 * TI OMAP3 ISP - H3A AF module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: David Cohen <dacohen@gmail.com>
10 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11 * Sakari Ailus <sakari.ailus@iki.fi>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 * 02110-1301 USA
26 */
27
28/* Linux specific include files */
29#include <linux/device.h>
30#include <linux/slab.h>
31
32#include "isp.h"
33#include "isph3a.h"
34#include "ispstat.h"
35
36#define IS_OUT_OF_BOUNDS(value, min, max) \
37 (((value) < (min)) || ((value) > (max)))
38
39static void h3a_af_setup_regs(struct ispstat *af, void *priv)
40{
41 struct omap3isp_h3a_af_config *conf = priv;
42 u32 pcr;
43 u32 pax1;
44 u32 pax2;
45 u32 paxstart;
46 u32 coef;
47 u32 base_coef_set0;
48 u32 base_coef_set1;
49 int index;
50
51 if (af->state == ISPSTAT_DISABLED)
52 return;
53
54 isp_reg_writel(af->isp, af->active_buf->iommu_addr, OMAP3_ISP_IOMEM_H3A,
55 ISPH3A_AFBUFST);
56
57 if (!af->update)
58 return;
59
60 /* Configure Hardware Registers */
61 pax1 = ((conf->paxel.width >> 1) - 1) << AF_PAXW_SHIFT;
62 /* Set height in AFPAX1 */
63 pax1 |= (conf->paxel.height >> 1) - 1;
64 isp_reg_writel(af->isp, pax1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1);
65
66 /* Configure AFPAX2 Register */
67 /* Set Line Increment in AFPAX2 Register */
68 pax2 = ((conf->paxel.line_inc >> 1) - 1) << AF_LINE_INCR_SHIFT;
69 /* Set Vertical Count */
70 pax2 |= (conf->paxel.v_cnt - 1) << AF_VT_COUNT_SHIFT;
71 /* Set Horizontal Count */
72 pax2 |= (conf->paxel.h_cnt - 1);
73 isp_reg_writel(af->isp, pax2, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2);
74
75 /* Configure PAXSTART Register */
76 /*Configure Horizontal Start */
77 paxstart = conf->paxel.h_start << AF_HZ_START_SHIFT;
78 /* Configure Vertical Start */
79 paxstart |= conf->paxel.v_start;
80 isp_reg_writel(af->isp, paxstart, OMAP3_ISP_IOMEM_H3A,
81 ISPH3A_AFPAXSTART);
82
83 /*SetIIRSH Register */
84 isp_reg_writel(af->isp, conf->iir.h_start,
85 OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH);
86
87 base_coef_set0 = ISPH3A_AFCOEF010;
88 base_coef_set1 = ISPH3A_AFCOEF110;
89 for (index = 0; index <= 8; index += 2) {
90 /*Set IIR Filter0 Coefficients */
91 coef = 0;
92 coef |= conf->iir.coeff_set0[index];
93 coef |= conf->iir.coeff_set0[index + 1] <<
94 AF_COEF_SHIFT;
95 isp_reg_writel(af->isp, coef, OMAP3_ISP_IOMEM_H3A,
96 base_coef_set0);
97 base_coef_set0 += AFCOEF_OFFSET;
98
99 /*Set IIR Filter1 Coefficients */
100 coef = 0;
101 coef |= conf->iir.coeff_set1[index];
102 coef |= conf->iir.coeff_set1[index + 1] <<
103 AF_COEF_SHIFT;
104 isp_reg_writel(af->isp, coef, OMAP3_ISP_IOMEM_H3A,
105 base_coef_set1);
106 base_coef_set1 += AFCOEF_OFFSET;
107 }
108 /* set AFCOEF0010 Register */
109 isp_reg_writel(af->isp, conf->iir.coeff_set0[10],
110 OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF0010);
111 /* set AFCOEF1010 Register */
112 isp_reg_writel(af->isp, conf->iir.coeff_set1[10],
113 OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010);
114
115 /* PCR Register */
116 /* Set RGB Position */
117 pcr = conf->rgb_pos << AF_RGBPOS_SHIFT;
118 /* Set Accumulator Mode */
119 if (conf->fvmode == OMAP3ISP_AF_MODE_PEAK)
120 pcr |= AF_FVMODE;
121 /* Set A-law */
122 if (conf->alaw_enable)
123 pcr |= AF_ALAW_EN;
124 /* HMF Configurations */
125 if (conf->hmf.enable) {
126 /* Enable HMF */
127 pcr |= AF_MED_EN;
128 /* Set Median Threshold */
129 pcr |= conf->hmf.threshold << AF_MED_TH_SHIFT;
130 }
131 /* Set PCR Register */
132 isp_reg_clr_set(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
133 AF_PCR_MASK, pcr);
134
135 af->update = 0;
136 af->config_counter += af->inc_config;
137 af->inc_config = 0;
138 af->buf_size = conf->buf_size;
139}
140
141static void h3a_af_enable(struct ispstat *af, int enable)
142{
143 if (enable) {
144 isp_reg_set(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
145 ISPH3A_PCR_AF_EN);
146 omap3isp_subclk_enable(af->isp, OMAP3_ISP_SUBCLK_AF);
147 } else {
148 isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
149 ISPH3A_PCR_AF_EN);
150 omap3isp_subclk_disable(af->isp, OMAP3_ISP_SUBCLK_AF);
151 }
152}
153
154static int h3a_af_busy(struct ispstat *af)
155{
156 return isp_reg_readl(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
157 & ISPH3A_PCR_BUSYAF;
158}
159
160static u32 h3a_af_get_buf_size(struct omap3isp_h3a_af_config *conf)
161{
162 return conf->paxel.h_cnt * conf->paxel.v_cnt * OMAP3ISP_AF_PAXEL_SIZE;
163}
164
165/* Function to check paxel parameters */
166static int h3a_af_validate_params(struct ispstat *af, void *new_conf)
167{
168 struct omap3isp_h3a_af_config *user_cfg = new_conf;
169 struct omap3isp_h3a_af_paxel *paxel_cfg = &user_cfg->paxel;
170 struct omap3isp_h3a_af_iir *iir_cfg = &user_cfg->iir;
171 int index;
172 u32 buf_size;
173
174 /* Check horizontal Count */
175 if (IS_OUT_OF_BOUNDS(paxel_cfg->h_cnt,
176 OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN,
177 OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MAX))
178 return -EINVAL;
179
180 /* Check Vertical Count */
181 if (IS_OUT_OF_BOUNDS(paxel_cfg->v_cnt,
182 OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN,
183 OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MAX))
184 return -EINVAL;
185
186 if (IS_OUT_OF_BOUNDS(paxel_cfg->height, OMAP3ISP_AF_PAXEL_HEIGHT_MIN,
187 OMAP3ISP_AF_PAXEL_HEIGHT_MAX) ||
188 paxel_cfg->height % 2)
189 return -EINVAL;
190
191 /* Check width */
192 if (IS_OUT_OF_BOUNDS(paxel_cfg->width, OMAP3ISP_AF_PAXEL_WIDTH_MIN,
193 OMAP3ISP_AF_PAXEL_WIDTH_MAX) ||
194 paxel_cfg->width % 2)
195 return -EINVAL;
196
197 /* Check Line Increment */
198 if (IS_OUT_OF_BOUNDS(paxel_cfg->line_inc,
199 OMAP3ISP_AF_PAXEL_INCREMENT_MIN,
200 OMAP3ISP_AF_PAXEL_INCREMENT_MAX) ||
201 paxel_cfg->line_inc % 2)
202 return -EINVAL;
203
204 /* Check Horizontal Start */
205 if ((paxel_cfg->h_start < iir_cfg->h_start) ||
206 IS_OUT_OF_BOUNDS(paxel_cfg->h_start,
207 OMAP3ISP_AF_PAXEL_HZSTART_MIN,
208 OMAP3ISP_AF_PAXEL_HZSTART_MAX))
209 return -EINVAL;
210
211 /* Check IIR */
212 for (index = 0; index < OMAP3ISP_AF_NUM_COEF; index++) {
213 if ((iir_cfg->coeff_set0[index]) > OMAP3ISP_AF_COEF_MAX)
214 return -EINVAL;
215
216 if ((iir_cfg->coeff_set1[index]) > OMAP3ISP_AF_COEF_MAX)
217 return -EINVAL;
218 }
219
220 if (IS_OUT_OF_BOUNDS(iir_cfg->h_start, OMAP3ISP_AF_IIRSH_MIN,
221 OMAP3ISP_AF_IIRSH_MAX))
222 return -EINVAL;
223
224 /* Hack: If paxel size is 12, the 10th AF window may be corrupted */
225 if ((paxel_cfg->h_cnt * paxel_cfg->v_cnt > 9) &&
226 (paxel_cfg->width * paxel_cfg->height == 12))
227 return -EINVAL;
228
229 buf_size = h3a_af_get_buf_size(user_cfg);
230 if (buf_size > user_cfg->buf_size)
231 /* User buf_size request wasn't enough */
232 user_cfg->buf_size = buf_size;
233 else if (user_cfg->buf_size > OMAP3ISP_AF_MAX_BUF_SIZE)
234 user_cfg->buf_size = OMAP3ISP_AF_MAX_BUF_SIZE;
235
236 return 0;
237}
238
239/* Update local parameters */
240static void h3a_af_set_params(struct ispstat *af, void *new_conf)
241{
242 struct omap3isp_h3a_af_config *user_cfg = new_conf;
243 struct omap3isp_h3a_af_config *cur_cfg = af->priv;
244 int update = 0;
245 int index;
246
247 /* alaw */
248 if (cur_cfg->alaw_enable != user_cfg->alaw_enable) {
249 update = 1;
250 goto out;
251 }
252
253 /* hmf */
254 if (cur_cfg->hmf.enable != user_cfg->hmf.enable) {
255 update = 1;
256 goto out;
257 }
258 if (cur_cfg->hmf.threshold != user_cfg->hmf.threshold) {
259 update = 1;
260 goto out;
261 }
262
263 /* rgbpos */
264 if (cur_cfg->rgb_pos != user_cfg->rgb_pos) {
265 update = 1;
266 goto out;
267 }
268
269 /* iir */
270 if (cur_cfg->iir.h_start != user_cfg->iir.h_start) {
271 update = 1;
272 goto out;
273 }
274 for (index = 0; index < OMAP3ISP_AF_NUM_COEF; index++) {
275 if (cur_cfg->iir.coeff_set0[index] !=
276 user_cfg->iir.coeff_set0[index]) {
277 update = 1;
278 goto out;
279 }
280 if (cur_cfg->iir.coeff_set1[index] !=
281 user_cfg->iir.coeff_set1[index]) {
282 update = 1;
283 goto out;
284 }
285 }
286
287 /* paxel */
288 if ((cur_cfg->paxel.width != user_cfg->paxel.width) ||
289 (cur_cfg->paxel.height != user_cfg->paxel.height) ||
290 (cur_cfg->paxel.h_start != user_cfg->paxel.h_start) ||
291 (cur_cfg->paxel.v_start != user_cfg->paxel.v_start) ||
292 (cur_cfg->paxel.h_cnt != user_cfg->paxel.h_cnt) ||
293 (cur_cfg->paxel.v_cnt != user_cfg->paxel.v_cnt) ||
294 (cur_cfg->paxel.line_inc != user_cfg->paxel.line_inc)) {
295 update = 1;
296 goto out;
297 }
298
299 /* af_mode */
300 if (cur_cfg->fvmode != user_cfg->fvmode)
301 update = 1;
302
303out:
304 if (update || !af->configured) {
305 memcpy(cur_cfg, user_cfg, sizeof(*cur_cfg));
306 af->inc_config++;
307 af->update = 1;
308 /*
309 * User might be asked for a bigger buffer than necessary for
310 * this configuration. In order to return the right amount of
311 * data during buffer request, let's calculate the size here
312 * instead of stick with user_cfg->buf_size.
313 */
314 cur_cfg->buf_size = h3a_af_get_buf_size(cur_cfg);
315 }
316}
317
318static long h3a_af_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
319{
320 struct ispstat *stat = v4l2_get_subdevdata(sd);
321
322 switch (cmd) {
323 case VIDIOC_OMAP3ISP_AF_CFG:
324 return omap3isp_stat_config(stat, arg);
325 case VIDIOC_OMAP3ISP_STAT_REQ:
326 return omap3isp_stat_request_statistics(stat, arg);
327 case VIDIOC_OMAP3ISP_STAT_EN: {
328 int *en = arg;
329 return omap3isp_stat_enable(stat, !!*en);
330 }
331 }
332
333 return -ENOIOCTLCMD;
334
335}
336
337static const struct ispstat_ops h3a_af_ops = {
338 .validate_params = h3a_af_validate_params,
339 .set_params = h3a_af_set_params,
340 .setup_regs = h3a_af_setup_regs,
341 .enable = h3a_af_enable,
342 .busy = h3a_af_busy,
343};
344
345static const struct v4l2_subdev_core_ops h3a_af_subdev_core_ops = {
346 .ioctl = h3a_af_ioctl,
347 .subscribe_event = omap3isp_stat_subscribe_event,
348 .unsubscribe_event = omap3isp_stat_unsubscribe_event,
349};
350
351static const struct v4l2_subdev_video_ops h3a_af_subdev_video_ops = {
352 .s_stream = omap3isp_stat_s_stream,
353};
354
355static const struct v4l2_subdev_ops h3a_af_subdev_ops = {
356 .core = &h3a_af_subdev_core_ops,
357 .video = &h3a_af_subdev_video_ops,
358};
359
360/* Function to register the AF character device driver. */
361int omap3isp_h3a_af_init(struct isp_device *isp)
362{
363 struct ispstat *af = &isp->isp_af;
364 struct omap3isp_h3a_af_config *af_cfg;
365 struct omap3isp_h3a_af_config *af_recover_cfg;
366 int ret;
367
368 af_cfg = kzalloc(sizeof(*af_cfg), GFP_KERNEL);
369 if (af_cfg == NULL)
370 return -ENOMEM;
371
372 memset(af, 0, sizeof(*af));
373 af->ops = &h3a_af_ops;
374 af->priv = af_cfg;
375 af->dma_ch = -1;
376 af->event_type = V4L2_EVENT_OMAP3ISP_AF;
377 af->isp = isp;
378
379 /* Set recover state configuration */
380 af_recover_cfg = kzalloc(sizeof(*af_recover_cfg), GFP_KERNEL);
381 if (!af_recover_cfg) {
382 dev_err(af->isp->dev, "AF: cannot allocate memory for recover "
383 "configuration.\n");
384 ret = -ENOMEM;
385 goto err_recover_alloc;
386 }
387
388 af_recover_cfg->paxel.h_start = OMAP3ISP_AF_PAXEL_HZSTART_MIN;
389 af_recover_cfg->paxel.width = OMAP3ISP_AF_PAXEL_WIDTH_MIN;
390 af_recover_cfg->paxel.height = OMAP3ISP_AF_PAXEL_HEIGHT_MIN;
391 af_recover_cfg->paxel.h_cnt = OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN;
392 af_recover_cfg->paxel.v_cnt = OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN;
393 af_recover_cfg->paxel.line_inc = OMAP3ISP_AF_PAXEL_INCREMENT_MIN;
394 if (h3a_af_validate_params(af, af_recover_cfg)) {
395 dev_err(af->isp->dev, "AF: recover configuration is "
396 "invalid.\n");
397 ret = -EINVAL;
398 goto err_conf;
399 }
400
401 af_recover_cfg->buf_size = h3a_af_get_buf_size(af_recover_cfg);
402 af->recover_priv = af_recover_cfg;
403
404 ret = omap3isp_stat_init(af, "AF", &h3a_af_subdev_ops);
405 if (ret)
406 goto err_conf;
407
408 return 0;
409
410err_conf:
411 kfree(af_recover_cfg);
412err_recover_alloc:
413 kfree(af_cfg);
414
415 return ret;
416}
417
418void omap3isp_h3a_af_cleanup(struct isp_device *isp)
419{
420 kfree(isp->isp_af.priv);
421 kfree(isp->isp_af.recover_priv);
422 omap3isp_stat_cleanup(&isp->isp_af);
423}
diff --git a/drivers/media/platform/omap3isp/isphist.c b/drivers/media/platform/omap3isp/isphist.c
new file mode 100644
index 000000000000..d1a8dee5e1ca
--- /dev/null
+++ b/drivers/media/platform/omap3isp/isphist.c
@@ -0,0 +1,518 @@
1/*
2 * isphist.c
3 *
4 * TI OMAP3 ISP - Histogram module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: David Cohen <dacohen@gmail.com>
10 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11 * Sakari Ailus <sakari.ailus@iki.fi>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 * 02110-1301 USA
26 */
27
28#include <linux/delay.h>
29#include <linux/slab.h>
30#include <linux/uaccess.h>
31#include <linux/device.h>
32
33#include "isp.h"
34#include "ispreg.h"
35#include "isphist.h"
36
37#define HIST_CONFIG_DMA 1
38
39#define HIST_USING_DMA(hist) ((hist)->dma_ch >= 0)
40
41/*
42 * hist_reset_mem - clear Histogram memory before start stats engine.
43 */
44static void hist_reset_mem(struct ispstat *hist)
45{
46 struct isp_device *isp = hist->isp;
47 struct omap3isp_hist_config *conf = hist->priv;
48 unsigned int i;
49
50 isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
51
52 /*
53 * By setting it, the histogram internal buffer is being cleared at the
54 * same time it's being read. This bit must be cleared afterwards.
55 */
56 isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);
57
58 /*
59 * We'll clear 4 words at each iteration for optimization. It avoids
60 * 3/4 of the jumps. We also know HIST_MEM_SIZE is divisible by 4.
61 */
62 for (i = OMAP3ISP_HIST_MEM_SIZE / 4; i > 0; i--) {
63 isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
64 isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
65 isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
66 isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
67 }
68 isp_reg_clr(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);
69
70 hist->wait_acc_frames = conf->num_acc_frames;
71}
72
73static void hist_dma_config(struct ispstat *hist)
74{
75 hist->dma_config.data_type = OMAP_DMA_DATA_TYPE_S32;
76 hist->dma_config.sync_mode = OMAP_DMA_SYNC_ELEMENT;
77 hist->dma_config.frame_count = 1;
78 hist->dma_config.src_amode = OMAP_DMA_AMODE_CONSTANT;
79 hist->dma_config.src_start = OMAP3ISP_HIST_REG_BASE + ISPHIST_DATA;
80 hist->dma_config.dst_amode = OMAP_DMA_AMODE_POST_INC;
81 hist->dma_config.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
82}
83
84/*
85 * hist_setup_regs - Helper function to update Histogram registers.
86 */
87static void hist_setup_regs(struct ispstat *hist, void *priv)
88{
89 struct isp_device *isp = hist->isp;
90 struct omap3isp_hist_config *conf = priv;
91 int c;
92 u32 cnt;
93 u32 wb_gain;
94 u32 reg_hor[OMAP3ISP_HIST_MAX_REGIONS];
95 u32 reg_ver[OMAP3ISP_HIST_MAX_REGIONS];
96
97 if (!hist->update || hist->state == ISPSTAT_DISABLED ||
98 hist->state == ISPSTAT_DISABLING)
99 return;
100
101 cnt = conf->cfa << ISPHIST_CNT_CFA_SHIFT;
102
103 wb_gain = conf->wg[0] << ISPHIST_WB_GAIN_WG00_SHIFT;
104 wb_gain |= conf->wg[1] << ISPHIST_WB_GAIN_WG01_SHIFT;
105 wb_gain |= conf->wg[2] << ISPHIST_WB_GAIN_WG02_SHIFT;
106 if (conf->cfa == OMAP3ISP_HIST_CFA_BAYER)
107 wb_gain |= conf->wg[3] << ISPHIST_WB_GAIN_WG03_SHIFT;
108
109 /* Regions size and position */
110 for (c = 0; c < OMAP3ISP_HIST_MAX_REGIONS; c++) {
111 if (c < conf->num_regions) {
112 reg_hor[c] = conf->region[c].h_start <<
113 ISPHIST_REG_START_SHIFT;
114 reg_hor[c] = conf->region[c].h_end <<
115 ISPHIST_REG_END_SHIFT;
116 reg_ver[c] = conf->region[c].v_start <<
117 ISPHIST_REG_START_SHIFT;
118 reg_ver[c] = conf->region[c].v_end <<
119 ISPHIST_REG_END_SHIFT;
120 } else {
121 reg_hor[c] = 0;
122 reg_ver[c] = 0;
123 }
124 }
125
126 cnt |= conf->hist_bins << ISPHIST_CNT_BINS_SHIFT;
127 switch (conf->hist_bins) {
128 case OMAP3ISP_HIST_BINS_256:
129 cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 8) <<
130 ISPHIST_CNT_SHIFT_SHIFT;
131 break;
132 case OMAP3ISP_HIST_BINS_128:
133 cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 7) <<
134 ISPHIST_CNT_SHIFT_SHIFT;
135 break;
136 case OMAP3ISP_HIST_BINS_64:
137 cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 6) <<
138 ISPHIST_CNT_SHIFT_SHIFT;
139 break;
140 default: /* OMAP3ISP_HIST_BINS_32 */
141 cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 5) <<
142 ISPHIST_CNT_SHIFT_SHIFT;
143 break;
144 }
145
146 hist_reset_mem(hist);
147
148 isp_reg_writel(isp, cnt, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT);
149 isp_reg_writel(isp, wb_gain, OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN);
150 isp_reg_writel(isp, reg_hor[0], OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ);
151 isp_reg_writel(isp, reg_ver[0], OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT);
152 isp_reg_writel(isp, reg_hor[1], OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ);
153 isp_reg_writel(isp, reg_ver[1], OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT);
154 isp_reg_writel(isp, reg_hor[2], OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ);
155 isp_reg_writel(isp, reg_ver[2], OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT);
156 isp_reg_writel(isp, reg_hor[3], OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ);
157 isp_reg_writel(isp, reg_ver[3], OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT);
158
159 hist->update = 0;
160 hist->config_counter += hist->inc_config;
161 hist->inc_config = 0;
162 hist->buf_size = conf->buf_size;
163}
164
165static void hist_enable(struct ispstat *hist, int enable)
166{
167 if (enable) {
168 isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR,
169 ISPHIST_PCR_ENABLE);
170 omap3isp_subclk_enable(hist->isp, OMAP3_ISP_SUBCLK_HIST);
171 } else {
172 isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR,
173 ISPHIST_PCR_ENABLE);
174 omap3isp_subclk_disable(hist->isp, OMAP3_ISP_SUBCLK_HIST);
175 }
176}
177
178static int hist_busy(struct ispstat *hist)
179{
180 return isp_reg_readl(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR)
181 & ISPHIST_PCR_BUSY;
182}
183
184static void hist_dma_cb(int lch, u16 ch_status, void *data)
185{
186 struct ispstat *hist = data;
187
188 if (ch_status & ~OMAP_DMA_BLOCK_IRQ) {
189 dev_dbg(hist->isp->dev, "hist: DMA error. status = 0x%04x\n",
190 ch_status);
191 omap_stop_dma(lch);
192 hist_reset_mem(hist);
193 atomic_set(&hist->buf_err, 1);
194 }
195 isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
196 ISPHIST_CNT_CLEAR);
197
198 omap3isp_stat_dma_isr(hist);
199 if (hist->state != ISPSTAT_DISABLED)
200 omap3isp_hist_dma_done(hist->isp);
201}
202
203static int hist_buf_dma(struct ispstat *hist)
204{
205 dma_addr_t dma_addr = hist->active_buf->dma_addr;
206
207 if (unlikely(!dma_addr)) {
208 dev_dbg(hist->isp->dev, "hist: invalid DMA buffer address\n");
209 hist_reset_mem(hist);
210 return STAT_NO_BUF;
211 }
212
213 isp_reg_writel(hist->isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
214 isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
215 ISPHIST_CNT_CLEAR);
216 omap3isp_flush(hist->isp);
217 hist->dma_config.dst_start = dma_addr;
218 hist->dma_config.elem_count = hist->buf_size / sizeof(u32);
219 omap_set_dma_params(hist->dma_ch, &hist->dma_config);
220
221 omap_start_dma(hist->dma_ch);
222
223 return STAT_BUF_WAITING_DMA;
224}
225
226static int hist_buf_pio(struct ispstat *hist)
227{
228 struct isp_device *isp = hist->isp;
229 u32 *buf = hist->active_buf->virt_addr;
230 unsigned int i;
231
232 if (!buf) {
233 dev_dbg(isp->dev, "hist: invalid PIO buffer address\n");
234 hist_reset_mem(hist);
235 return STAT_NO_BUF;
236 }
237
238 isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
239
240 /*
241 * By setting it, the histogram internal buffer is being cleared at the
242 * same time it's being read. This bit must be cleared just after all
243 * data is acquired.
244 */
245 isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);
246
247 /*
248 * We'll read 4 times a 4-bytes-word at each iteration for
249 * optimization. It avoids 3/4 of the jumps. We also know buf_size is
250 * divisible by 16.
251 */
252 for (i = hist->buf_size / 16; i > 0; i--) {
253 *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
254 *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
255 *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
256 *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
257 }
258 isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
259 ISPHIST_CNT_CLEAR);
260
261 return STAT_BUF_DONE;
262}
263
264/*
265 * hist_buf_process - Callback from ISP driver for HIST interrupt.
266 */
267static int hist_buf_process(struct ispstat *hist)
268{
269 struct omap3isp_hist_config *user_cfg = hist->priv;
270 int ret;
271
272 if (atomic_read(&hist->buf_err) || hist->state != ISPSTAT_ENABLED) {
273 hist_reset_mem(hist);
274 return STAT_NO_BUF;
275 }
276
277 if (--(hist->wait_acc_frames))
278 return STAT_NO_BUF;
279
280 if (HIST_USING_DMA(hist))
281 ret = hist_buf_dma(hist);
282 else
283 ret = hist_buf_pio(hist);
284
285 hist->wait_acc_frames = user_cfg->num_acc_frames;
286
287 return ret;
288}
289
290static u32 hist_get_buf_size(struct omap3isp_hist_config *conf)
291{
292 return OMAP3ISP_HIST_MEM_SIZE_BINS(conf->hist_bins) * conf->num_regions;
293}
294
295/*
296 * hist_validate_params - Helper function to check user given params.
297 * @user_cfg: Pointer to user configuration structure.
298 *
299 * Returns 0 on success configuration.
300 */
301static int hist_validate_params(struct ispstat *hist, void *new_conf)
302{
303 struct omap3isp_hist_config *user_cfg = new_conf;
304 int c;
305 u32 buf_size;
306
307 if (user_cfg->cfa > OMAP3ISP_HIST_CFA_FOVEONX3)
308 return -EINVAL;
309
310 /* Regions size and position */
311
312 if ((user_cfg->num_regions < OMAP3ISP_HIST_MIN_REGIONS) ||
313 (user_cfg->num_regions > OMAP3ISP_HIST_MAX_REGIONS))
314 return -EINVAL;
315
316 /* Regions */
317 for (c = 0; c < user_cfg->num_regions; c++) {
318 if (user_cfg->region[c].h_start & ~ISPHIST_REG_START_END_MASK)
319 return -EINVAL;
320 if (user_cfg->region[c].h_end & ~ISPHIST_REG_START_END_MASK)
321 return -EINVAL;
322 if (user_cfg->region[c].v_start & ~ISPHIST_REG_START_END_MASK)
323 return -EINVAL;
324 if (user_cfg->region[c].v_end & ~ISPHIST_REG_START_END_MASK)
325 return -EINVAL;
326 if (user_cfg->region[c].h_start > user_cfg->region[c].h_end)
327 return -EINVAL;
328 if (user_cfg->region[c].v_start > user_cfg->region[c].v_end)
329 return -EINVAL;
330 }
331
332 switch (user_cfg->num_regions) {
333 case 1:
334 if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_256)
335 return -EINVAL;
336 break;
337 case 2:
338 if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_128)
339 return -EINVAL;
340 break;
341 default: /* 3 or 4 */
342 if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_64)
343 return -EINVAL;
344 break;
345 }
346
347 buf_size = hist_get_buf_size(user_cfg);
348 if (buf_size > user_cfg->buf_size)
349 /* User's buf_size request wasn't enoght */
350 user_cfg->buf_size = buf_size;
351 else if (user_cfg->buf_size > OMAP3ISP_HIST_MAX_BUF_SIZE)
352 user_cfg->buf_size = OMAP3ISP_HIST_MAX_BUF_SIZE;
353
354 return 0;
355}
356
357static int hist_comp_params(struct ispstat *hist,
358 struct omap3isp_hist_config *user_cfg)
359{
360 struct omap3isp_hist_config *cur_cfg = hist->priv;
361 int c;
362
363 if (cur_cfg->cfa != user_cfg->cfa)
364 return 1;
365
366 if (cur_cfg->num_acc_frames != user_cfg->num_acc_frames)
367 return 1;
368
369 if (cur_cfg->hist_bins != user_cfg->hist_bins)
370 return 1;
371
372 for (c = 0; c < OMAP3ISP_HIST_MAX_WG; c++) {
373 if (c == 3 && user_cfg->cfa == OMAP3ISP_HIST_CFA_FOVEONX3)
374 break;
375 else if (cur_cfg->wg[c] != user_cfg->wg[c])
376 return 1;
377 }
378
379 if (cur_cfg->num_regions != user_cfg->num_regions)
380 return 1;
381
382 /* Regions */
383 for (c = 0; c < user_cfg->num_regions; c++) {
384 if (cur_cfg->region[c].h_start != user_cfg->region[c].h_start)
385 return 1;
386 if (cur_cfg->region[c].h_end != user_cfg->region[c].h_end)
387 return 1;
388 if (cur_cfg->region[c].v_start != user_cfg->region[c].v_start)
389 return 1;
390 if (cur_cfg->region[c].v_end != user_cfg->region[c].v_end)
391 return 1;
392 }
393
394 return 0;
395}
396
397/*
398 * hist_update_params - Helper function to check and store user given params.
399 * @new_conf: Pointer to user configuration structure.
400 */
401static void hist_set_params(struct ispstat *hist, void *new_conf)
402{
403 struct omap3isp_hist_config *user_cfg = new_conf;
404 struct omap3isp_hist_config *cur_cfg = hist->priv;
405
406 if (!hist->configured || hist_comp_params(hist, user_cfg)) {
407 memcpy(cur_cfg, user_cfg, sizeof(*user_cfg));
408 if (user_cfg->num_acc_frames == 0)
409 user_cfg->num_acc_frames = 1;
410 hist->inc_config++;
411 hist->update = 1;
412 /*
413 * User might be asked for a bigger buffer than necessary for
414 * this configuration. In order to return the right amount of
415 * data during buffer request, let's calculate the size here
416 * instead of stick with user_cfg->buf_size.
417 */
418 cur_cfg->buf_size = hist_get_buf_size(cur_cfg);
419
420 }
421}
422
423static long hist_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
424{
425 struct ispstat *stat = v4l2_get_subdevdata(sd);
426
427 switch (cmd) {
428 case VIDIOC_OMAP3ISP_HIST_CFG:
429 return omap3isp_stat_config(stat, arg);
430 case VIDIOC_OMAP3ISP_STAT_REQ:
431 return omap3isp_stat_request_statistics(stat, arg);
432 case VIDIOC_OMAP3ISP_STAT_EN: {
433 int *en = arg;
434 return omap3isp_stat_enable(stat, !!*en);
435 }
436 }
437
438 return -ENOIOCTLCMD;
439
440}
441
442static const struct ispstat_ops hist_ops = {
443 .validate_params = hist_validate_params,
444 .set_params = hist_set_params,
445 .setup_regs = hist_setup_regs,
446 .enable = hist_enable,
447 .busy = hist_busy,
448 .buf_process = hist_buf_process,
449};
450
451static const struct v4l2_subdev_core_ops hist_subdev_core_ops = {
452 .ioctl = hist_ioctl,
453 .subscribe_event = omap3isp_stat_subscribe_event,
454 .unsubscribe_event = omap3isp_stat_unsubscribe_event,
455};
456
457static const struct v4l2_subdev_video_ops hist_subdev_video_ops = {
458 .s_stream = omap3isp_stat_s_stream,
459};
460
461static const struct v4l2_subdev_ops hist_subdev_ops = {
462 .core = &hist_subdev_core_ops,
463 .video = &hist_subdev_video_ops,
464};
465
466/*
467 * omap3isp_hist_init - Module Initialization.
468 */
469int omap3isp_hist_init(struct isp_device *isp)
470{
471 struct ispstat *hist = &isp->isp_hist;
472 struct omap3isp_hist_config *hist_cfg;
473 int ret = -1;
474
475 hist_cfg = kzalloc(sizeof(*hist_cfg), GFP_KERNEL);
476 if (hist_cfg == NULL)
477 return -ENOMEM;
478
479 memset(hist, 0, sizeof(*hist));
480 if (HIST_CONFIG_DMA)
481 ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, "DMA_ISP_HIST",
482 hist_dma_cb, hist, &hist->dma_ch);
483 if (ret) {
484 if (HIST_CONFIG_DMA)
485 dev_warn(isp->dev, "hist: DMA request channel failed. "
486 "Using PIO only.\n");
487 hist->dma_ch = -1;
488 } else {
489 dev_dbg(isp->dev, "hist: DMA channel = %d\n", hist->dma_ch);
490 hist_dma_config(hist);
491 omap_enable_dma_irq(hist->dma_ch, OMAP_DMA_BLOCK_IRQ);
492 }
493
494 hist->ops = &hist_ops;
495 hist->priv = hist_cfg;
496 hist->event_type = V4L2_EVENT_OMAP3ISP_HIST;
497 hist->isp = isp;
498
499 ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops);
500 if (ret) {
501 kfree(hist_cfg);
502 if (HIST_USING_DMA(hist))
503 omap_free_dma(hist->dma_ch);
504 }
505
506 return ret;
507}
508
509/*
510 * omap3isp_hist_cleanup - Module cleanup.
511 */
512void omap3isp_hist_cleanup(struct isp_device *isp)
513{
514 if (HIST_USING_DMA(&isp->isp_hist))
515 omap_free_dma(isp->isp_hist.dma_ch);
516 kfree(isp->isp_hist.priv);
517 omap3isp_stat_cleanup(&isp->isp_hist);
518}
diff --git a/drivers/media/platform/omap3isp/isphist.h b/drivers/media/platform/omap3isp/isphist.h
new file mode 100644
index 000000000000..0b2a38ec94c4
--- /dev/null
+++ b/drivers/media/platform/omap3isp/isphist.h
@@ -0,0 +1,40 @@
1/*
2 * isphist.h
3 *
4 * TI OMAP3 ISP - Histogram module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: David Cohen <dacohen@gmail.com>
10 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11 * Sakari Ailus <sakari.ailus@iki.fi>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 * 02110-1301 USA
26 */
27
28#ifndef OMAP3_ISP_HIST_H
29#define OMAP3_ISP_HIST_H
30
31#include <linux/omap3isp.h>
32
33#define ISPHIST_IN_BIT_WIDTH_CCDC 10
34
35struct isp_device;
36
37int omap3isp_hist_init(struct isp_device *isp);
38void omap3isp_hist_cleanup(struct isp_device *isp);
39
40#endif /* OMAP3_ISP_HIST */
diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c
new file mode 100644
index 000000000000..1ae1c0909ed1
--- /dev/null
+++ b/drivers/media/platform/omap3isp/isppreview.c
@@ -0,0 +1,2348 @@
1/*
2 * isppreview.c
3 *
4 * TI OMAP3 ISP driver - Preview module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#include <linux/device.h>
28#include <linux/mm.h>
29#include <linux/module.h>
30#include <linux/mutex.h>
31#include <linux/uaccess.h>
32
33#include "isp.h"
34#include "ispreg.h"
35#include "isppreview.h"
36
37/* Default values in Office Fluorescent Light for RGBtoRGB Blending */
38static struct omap3isp_prev_rgbtorgb flr_rgb2rgb = {
39 { /* RGB-RGB Matrix */
40 {0x01E2, 0x0F30, 0x0FEE},
41 {0x0F9B, 0x01AC, 0x0FB9},
42 {0x0FE0, 0x0EC0, 0x0260}
43 }, /* RGB Offset */
44 {0x0000, 0x0000, 0x0000}
45};
46
47/* Default values in Office Fluorescent Light for RGB to YUV Conversion*/
48static struct omap3isp_prev_csc flr_prev_csc = {
49 { /* CSC Coef Matrix */
50 {66, 129, 25},
51 {-38, -75, 112},
52 {112, -94 , -18}
53 }, /* CSC Offset */
54 {0x0, 0x0, 0x0}
55};
56
57/* Default values in Office Fluorescent Light for CFA Gradient*/
58#define FLR_CFA_GRADTHRS_HORZ 0x28
59#define FLR_CFA_GRADTHRS_VERT 0x28
60
61/* Default values in Office Fluorescent Light for Chroma Suppression*/
62#define FLR_CSUP_GAIN 0x0D
63#define FLR_CSUP_THRES 0xEB
64
65/* Default values in Office Fluorescent Light for Noise Filter*/
66#define FLR_NF_STRGTH 0x03
67
68/* Default values for White Balance */
69#define FLR_WBAL_DGAIN 0x100
70#define FLR_WBAL_COEF 0x20
71
72/* Default values in Office Fluorescent Light for Black Adjustment*/
73#define FLR_BLKADJ_BLUE 0x0
74#define FLR_BLKADJ_GREEN 0x0
75#define FLR_BLKADJ_RED 0x0
76
77#define DEF_DETECT_CORRECT_VAL 0xe
78
79/*
80 * Margins and image size limits.
81 *
82 * The preview engine crops several rows and columns internally depending on
83 * which filters are enabled. To avoid format changes when the filters are
84 * enabled or disabled (which would prevent them from being turned on or off
85 * during streaming), the driver assumes all the filters are enabled when
86 * computing sink crop and source format limits.
87 *
88 * If a filter is disabled, additional cropping is automatically added at the
89 * preview engine input by the driver to avoid overflow at line and frame end.
90 * This is completely transparent for applications.
91 *
92 * Median filter 4 pixels
93 * Noise filter,
94 * Faulty pixels correction 4 pixels, 4 lines
95 * CFA filter 4 pixels, 4 lines in Bayer mode
96 * 2 lines in other modes
97 * Color suppression 2 pixels
98 * or luma enhancement
99 * -------------------------------------------------------------
100 * Maximum total 14 pixels, 8 lines
101 *
102 * The color suppression and luma enhancement filters are applied after bayer to
103 * YUV conversion. They thus can crop one pixel on the left and one pixel on the
104 * right side of the image without changing the color pattern. When both those
105 * filters are disabled, the driver must crop the two pixels on the same side of
106 * the image to avoid changing the bayer pattern. The left margin is thus set to
107 * 8 pixels and the right margin to 6 pixels.
108 */
109
110#define PREV_MARGIN_LEFT 8
111#define PREV_MARGIN_RIGHT 6
112#define PREV_MARGIN_TOP 4
113#define PREV_MARGIN_BOTTOM 4
114
115#define PREV_MIN_IN_WIDTH 64
116#define PREV_MIN_IN_HEIGHT 8
117#define PREV_MAX_IN_HEIGHT 16384
118
119#define PREV_MIN_OUT_WIDTH 0
120#define PREV_MIN_OUT_HEIGHT 0
121#define PREV_MAX_OUT_WIDTH_REV_1 1280
122#define PREV_MAX_OUT_WIDTH_REV_2 3300
123#define PREV_MAX_OUT_WIDTH_REV_15 4096
124
125/*
126 * Coeficient Tables for the submodules in Preview.
127 * Array is initialised with the values from.the tables text file.
128 */
129
130/*
131 * CFA Filter Coefficient Table
132 *
133 */
134static u32 cfa_coef_table[4][OMAP3ISP_PREV_CFA_BLK_SIZE] = {
135#include "cfa_coef_table.h"
136};
137
138/*
139 * Default Gamma Correction Table - All components
140 */
141static u32 gamma_table[] = {
142#include "gamma_table.h"
143};
144
145/*
146 * Noise Filter Threshold table
147 */
148static u32 noise_filter_table[] = {
149#include "noise_filter_table.h"
150};
151
152/*
153 * Luminance Enhancement Table
154 */
155static u32 luma_enhance_table[] = {
156#include "luma_enhance_table.h"
157};
158
159/*
160 * preview_config_luma_enhancement - Configure the Luminance Enhancement table
161 */
162static void
163preview_config_luma_enhancement(struct isp_prev_device *prev,
164 const struct prev_params *params)
165{
166 struct isp_device *isp = to_isp_device(prev);
167 const struct omap3isp_prev_luma *yt = &params->luma;
168 unsigned int i;
169
170 isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR,
171 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
172 for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) {
173 isp_reg_writel(isp, yt->table[i],
174 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
175 }
176}
177
178/*
179 * preview_enable_luma_enhancement - Enable/disable Luminance Enhancement
180 */
181static void
182preview_enable_luma_enhancement(struct isp_prev_device *prev, bool enable)
183{
184 struct isp_device *isp = to_isp_device(prev);
185
186 if (enable)
187 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
188 ISPPRV_PCR_YNENHEN);
189 else
190 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
191 ISPPRV_PCR_YNENHEN);
192}
193
194/*
195 * preview_enable_invalaw - Enable/disable Inverse A-Law decompression
196 */
197static void preview_enable_invalaw(struct isp_prev_device *prev, bool enable)
198{
199 struct isp_device *isp = to_isp_device(prev);
200
201 if (enable)
202 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
203 ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
204 else
205 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
206 ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
207}
208
209/*
210 * preview_config_hmed - Configure the Horizontal Median Filter
211 */
212static void preview_config_hmed(struct isp_prev_device *prev,
213 const struct prev_params *params)
214{
215 struct isp_device *isp = to_isp_device(prev);
216 const struct omap3isp_prev_hmed *hmed = &params->hmed;
217
218 isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) |
219 (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) |
220 (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT),
221 OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
222}
223
224/*
225 * preview_enable_hmed - Enable/disable the Horizontal Median Filter
226 */
227static void preview_enable_hmed(struct isp_prev_device *prev, bool enable)
228{
229 struct isp_device *isp = to_isp_device(prev);
230
231 if (enable)
232 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
233 ISPPRV_PCR_HMEDEN);
234 else
235 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
236 ISPPRV_PCR_HMEDEN);
237}
238
239/*
240 * preview_config_cfa - Configure CFA Interpolation for Bayer formats
241 *
242 * The CFA table is organised in four blocks, one per Bayer component. The
243 * hardware expects blocks to follow the Bayer order of the input data, while
244 * the driver stores the table in GRBG order in memory. The blocks need to be
245 * reordered to support non-GRBG Bayer patterns.
246 */
247static void preview_config_cfa(struct isp_prev_device *prev,
248 const struct prev_params *params)
249{
250 static const unsigned int cfa_coef_order[4][4] = {
251 { 0, 1, 2, 3 }, /* GRBG */
252 { 1, 0, 3, 2 }, /* RGGB */
253 { 2, 3, 0, 1 }, /* BGGR */
254 { 3, 2, 1, 0 }, /* GBRG */
255 };
256 const unsigned int *order = cfa_coef_order[prev->params.cfa_order];
257 const struct omap3isp_prev_cfa *cfa = &params->cfa;
258 struct isp_device *isp = to_isp_device(prev);
259 unsigned int i;
260 unsigned int j;
261
262 isp_reg_writel(isp,
263 (cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
264 (cfa->gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
265 OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
266
267 isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR,
268 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
269
270 for (i = 0; i < 4; ++i) {
271 const __u32 *block = cfa->table[order[i]];
272
273 for (j = 0; j < OMAP3ISP_PREV_CFA_BLK_SIZE; ++j)
274 isp_reg_writel(isp, block[j], OMAP3_ISP_IOMEM_PREV,
275 ISPPRV_SET_TBL_DATA);
276 }
277}
278
279/*
280 * preview_config_chroma_suppression - Configure Chroma Suppression
281 */
282static void
283preview_config_chroma_suppression(struct isp_prev_device *prev,
284 const struct prev_params *params)
285{
286 struct isp_device *isp = to_isp_device(prev);
287 const struct omap3isp_prev_csup *cs = &params->csup;
288
289 isp_reg_writel(isp,
290 cs->gain | (cs->thres << ISPPRV_CSUP_THRES_SHIFT) |
291 (cs->hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
292 OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
293}
294
295/*
296 * preview_enable_chroma_suppression - Enable/disable Chrominance Suppression
297 */
298static void
299preview_enable_chroma_suppression(struct isp_prev_device *prev, bool enable)
300{
301 struct isp_device *isp = to_isp_device(prev);
302
303 if (enable)
304 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
305 ISPPRV_PCR_SUPEN);
306 else
307 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
308 ISPPRV_PCR_SUPEN);
309}
310
311/*
312 * preview_config_whitebalance - Configure White Balance parameters
313 *
314 * Coefficient matrix always with default values.
315 */
316static void
317preview_config_whitebalance(struct isp_prev_device *prev,
318 const struct prev_params *params)
319{
320 struct isp_device *isp = to_isp_device(prev);
321 const struct omap3isp_prev_wbal *wbal = &params->wbal;
322 u32 val;
323
324 isp_reg_writel(isp, wbal->dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
325
326 val = wbal->coef0 << ISPPRV_WBGAIN_COEF0_SHIFT;
327 val |= wbal->coef1 << ISPPRV_WBGAIN_COEF1_SHIFT;
328 val |= wbal->coef2 << ISPPRV_WBGAIN_COEF2_SHIFT;
329 val |= wbal->coef3 << ISPPRV_WBGAIN_COEF3_SHIFT;
330 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
331
332 isp_reg_writel(isp,
333 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT |
334 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT |
335 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT |
336 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT |
337 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT |
338 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT |
339 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT |
340 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT |
341 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT |
342 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT |
343 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT |
344 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT |
345 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT |
346 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT |
347 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT |
348 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT,
349 OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
350}
351
352/*
353 * preview_config_blkadj - Configure Black Adjustment
354 */
355static void
356preview_config_blkadj(struct isp_prev_device *prev,
357 const struct prev_params *params)
358{
359 struct isp_device *isp = to_isp_device(prev);
360 const struct omap3isp_prev_blkadj *blkadj = &params->blkadj;
361
362 isp_reg_writel(isp, (blkadj->blue << ISPPRV_BLKADJOFF_B_SHIFT) |
363 (blkadj->green << ISPPRV_BLKADJOFF_G_SHIFT) |
364 (blkadj->red << ISPPRV_BLKADJOFF_R_SHIFT),
365 OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
366}
367
368/*
369 * preview_config_rgb_blending - Configure RGB-RGB Blending
370 */
371static void
372preview_config_rgb_blending(struct isp_prev_device *prev,
373 const struct prev_params *params)
374{
375 struct isp_device *isp = to_isp_device(prev);
376 const struct omap3isp_prev_rgbtorgb *rgbrgb = &params->rgb2rgb;
377 u32 val;
378
379 val = (rgbrgb->matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
380 val |= (rgbrgb->matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
381 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1);
382
383 val = (rgbrgb->matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
384 val |= (rgbrgb->matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
385 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2);
386
387 val = (rgbrgb->matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
388 val |= (rgbrgb->matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
389 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3);
390
391 val = (rgbrgb->matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
392 val |= (rgbrgb->matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
393 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4);
394
395 val = (rgbrgb->matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
396 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5);
397
398 val = (rgbrgb->offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
399 val |= (rgbrgb->offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
400 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1);
401
402 val = (rgbrgb->offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
403 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2);
404}
405
406/*
407 * preview_config_csc - Configure Color Space Conversion (RGB to YCbYCr)
408 */
409static void
410preview_config_csc(struct isp_prev_device *prev,
411 const struct prev_params *params)
412{
413 struct isp_device *isp = to_isp_device(prev);
414 const struct omap3isp_prev_csc *csc = &params->csc;
415 u32 val;
416
417 val = (csc->matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
418 val |= (csc->matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
419 val |= (csc->matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
420 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
421
422 val = (csc->matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
423 val |= (csc->matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
424 val |= (csc->matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
425 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
426
427 val = (csc->matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
428 val |= (csc->matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
429 val |= (csc->matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
430 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
431
432 val = (csc->offset[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
433 val |= (csc->offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
434 val |= (csc->offset[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
435 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
436}
437
438/*
439 * preview_config_yc_range - Configure the max and min Y and C values
440 */
441static void
442preview_config_yc_range(struct isp_prev_device *prev,
443 const struct prev_params *params)
444{
445 struct isp_device *isp = to_isp_device(prev);
446 const struct omap3isp_prev_yclimit *yc = &params->yclimit;
447
448 isp_reg_writel(isp,
449 yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
450 yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
451 yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT |
452 yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT,
453 OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
454}
455
456/*
457 * preview_config_dcor - Configure Couplet Defect Correction
458 */
459static void
460preview_config_dcor(struct isp_prev_device *prev,
461 const struct prev_params *params)
462{
463 struct isp_device *isp = to_isp_device(prev);
464 const struct omap3isp_prev_dcor *dcor = &params->dcor;
465
466 isp_reg_writel(isp, dcor->detect_correct[0],
467 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
468 isp_reg_writel(isp, dcor->detect_correct[1],
469 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
470 isp_reg_writel(isp, dcor->detect_correct[2],
471 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
472 isp_reg_writel(isp, dcor->detect_correct[3],
473 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
474 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
475 ISPPRV_PCR_DCCOUP,
476 dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0);
477}
478
479/*
480 * preview_enable_dcor - Enable/disable Couplet Defect Correction
481 */
482static void preview_enable_dcor(struct isp_prev_device *prev, bool enable)
483{
484 struct isp_device *isp = to_isp_device(prev);
485
486 if (enable)
487 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
488 ISPPRV_PCR_DCOREN);
489 else
490 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
491 ISPPRV_PCR_DCOREN);
492}
493
494/*
495 * preview_enable_drkframe_capture - Enable/disable Dark Frame Capture
496 */
497static void
498preview_enable_drkframe_capture(struct isp_prev_device *prev, bool enable)
499{
500 struct isp_device *isp = to_isp_device(prev);
501
502 if (enable)
503 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
504 ISPPRV_PCR_DRKFCAP);
505 else
506 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
507 ISPPRV_PCR_DRKFCAP);
508}
509
510/*
511 * preview_enable_drkframe - Enable/disable Dark Frame Subtraction
512 */
513static void preview_enable_drkframe(struct isp_prev_device *prev, bool enable)
514{
515 struct isp_device *isp = to_isp_device(prev);
516
517 if (enable)
518 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
519 ISPPRV_PCR_DRKFEN);
520 else
521 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
522 ISPPRV_PCR_DRKFEN);
523}
524
525/*
526 * preview_config_noisefilter - Configure the Noise Filter
527 */
528static void
529preview_config_noisefilter(struct isp_prev_device *prev,
530 const struct prev_params *params)
531{
532 struct isp_device *isp = to_isp_device(prev);
533 const struct omap3isp_prev_nf *nf = &params->nf;
534 unsigned int i;
535
536 isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
537 isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR,
538 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
539 for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) {
540 isp_reg_writel(isp, nf->table[i],
541 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
542 }
543}
544
545/*
546 * preview_enable_noisefilter - Enable/disable the Noise Filter
547 */
548static void
549preview_enable_noisefilter(struct isp_prev_device *prev, bool enable)
550{
551 struct isp_device *isp = to_isp_device(prev);
552
553 if (enable)
554 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
555 ISPPRV_PCR_NFEN);
556 else
557 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
558 ISPPRV_PCR_NFEN);
559}
560
561/*
562 * preview_config_gammacorrn - Configure the Gamma Correction tables
563 */
564static void
565preview_config_gammacorrn(struct isp_prev_device *prev,
566 const struct prev_params *params)
567{
568 struct isp_device *isp = to_isp_device(prev);
569 const struct omap3isp_prev_gtables *gt = &params->gamma;
570 unsigned int i;
571
572 isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR,
573 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
574 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
575 isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV,
576 ISPPRV_SET_TBL_DATA);
577
578 isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR,
579 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
580 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
581 isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV,
582 ISPPRV_SET_TBL_DATA);
583
584 isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR,
585 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
586 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
587 isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV,
588 ISPPRV_SET_TBL_DATA);
589}
590
591/*
592 * preview_enable_gammacorrn - Enable/disable Gamma Correction
593 *
594 * When gamma correction is disabled, the module is bypassed and its output is
595 * the 8 MSB of the 10-bit input .
596 */
597static void
598preview_enable_gammacorrn(struct isp_prev_device *prev, bool enable)
599{
600 struct isp_device *isp = to_isp_device(prev);
601
602 if (enable)
603 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
604 ISPPRV_PCR_GAMMA_BYPASS);
605 else
606 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
607 ISPPRV_PCR_GAMMA_BYPASS);
608}
609
610/*
611 * preview_config_contrast - Configure the Contrast
612 *
613 * Value should be programmed before enabling the module.
614 */
615static void
616preview_config_contrast(struct isp_prev_device *prev,
617 const struct prev_params *params)
618{
619 struct isp_device *isp = to_isp_device(prev);
620
621 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
622 0xff << ISPPRV_CNT_BRT_CNT_SHIFT,
623 params->contrast << ISPPRV_CNT_BRT_CNT_SHIFT);
624}
625
626/*
627 * preview_config_brightness - Configure the Brightness
628 */
629static void
630preview_config_brightness(struct isp_prev_device *prev,
631 const struct prev_params *params)
632{
633 struct isp_device *isp = to_isp_device(prev);
634
635 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
636 0xff << ISPPRV_CNT_BRT_BRT_SHIFT,
637 params->brightness << ISPPRV_CNT_BRT_BRT_SHIFT);
638}
639
640/*
641 * preview_update_contrast - Updates the contrast.
642 * @contrast: Pointer to hold the current programmed contrast value.
643 *
644 * Value should be programmed before enabling the module.
645 */
646static void
647preview_update_contrast(struct isp_prev_device *prev, u8 contrast)
648{
649 struct prev_params *params;
650 unsigned long flags;
651
652 spin_lock_irqsave(&prev->params.lock, flags);
653 params = (prev->params.active & OMAP3ISP_PREV_CONTRAST)
654 ? &prev->params.params[0] : &prev->params.params[1];
655
656 if (params->contrast != (contrast * ISPPRV_CONTRAST_UNITS)) {
657 params->contrast = contrast * ISPPRV_CONTRAST_UNITS;
658 params->update |= OMAP3ISP_PREV_CONTRAST;
659 }
660 spin_unlock_irqrestore(&prev->params.lock, flags);
661}
662
663/*
664 * preview_update_brightness - Updates the brightness in preview module.
665 * @brightness: Pointer to hold the current programmed brightness value.
666 *
667 */
668static void
669preview_update_brightness(struct isp_prev_device *prev, u8 brightness)
670{
671 struct prev_params *params;
672 unsigned long flags;
673
674 spin_lock_irqsave(&prev->params.lock, flags);
675 params = (prev->params.active & OMAP3ISP_PREV_BRIGHTNESS)
676 ? &prev->params.params[0] : &prev->params.params[1];
677
678 if (params->brightness != (brightness * ISPPRV_BRIGHT_UNITS)) {
679 params->brightness = brightness * ISPPRV_BRIGHT_UNITS;
680 params->update |= OMAP3ISP_PREV_BRIGHTNESS;
681 }
682 spin_unlock_irqrestore(&prev->params.lock, flags);
683}
684
685static u32
686preview_params_lock(struct isp_prev_device *prev, u32 update, bool shadow)
687{
688 u32 active = prev->params.active;
689
690 if (shadow) {
691 /* Mark all shadow parameters we are going to touch as busy. */
692 prev->params.params[0].busy |= ~active & update;
693 prev->params.params[1].busy |= active & update;
694 } else {
695 /* Mark all active parameters we are going to touch as busy. */
696 update = (prev->params.params[0].update & active)
697 | (prev->params.params[1].update & ~active);
698
699 prev->params.params[0].busy |= active & update;
700 prev->params.params[1].busy |= ~active & update;
701 }
702
703 return update;
704}
705
706static void
707preview_params_unlock(struct isp_prev_device *prev, u32 update, bool shadow)
708{
709 u32 active = prev->params.active;
710
711 if (shadow) {
712 /* Set the update flag for shadow parameters that have been
713 * updated and clear the busy flag for all shadow parameters.
714 */
715 prev->params.params[0].update |= (~active & update);
716 prev->params.params[1].update |= (active & update);
717 prev->params.params[0].busy &= active;
718 prev->params.params[1].busy &= ~active;
719 } else {
720 /* Clear the update flag for active parameters that have been
721 * applied and the busy flag for all active parameters.
722 */
723 prev->params.params[0].update &= ~(active & update);
724 prev->params.params[1].update &= ~(~active & update);
725 prev->params.params[0].busy &= ~active;
726 prev->params.params[1].busy &= active;
727 }
728}
729
730static void preview_params_switch(struct isp_prev_device *prev)
731{
732 u32 to_switch;
733
734 /* Switch active parameters with updated shadow parameters when the
735 * shadow parameter has been updated and neither the active not the
736 * shadow parameter is busy.
737 */
738 to_switch = (prev->params.params[0].update & ~prev->params.active)
739 | (prev->params.params[1].update & prev->params.active);
740 to_switch &= ~(prev->params.params[0].busy |
741 prev->params.params[1].busy);
742 if (to_switch == 0)
743 return;
744
745 prev->params.active ^= to_switch;
746
747 /* Remove the update flag for the shadow copy of parameters we have
748 * switched.
749 */
750 prev->params.params[0].update &= ~(~prev->params.active & to_switch);
751 prev->params.params[1].update &= ~(prev->params.active & to_switch);
752}
753
754/* preview parameters update structure */
755struct preview_update {
756 void (*config)(struct isp_prev_device *, const struct prev_params *);
757 void (*enable)(struct isp_prev_device *, bool);
758 unsigned int param_offset;
759 unsigned int param_size;
760 unsigned int config_offset;
761 bool skip;
762};
763
764/* Keep the array indexed by the OMAP3ISP_PREV_* bit number. */
765static const struct preview_update update_attrs[] = {
766 /* OMAP3ISP_PREV_LUMAENH */ {
767 preview_config_luma_enhancement,
768 preview_enable_luma_enhancement,
769 offsetof(struct prev_params, luma),
770 FIELD_SIZEOF(struct prev_params, luma),
771 offsetof(struct omap3isp_prev_update_config, luma),
772 }, /* OMAP3ISP_PREV_INVALAW */ {
773 NULL,
774 preview_enable_invalaw,
775 }, /* OMAP3ISP_PREV_HRZ_MED */ {
776 preview_config_hmed,
777 preview_enable_hmed,
778 offsetof(struct prev_params, hmed),
779 FIELD_SIZEOF(struct prev_params, hmed),
780 offsetof(struct omap3isp_prev_update_config, hmed),
781 }, /* OMAP3ISP_PREV_CFA */ {
782 preview_config_cfa,
783 NULL,
784 offsetof(struct prev_params, cfa),
785 FIELD_SIZEOF(struct prev_params, cfa),
786 offsetof(struct omap3isp_prev_update_config, cfa),
787 }, /* OMAP3ISP_PREV_CHROMA_SUPP */ {
788 preview_config_chroma_suppression,
789 preview_enable_chroma_suppression,
790 offsetof(struct prev_params, csup),
791 FIELD_SIZEOF(struct prev_params, csup),
792 offsetof(struct omap3isp_prev_update_config, csup),
793 }, /* OMAP3ISP_PREV_WB */ {
794 preview_config_whitebalance,
795 NULL,
796 offsetof(struct prev_params, wbal),
797 FIELD_SIZEOF(struct prev_params, wbal),
798 offsetof(struct omap3isp_prev_update_config, wbal),
799 }, /* OMAP3ISP_PREV_BLKADJ */ {
800 preview_config_blkadj,
801 NULL,
802 offsetof(struct prev_params, blkadj),
803 FIELD_SIZEOF(struct prev_params, blkadj),
804 offsetof(struct omap3isp_prev_update_config, blkadj),
805 }, /* OMAP3ISP_PREV_RGB2RGB */ {
806 preview_config_rgb_blending,
807 NULL,
808 offsetof(struct prev_params, rgb2rgb),
809 FIELD_SIZEOF(struct prev_params, rgb2rgb),
810 offsetof(struct omap3isp_prev_update_config, rgb2rgb),
811 }, /* OMAP3ISP_PREV_COLOR_CONV */ {
812 preview_config_csc,
813 NULL,
814 offsetof(struct prev_params, csc),
815 FIELD_SIZEOF(struct prev_params, csc),
816 offsetof(struct omap3isp_prev_update_config, csc),
817 }, /* OMAP3ISP_PREV_YC_LIMIT */ {
818 preview_config_yc_range,
819 NULL,
820 offsetof(struct prev_params, yclimit),
821 FIELD_SIZEOF(struct prev_params, yclimit),
822 offsetof(struct omap3isp_prev_update_config, yclimit),
823 }, /* OMAP3ISP_PREV_DEFECT_COR */ {
824 preview_config_dcor,
825 preview_enable_dcor,
826 offsetof(struct prev_params, dcor),
827 FIELD_SIZEOF(struct prev_params, dcor),
828 offsetof(struct omap3isp_prev_update_config, dcor),
829 }, /* Previously OMAP3ISP_PREV_GAMMABYPASS, not used anymore */ {
830 NULL,
831 NULL,
832 }, /* OMAP3ISP_PREV_DRK_FRM_CAPTURE */ {
833 NULL,
834 preview_enable_drkframe_capture,
835 }, /* OMAP3ISP_PREV_DRK_FRM_SUBTRACT */ {
836 NULL,
837 preview_enable_drkframe,
838 }, /* OMAP3ISP_PREV_LENS_SHADING */ {
839 NULL,
840 preview_enable_drkframe,
841 }, /* OMAP3ISP_PREV_NF */ {
842 preview_config_noisefilter,
843 preview_enable_noisefilter,
844 offsetof(struct prev_params, nf),
845 FIELD_SIZEOF(struct prev_params, nf),
846 offsetof(struct omap3isp_prev_update_config, nf),
847 }, /* OMAP3ISP_PREV_GAMMA */ {
848 preview_config_gammacorrn,
849 preview_enable_gammacorrn,
850 offsetof(struct prev_params, gamma),
851 FIELD_SIZEOF(struct prev_params, gamma),
852 offsetof(struct omap3isp_prev_update_config, gamma),
853 }, /* OMAP3ISP_PREV_CONTRAST */ {
854 preview_config_contrast,
855 NULL,
856 0, 0, 0, true,
857 }, /* OMAP3ISP_PREV_BRIGHTNESS */ {
858 preview_config_brightness,
859 NULL,
860 0, 0, 0, true,
861 },
862};
863
864/*
865 * preview_config - Copy and update local structure with userspace preview
866 * configuration.
867 * @prev: ISP preview engine
868 * @cfg: Configuration
869 *
870 * Return zero if success or -EFAULT if the configuration can't be copied from
871 * userspace.
872 */
873static int preview_config(struct isp_prev_device *prev,
874 struct omap3isp_prev_update_config *cfg)
875{
876 unsigned long flags;
877 unsigned int i;
878 int rval = 0;
879 u32 update;
880 u32 active;
881
882 if (cfg->update == 0)
883 return 0;
884
885 /* Mark the shadow parameters we're going to update as busy. */
886 spin_lock_irqsave(&prev->params.lock, flags);
887 preview_params_lock(prev, cfg->update, true);
888 active = prev->params.active;
889 spin_unlock_irqrestore(&prev->params.lock, flags);
890
891 update = 0;
892
893 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
894 const struct preview_update *attr = &update_attrs[i];
895 struct prev_params *params;
896 unsigned int bit = 1 << i;
897
898 if (attr->skip || !(cfg->update & bit))
899 continue;
900
901 params = &prev->params.params[!!(active & bit)];
902
903 if (cfg->flag & bit) {
904 void __user *from = *(void * __user *)
905 ((void *)cfg + attr->config_offset);
906 void *to = (void *)params + attr->param_offset;
907 size_t size = attr->param_size;
908
909 if (to && from && size) {
910 if (copy_from_user(to, from, size)) {
911 rval = -EFAULT;
912 break;
913 }
914 }
915 params->features |= bit;
916 } else {
917 params->features &= ~bit;
918 }
919
920 update |= bit;
921 }
922
923 spin_lock_irqsave(&prev->params.lock, flags);
924 preview_params_unlock(prev, update, true);
925 preview_params_switch(prev);
926 spin_unlock_irqrestore(&prev->params.lock, flags);
927
928 return rval;
929}
930
931/*
932 * preview_setup_hw - Setup preview registers and/or internal memory
933 * @prev: pointer to preview private structure
934 * @update: Bitmask of parameters to setup
935 * @active: Bitmask of parameters active in set 0
936 * Note: can be called from interrupt context
937 * Return none
938 */
939static void preview_setup_hw(struct isp_prev_device *prev, u32 update,
940 u32 active)
941{
942 unsigned int i;
943 u32 features;
944
945 if (update == 0)
946 return;
947
948 features = (prev->params.params[0].features & active)
949 | (prev->params.params[1].features & ~active);
950
951 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
952 const struct preview_update *attr = &update_attrs[i];
953 struct prev_params *params;
954 unsigned int bit = 1 << i;
955
956 if (!(update & bit))
957 continue;
958
959 params = &prev->params.params[!(active & bit)];
960
961 if (params->features & bit) {
962 if (attr->config)
963 attr->config(prev, params);
964 if (attr->enable)
965 attr->enable(prev, true);
966 } else {
967 if (attr->enable)
968 attr->enable(prev, false);
969 }
970 }
971}
972
973/*
974 * preview_config_ycpos - Configure byte layout of YUV image.
975 * @mode: Indicates the required byte layout.
976 */
977static void
978preview_config_ycpos(struct isp_prev_device *prev,
979 enum v4l2_mbus_pixelcode pixelcode)
980{
981 struct isp_device *isp = to_isp_device(prev);
982 enum preview_ycpos_mode mode;
983
984 switch (pixelcode) {
985 case V4L2_MBUS_FMT_YUYV8_1X16:
986 mode = YCPOS_CrYCbY;
987 break;
988 case V4L2_MBUS_FMT_UYVY8_1X16:
989 mode = YCPOS_YCrYCb;
990 break;
991 default:
992 return;
993 }
994
995 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
996 ISPPRV_PCR_YCPOS_CrYCbY,
997 mode << ISPPRV_PCR_YCPOS_SHIFT);
998}
999
1000/*
1001 * preview_config_averager - Enable / disable / configure averager
1002 * @average: Average value to be configured.
1003 */
1004static void preview_config_averager(struct isp_prev_device *prev, u8 average)
1005{
1006 struct isp_device *isp = to_isp_device(prev);
1007
1008 isp_reg_writel(isp, ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
1009 ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
1010 average, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
1011}
1012
1013
1014/*
1015 * preview_config_input_format - Configure the input format
1016 * @prev: The preview engine
1017 * @format: Format on the preview engine sink pad
1018 *
1019 * Enable and configure CFA interpolation for Bayer formats and disable it for
1020 * greyscale formats.
1021 *
1022 * The CFA table is organised in four blocks, one per Bayer component. The
1023 * hardware expects blocks to follow the Bayer order of the input data, while
1024 * the driver stores the table in GRBG order in memory. The blocks need to be
1025 * reordered to support non-GRBG Bayer patterns.
1026 */
1027static void preview_config_input_format(struct isp_prev_device *prev,
1028 const struct v4l2_mbus_framefmt *format)
1029{
1030 struct isp_device *isp = to_isp_device(prev);
1031 struct prev_params *params;
1032
1033 switch (format->code) {
1034 case V4L2_MBUS_FMT_SGRBG10_1X10:
1035 prev->params.cfa_order = 0;
1036 break;
1037 case V4L2_MBUS_FMT_SRGGB10_1X10:
1038 prev->params.cfa_order = 1;
1039 break;
1040 case V4L2_MBUS_FMT_SBGGR10_1X10:
1041 prev->params.cfa_order = 2;
1042 break;
1043 case V4L2_MBUS_FMT_SGBRG10_1X10:
1044 prev->params.cfa_order = 3;
1045 break;
1046 default:
1047 /* Disable CFA for non-Bayer formats. */
1048 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1049 ISPPRV_PCR_CFAEN);
1050 return;
1051 }
1052
1053 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN);
1054 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1055 ISPPRV_PCR_CFAFMT_MASK, ISPPRV_PCR_CFAFMT_BAYER);
1056
1057 params = (prev->params.active & OMAP3ISP_PREV_CFA)
1058 ? &prev->params.params[0] : &prev->params.params[1];
1059
1060 preview_config_cfa(prev, params);
1061}
1062
1063/*
1064 * preview_config_input_size - Configure the input frame size
1065 *
1066 * The preview engine crops several rows and columns internally depending on
1067 * which processing blocks are enabled. The driver assumes all those blocks are
1068 * enabled when reporting source pad formats to userspace. If this assumption is
1069 * not true, rows and columns must be manually cropped at the preview engine
1070 * input to avoid overflows at the end of lines and frames.
1071 *
1072 * See the explanation at the PREV_MARGIN_* definitions for more details.
1073 */
1074static void preview_config_input_size(struct isp_prev_device *prev, u32 active)
1075{
1076 const struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK];
1077 struct isp_device *isp = to_isp_device(prev);
1078 unsigned int sph = prev->crop.left;
1079 unsigned int eph = prev->crop.left + prev->crop.width - 1;
1080 unsigned int slv = prev->crop.top;
1081 unsigned int elv = prev->crop.top + prev->crop.height - 1;
1082 u32 features;
1083
1084 if (format->code != V4L2_MBUS_FMT_Y10_1X10) {
1085 sph -= 2;
1086 eph += 2;
1087 slv -= 2;
1088 elv += 2;
1089 }
1090
1091 features = (prev->params.params[0].features & active)
1092 | (prev->params.params[1].features & ~active);
1093
1094 if (features & (OMAP3ISP_PREV_DEFECT_COR | OMAP3ISP_PREV_NF)) {
1095 sph -= 2;
1096 eph += 2;
1097 slv -= 2;
1098 elv += 2;
1099 }
1100 if (features & OMAP3ISP_PREV_HRZ_MED) {
1101 sph -= 2;
1102 eph += 2;
1103 }
1104 if (features & (OMAP3ISP_PREV_CHROMA_SUPP | OMAP3ISP_PREV_LUMAENH))
1105 sph -= 2;
1106
1107 isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
1108 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
1109 isp_reg_writel(isp, (slv << ISPPRV_VERT_INFO_SLV_SHIFT) | elv,
1110 OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
1111}
1112
1113/*
1114 * preview_config_inlineoffset - Configures the Read address line offset.
1115 * @prev: Preview module
1116 * @offset: Line offset
1117 *
1118 * According to the TRM, the line offset must be aligned on a 32 bytes boundary.
1119 * However, a hardware bug requires the memory start address to be aligned on a
1120 * 64 bytes boundary, so the offset probably should be aligned on 64 bytes as
1121 * well.
1122 */
1123static void
1124preview_config_inlineoffset(struct isp_prev_device *prev, u32 offset)
1125{
1126 struct isp_device *isp = to_isp_device(prev);
1127
1128 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1129 ISPPRV_RADR_OFFSET);
1130}
1131
1132/*
1133 * preview_set_inaddr - Sets memory address of input frame.
1134 * @addr: 32bit memory address aligned on 32byte boundary.
1135 *
1136 * Configures the memory address from which the input frame is to be read.
1137 */
1138static void preview_set_inaddr(struct isp_prev_device *prev, u32 addr)
1139{
1140 struct isp_device *isp = to_isp_device(prev);
1141
1142 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
1143}
1144
1145/*
1146 * preview_config_outlineoffset - Configures the Write address line offset.
1147 * @offset: Line Offset for the preview output.
1148 *
1149 * The offset must be a multiple of 32 bytes.
1150 */
1151static void preview_config_outlineoffset(struct isp_prev_device *prev,
1152 u32 offset)
1153{
1154 struct isp_device *isp = to_isp_device(prev);
1155
1156 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1157 ISPPRV_WADD_OFFSET);
1158}
1159
1160/*
1161 * preview_set_outaddr - Sets the memory address to store output frame
1162 * @addr: 32bit memory address aligned on 32byte boundary.
1163 *
1164 * Configures the memory address to which the output frame is written.
1165 */
1166static void preview_set_outaddr(struct isp_prev_device *prev, u32 addr)
1167{
1168 struct isp_device *isp = to_isp_device(prev);
1169
1170 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR);
1171}
1172
1173static void preview_adjust_bandwidth(struct isp_prev_device *prev)
1174{
1175 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
1176 struct isp_device *isp = to_isp_device(prev);
1177 const struct v4l2_mbus_framefmt *ifmt = &prev->formats[PREV_PAD_SINK];
1178 unsigned long l3_ick = pipe->l3_ick;
1179 struct v4l2_fract *timeperframe;
1180 unsigned int cycles_per_frame;
1181 unsigned int requests_per_frame;
1182 unsigned int cycles_per_request;
1183 unsigned int minimum;
1184 unsigned int maximum;
1185 unsigned int value;
1186
1187 if (prev->input != PREVIEW_INPUT_MEMORY) {
1188 isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
1189 ISPSBL_SDR_REQ_PRV_EXP_MASK);
1190 return;
1191 }
1192
1193 /* Compute the minimum number of cycles per request, based on the
1194 * pipeline maximum data rate. This is an absolute lower bound if we
1195 * don't want SBL overflows, so round the value up.
1196 */
1197 cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1,
1198 pipe->max_rate);
1199 minimum = DIV_ROUND_UP(cycles_per_request, 32);
1200
1201 /* Compute the maximum number of cycles per request, based on the
1202 * requested frame rate. This is a soft upper bound to achieve a frame
1203 * rate equal or higher than the requested value, so round the value
1204 * down.
1205 */
1206 timeperframe = &pipe->max_timeperframe;
1207
1208 requests_per_frame = DIV_ROUND_UP(ifmt->width * 2, 256) * ifmt->height;
1209 cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator,
1210 timeperframe->denominator);
1211 cycles_per_request = cycles_per_frame / requests_per_frame;
1212
1213 maximum = cycles_per_request / 32;
1214
1215 value = max(minimum, maximum);
1216
1217 dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value);
1218 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
1219 ISPSBL_SDR_REQ_PRV_EXP_MASK,
1220 value << ISPSBL_SDR_REQ_PRV_EXP_SHIFT);
1221}
1222
1223/*
1224 * omap3isp_preview_busy - Gets busy state of preview module.
1225 */
1226int omap3isp_preview_busy(struct isp_prev_device *prev)
1227{
1228 struct isp_device *isp = to_isp_device(prev);
1229
1230 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR)
1231 & ISPPRV_PCR_BUSY;
1232}
1233
1234/*
1235 * omap3isp_preview_restore_context - Restores the values of preview registers
1236 */
1237void omap3isp_preview_restore_context(struct isp_device *isp)
1238{
1239 struct isp_prev_device *prev = &isp->isp_prev;
1240 const u32 update = OMAP3ISP_PREV_FEATURES_END - 1;
1241
1242 prev->params.params[0].update = prev->params.active & update;
1243 prev->params.params[1].update = ~prev->params.active & update;
1244
1245 preview_setup_hw(prev, update, prev->params.active);
1246
1247 prev->params.params[0].update = 0;
1248 prev->params.params[1].update = 0;
1249}
1250
1251/*
1252 * preview_print_status - Dump preview module registers to the kernel log
1253 */
1254#define PREV_PRINT_REGISTER(isp, name)\
1255 dev_dbg(isp->dev, "###PRV " #name "=0x%08x\n", \
1256 isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_##name))
1257
1258static void preview_print_status(struct isp_prev_device *prev)
1259{
1260 struct isp_device *isp = to_isp_device(prev);
1261
1262 dev_dbg(isp->dev, "-------------Preview Register dump----------\n");
1263
1264 PREV_PRINT_REGISTER(isp, PCR);
1265 PREV_PRINT_REGISTER(isp, HORZ_INFO);
1266 PREV_PRINT_REGISTER(isp, VERT_INFO);
1267 PREV_PRINT_REGISTER(isp, RSDR_ADDR);
1268 PREV_PRINT_REGISTER(isp, RADR_OFFSET);
1269 PREV_PRINT_REGISTER(isp, DSDR_ADDR);
1270 PREV_PRINT_REGISTER(isp, DRKF_OFFSET);
1271 PREV_PRINT_REGISTER(isp, WSDR_ADDR);
1272 PREV_PRINT_REGISTER(isp, WADD_OFFSET);
1273 PREV_PRINT_REGISTER(isp, AVE);
1274 PREV_PRINT_REGISTER(isp, HMED);
1275 PREV_PRINT_REGISTER(isp, NF);
1276 PREV_PRINT_REGISTER(isp, WB_DGAIN);
1277 PREV_PRINT_REGISTER(isp, WBGAIN);
1278 PREV_PRINT_REGISTER(isp, WBSEL);
1279 PREV_PRINT_REGISTER(isp, CFA);
1280 PREV_PRINT_REGISTER(isp, BLKADJOFF);
1281 PREV_PRINT_REGISTER(isp, RGB_MAT1);
1282 PREV_PRINT_REGISTER(isp, RGB_MAT2);
1283 PREV_PRINT_REGISTER(isp, RGB_MAT3);
1284 PREV_PRINT_REGISTER(isp, RGB_MAT4);
1285 PREV_PRINT_REGISTER(isp, RGB_MAT5);
1286 PREV_PRINT_REGISTER(isp, RGB_OFF1);
1287 PREV_PRINT_REGISTER(isp, RGB_OFF2);
1288 PREV_PRINT_REGISTER(isp, CSC0);
1289 PREV_PRINT_REGISTER(isp, CSC1);
1290 PREV_PRINT_REGISTER(isp, CSC2);
1291 PREV_PRINT_REGISTER(isp, CSC_OFFSET);
1292 PREV_PRINT_REGISTER(isp, CNT_BRT);
1293 PREV_PRINT_REGISTER(isp, CSUP);
1294 PREV_PRINT_REGISTER(isp, SETUP_YC);
1295 PREV_PRINT_REGISTER(isp, SET_TBL_ADDR);
1296 PREV_PRINT_REGISTER(isp, CDC_THR0);
1297 PREV_PRINT_REGISTER(isp, CDC_THR1);
1298 PREV_PRINT_REGISTER(isp, CDC_THR2);
1299 PREV_PRINT_REGISTER(isp, CDC_THR3);
1300
1301 dev_dbg(isp->dev, "--------------------------------------------\n");
1302}
1303
1304/*
1305 * preview_init_params - init image processing parameters.
1306 * @prev: pointer to previewer private structure
1307 */
1308static void preview_init_params(struct isp_prev_device *prev)
1309{
1310 struct prev_params *params;
1311 unsigned int i;
1312
1313 spin_lock_init(&prev->params.lock);
1314
1315 prev->params.active = ~0;
1316 prev->params.params[0].busy = 0;
1317 prev->params.params[0].update = OMAP3ISP_PREV_FEATURES_END - 1;
1318 prev->params.params[1].busy = 0;
1319 prev->params.params[1].update = 0;
1320
1321 params = &prev->params.params[0];
1322
1323 /* Init values */
1324 params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS;
1325 params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS;
1326 params->cfa.format = OMAP3ISP_CFAFMT_BAYER;
1327 memcpy(params->cfa.table, cfa_coef_table,
1328 sizeof(params->cfa.table));
1329 params->cfa.gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
1330 params->cfa.gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
1331 params->csup.gain = FLR_CSUP_GAIN;
1332 params->csup.thres = FLR_CSUP_THRES;
1333 params->csup.hypf_en = 0;
1334 memcpy(params->luma.table, luma_enhance_table,
1335 sizeof(params->luma.table));
1336 params->nf.spread = FLR_NF_STRGTH;
1337 memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
1338 params->dcor.couplet_mode_en = 1;
1339 for (i = 0; i < OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS; i++)
1340 params->dcor.detect_correct[i] = DEF_DETECT_CORRECT_VAL;
1341 memcpy(params->gamma.blue, gamma_table, sizeof(params->gamma.blue));
1342 memcpy(params->gamma.green, gamma_table, sizeof(params->gamma.green));
1343 memcpy(params->gamma.red, gamma_table, sizeof(params->gamma.red));
1344 params->wbal.dgain = FLR_WBAL_DGAIN;
1345 params->wbal.coef0 = FLR_WBAL_COEF;
1346 params->wbal.coef1 = FLR_WBAL_COEF;
1347 params->wbal.coef2 = FLR_WBAL_COEF;
1348 params->wbal.coef3 = FLR_WBAL_COEF;
1349 params->blkadj.red = FLR_BLKADJ_RED;
1350 params->blkadj.green = FLR_BLKADJ_GREEN;
1351 params->blkadj.blue = FLR_BLKADJ_BLUE;
1352 params->rgb2rgb = flr_rgb2rgb;
1353 params->csc = flr_prev_csc;
1354 params->yclimit.minC = ISPPRV_YC_MIN;
1355 params->yclimit.maxC = ISPPRV_YC_MAX;
1356 params->yclimit.minY = ISPPRV_YC_MIN;
1357 params->yclimit.maxY = ISPPRV_YC_MAX;
1358
1359 params->features = OMAP3ISP_PREV_CFA | OMAP3ISP_PREV_DEFECT_COR
1360 | OMAP3ISP_PREV_NF | OMAP3ISP_PREV_GAMMA
1361 | OMAP3ISP_PREV_BLKADJ | OMAP3ISP_PREV_YC_LIMIT
1362 | OMAP3ISP_PREV_RGB2RGB | OMAP3ISP_PREV_COLOR_CONV
1363 | OMAP3ISP_PREV_WB | OMAP3ISP_PREV_BRIGHTNESS
1364 | OMAP3ISP_PREV_CONTRAST;
1365}
1366
1367/*
1368 * preview_max_out_width - Handle previewer hardware ouput limitations
1369 * @isp_revision : ISP revision
1370 * returns maximum width output for current isp revision
1371 */
1372static unsigned int preview_max_out_width(struct isp_prev_device *prev)
1373{
1374 struct isp_device *isp = to_isp_device(prev);
1375
1376 switch (isp->revision) {
1377 case ISP_REVISION_1_0:
1378 return PREV_MAX_OUT_WIDTH_REV_1;
1379
1380 case ISP_REVISION_2_0:
1381 default:
1382 return PREV_MAX_OUT_WIDTH_REV_2;
1383
1384 case ISP_REVISION_15_0:
1385 return PREV_MAX_OUT_WIDTH_REV_15;
1386 }
1387}
1388
1389static void preview_configure(struct isp_prev_device *prev)
1390{
1391 struct isp_device *isp = to_isp_device(prev);
1392 struct v4l2_mbus_framefmt *format;
1393 unsigned long flags;
1394 u32 update;
1395 u32 active;
1396
1397 spin_lock_irqsave(&prev->params.lock, flags);
1398 /* Mark all active parameters we are going to touch as busy. */
1399 update = preview_params_lock(prev, 0, false);
1400 active = prev->params.active;
1401 spin_unlock_irqrestore(&prev->params.lock, flags);
1402
1403 /* PREV_PAD_SINK */
1404 format = &prev->formats[PREV_PAD_SINK];
1405
1406 preview_adjust_bandwidth(prev);
1407
1408 preview_config_input_format(prev, format);
1409 preview_config_input_size(prev, active);
1410
1411 if (prev->input == PREVIEW_INPUT_CCDC)
1412 preview_config_inlineoffset(prev, 0);
1413 else
1414 preview_config_inlineoffset(prev,
1415 ALIGN(format->width, 0x20) * 2);
1416
1417 preview_setup_hw(prev, update, active);
1418
1419 /* PREV_PAD_SOURCE */
1420 format = &prev->formats[PREV_PAD_SOURCE];
1421
1422 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1423 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1424 ISPPRV_PCR_SDRPORT);
1425 else
1426 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1427 ISPPRV_PCR_SDRPORT);
1428
1429 if (prev->output & PREVIEW_OUTPUT_RESIZER)
1430 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1431 ISPPRV_PCR_RSZPORT);
1432 else
1433 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1434 ISPPRV_PCR_RSZPORT);
1435
1436 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1437 preview_config_outlineoffset(prev,
1438 ALIGN(format->width, 0x10) * 2);
1439
1440 preview_config_averager(prev, 0);
1441 preview_config_ycpos(prev, format->code);
1442
1443 spin_lock_irqsave(&prev->params.lock, flags);
1444 preview_params_unlock(prev, update, false);
1445 spin_unlock_irqrestore(&prev->params.lock, flags);
1446}
1447
1448/* -----------------------------------------------------------------------------
1449 * Interrupt handling
1450 */
1451
1452static void preview_enable_oneshot(struct isp_prev_device *prev)
1453{
1454 struct isp_device *isp = to_isp_device(prev);
1455
1456 /* The PCR.SOURCE bit is automatically reset to 0 when the PCR.ENABLE
1457 * bit is set. As the preview engine is used in single-shot mode, we
1458 * need to set PCR.SOURCE before enabling the preview engine.
1459 */
1460 if (prev->input == PREVIEW_INPUT_MEMORY)
1461 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1462 ISPPRV_PCR_SOURCE);
1463
1464 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1465 ISPPRV_PCR_EN | ISPPRV_PCR_ONESHOT);
1466}
1467
1468void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev)
1469{
1470 /*
1471 * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun
1472 * condition, the module was paused and now we have a buffer queued
1473 * on the output again. Restart the pipeline if running in continuous
1474 * mode.
1475 */
1476 if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
1477 prev->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
1478 preview_enable_oneshot(prev);
1479 isp_video_dmaqueue_flags_clr(&prev->video_out);
1480 }
1481}
1482
1483static void preview_isr_buffer(struct isp_prev_device *prev)
1484{
1485 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
1486 struct isp_buffer *buffer;
1487 int restart = 0;
1488
1489 if (prev->input == PREVIEW_INPUT_MEMORY) {
1490 buffer = omap3isp_video_buffer_next(&prev->video_in);
1491 if (buffer != NULL)
1492 preview_set_inaddr(prev, buffer->isp_addr);
1493 pipe->state |= ISP_PIPELINE_IDLE_INPUT;
1494 }
1495
1496 if (prev->output & PREVIEW_OUTPUT_MEMORY) {
1497 buffer = omap3isp_video_buffer_next(&prev->video_out);
1498 if (buffer != NULL) {
1499 preview_set_outaddr(prev, buffer->isp_addr);
1500 restart = 1;
1501 }
1502 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
1503 }
1504
1505 switch (prev->state) {
1506 case ISP_PIPELINE_STREAM_SINGLESHOT:
1507 if (isp_pipeline_ready(pipe))
1508 omap3isp_pipeline_set_stream(pipe,
1509 ISP_PIPELINE_STREAM_SINGLESHOT);
1510 break;
1511
1512 case ISP_PIPELINE_STREAM_CONTINUOUS:
1513 /* If an underrun occurs, the video queue operation handler will
1514 * restart the preview engine. Otherwise restart it immediately.
1515 */
1516 if (restart)
1517 preview_enable_oneshot(prev);
1518 break;
1519
1520 case ISP_PIPELINE_STREAM_STOPPED:
1521 default:
1522 return;
1523 }
1524}
1525
1526/*
1527 * omap3isp_preview_isr - ISP preview engine interrupt handler
1528 *
1529 * Manage the preview engine video buffers and configure shadowed registers.
1530 */
1531void omap3isp_preview_isr(struct isp_prev_device *prev)
1532{
1533 unsigned long flags;
1534 u32 update;
1535 u32 active;
1536
1537 if (omap3isp_module_sync_is_stopping(&prev->wait, &prev->stopping))
1538 return;
1539
1540 spin_lock_irqsave(&prev->params.lock, flags);
1541 preview_params_switch(prev);
1542 update = preview_params_lock(prev, 0, false);
1543 active = prev->params.active;
1544 spin_unlock_irqrestore(&prev->params.lock, flags);
1545
1546 preview_setup_hw(prev, update, active);
1547 preview_config_input_size(prev, active);
1548
1549 if (prev->input == PREVIEW_INPUT_MEMORY ||
1550 prev->output & PREVIEW_OUTPUT_MEMORY)
1551 preview_isr_buffer(prev);
1552 else if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS)
1553 preview_enable_oneshot(prev);
1554
1555 spin_lock_irqsave(&prev->params.lock, flags);
1556 preview_params_unlock(prev, update, false);
1557 spin_unlock_irqrestore(&prev->params.lock, flags);
1558}
1559
1560/* -----------------------------------------------------------------------------
1561 * ISP video operations
1562 */
1563
1564static int preview_video_queue(struct isp_video *video,
1565 struct isp_buffer *buffer)
1566{
1567 struct isp_prev_device *prev = &video->isp->isp_prev;
1568
1569 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1570 preview_set_inaddr(prev, buffer->isp_addr);
1571
1572 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1573 preview_set_outaddr(prev, buffer->isp_addr);
1574
1575 return 0;
1576}
1577
1578static const struct isp_video_operations preview_video_ops = {
1579 .queue = preview_video_queue,
1580};
1581
1582/* -----------------------------------------------------------------------------
1583 * V4L2 subdev operations
1584 */
1585
1586/*
1587 * preview_s_ctrl - Handle set control subdev method
1588 * @ctrl: pointer to v4l2 control structure
1589 */
1590static int preview_s_ctrl(struct v4l2_ctrl *ctrl)
1591{
1592 struct isp_prev_device *prev =
1593 container_of(ctrl->handler, struct isp_prev_device, ctrls);
1594
1595 switch (ctrl->id) {
1596 case V4L2_CID_BRIGHTNESS:
1597 preview_update_brightness(prev, ctrl->val);
1598 break;
1599 case V4L2_CID_CONTRAST:
1600 preview_update_contrast(prev, ctrl->val);
1601 break;
1602 }
1603
1604 return 0;
1605}
1606
1607static const struct v4l2_ctrl_ops preview_ctrl_ops = {
1608 .s_ctrl = preview_s_ctrl,
1609};
1610
1611/*
1612 * preview_ioctl - Handle preview module private ioctl's
1613 * @prev: pointer to preview context structure
1614 * @cmd: configuration command
1615 * @arg: configuration argument
1616 * return -EINVAL or zero on success
1617 */
1618static long preview_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1619{
1620 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1621
1622 switch (cmd) {
1623 case VIDIOC_OMAP3ISP_PRV_CFG:
1624 return preview_config(prev, arg);
1625
1626 default:
1627 return -ENOIOCTLCMD;
1628 }
1629}
1630
1631/*
1632 * preview_set_stream - Enable/Disable streaming on preview subdev
1633 * @sd : pointer to v4l2 subdev structure
1634 * @enable: 1 == Enable, 0 == Disable
1635 * return -EINVAL or zero on success
1636 */
1637static int preview_set_stream(struct v4l2_subdev *sd, int enable)
1638{
1639 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1640 struct isp_video *video_out = &prev->video_out;
1641 struct isp_device *isp = to_isp_device(prev);
1642 struct device *dev = to_device(prev);
1643
1644 if (prev->state == ISP_PIPELINE_STREAM_STOPPED) {
1645 if (enable == ISP_PIPELINE_STREAM_STOPPED)
1646 return 0;
1647
1648 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1649 preview_configure(prev);
1650 atomic_set(&prev->stopping, 0);
1651 preview_print_status(prev);
1652 }
1653
1654 switch (enable) {
1655 case ISP_PIPELINE_STREAM_CONTINUOUS:
1656 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1657 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1658
1659 if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED ||
1660 !(prev->output & PREVIEW_OUTPUT_MEMORY))
1661 preview_enable_oneshot(prev);
1662
1663 isp_video_dmaqueue_flags_clr(video_out);
1664 break;
1665
1666 case ISP_PIPELINE_STREAM_SINGLESHOT:
1667 if (prev->input == PREVIEW_INPUT_MEMORY)
1668 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
1669 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1670 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1671
1672 preview_enable_oneshot(prev);
1673 break;
1674
1675 case ISP_PIPELINE_STREAM_STOPPED:
1676 if (omap3isp_module_sync_idle(&sd->entity, &prev->wait,
1677 &prev->stopping))
1678 dev_dbg(dev, "%s: stop timeout.\n", sd->name);
1679 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
1680 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1681 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1682 isp_video_dmaqueue_flags_clr(video_out);
1683 break;
1684 }
1685
1686 prev->state = enable;
1687 return 0;
1688}
1689
1690static struct v4l2_mbus_framefmt *
1691__preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
1692 unsigned int pad, enum v4l2_subdev_format_whence which)
1693{
1694 if (which == V4L2_SUBDEV_FORMAT_TRY)
1695 return v4l2_subdev_get_try_format(fh, pad);
1696 else
1697 return &prev->formats[pad];
1698}
1699
1700static struct v4l2_rect *
1701__preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
1702 enum v4l2_subdev_format_whence which)
1703{
1704 if (which == V4L2_SUBDEV_FORMAT_TRY)
1705 return v4l2_subdev_get_try_crop(fh, PREV_PAD_SINK);
1706 else
1707 return &prev->crop;
1708}
1709
1710/* previewer format descriptions */
1711static const unsigned int preview_input_fmts[] = {
1712 V4L2_MBUS_FMT_Y10_1X10,
1713 V4L2_MBUS_FMT_SGRBG10_1X10,
1714 V4L2_MBUS_FMT_SRGGB10_1X10,
1715 V4L2_MBUS_FMT_SBGGR10_1X10,
1716 V4L2_MBUS_FMT_SGBRG10_1X10,
1717};
1718
1719static const unsigned int preview_output_fmts[] = {
1720 V4L2_MBUS_FMT_UYVY8_1X16,
1721 V4L2_MBUS_FMT_YUYV8_1X16,
1722};
1723
1724/*
1725 * preview_try_format - Validate a format
1726 * @prev: ISP preview engine
1727 * @fh: V4L2 subdev file handle
1728 * @pad: pad number
1729 * @fmt: format to be validated
1730 * @which: try/active format selector
1731 *
1732 * Validate and adjust the given format for the given pad based on the preview
1733 * engine limits and the format and crop rectangles on other pads.
1734 */
1735static void preview_try_format(struct isp_prev_device *prev,
1736 struct v4l2_subdev_fh *fh, unsigned int pad,
1737 struct v4l2_mbus_framefmt *fmt,
1738 enum v4l2_subdev_format_whence which)
1739{
1740 enum v4l2_mbus_pixelcode pixelcode;
1741 struct v4l2_rect *crop;
1742 unsigned int i;
1743
1744 switch (pad) {
1745 case PREV_PAD_SINK:
1746 /* When reading data from the CCDC, the input size has already
1747 * been mangled by the CCDC output pad so it can be accepted
1748 * as-is.
1749 *
1750 * When reading data from memory, clamp the requested width and
1751 * height. The TRM doesn't specify a minimum input height, make
1752 * sure we got enough lines to enable the noise filter and color
1753 * filter array interpolation.
1754 */
1755 if (prev->input == PREVIEW_INPUT_MEMORY) {
1756 fmt->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH,
1757 preview_max_out_width(prev));
1758 fmt->height = clamp_t(u32, fmt->height,
1759 PREV_MIN_IN_HEIGHT,
1760 PREV_MAX_IN_HEIGHT);
1761 }
1762
1763 fmt->colorspace = V4L2_COLORSPACE_SRGB;
1764
1765 for (i = 0; i < ARRAY_SIZE(preview_input_fmts); i++) {
1766 if (fmt->code == preview_input_fmts[i])
1767 break;
1768 }
1769
1770 /* If not found, use SGRBG10 as default */
1771 if (i >= ARRAY_SIZE(preview_input_fmts))
1772 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
1773 break;
1774
1775 case PREV_PAD_SOURCE:
1776 pixelcode = fmt->code;
1777 *fmt = *__preview_get_format(prev, fh, PREV_PAD_SINK, which);
1778
1779 switch (pixelcode) {
1780 case V4L2_MBUS_FMT_YUYV8_1X16:
1781 case V4L2_MBUS_FMT_UYVY8_1X16:
1782 fmt->code = pixelcode;
1783 break;
1784
1785 default:
1786 fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
1787 break;
1788 }
1789
1790 /* The preview module output size is configurable through the
1791 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). This
1792 * is not supported yet, hardcode the output size to the crop
1793 * rectangle size.
1794 */
1795 crop = __preview_get_crop(prev, fh, which);
1796 fmt->width = crop->width;
1797 fmt->height = crop->height;
1798
1799 fmt->colorspace = V4L2_COLORSPACE_JPEG;
1800 break;
1801 }
1802
1803 fmt->field = V4L2_FIELD_NONE;
1804}
1805
1806/*
1807 * preview_try_crop - Validate a crop rectangle
1808 * @prev: ISP preview engine
1809 * @sink: format on the sink pad
1810 * @crop: crop rectangle to be validated
1811 *
1812 * The preview engine crops lines and columns for its internal operation,
1813 * depending on which filters are enabled. Enforce minimum crop margins to
1814 * handle that transparently for userspace.
1815 *
1816 * See the explanation at the PREV_MARGIN_* definitions for more details.
1817 */
1818static void preview_try_crop(struct isp_prev_device *prev,
1819 const struct v4l2_mbus_framefmt *sink,
1820 struct v4l2_rect *crop)
1821{
1822 unsigned int left = PREV_MARGIN_LEFT;
1823 unsigned int right = sink->width - PREV_MARGIN_RIGHT;
1824 unsigned int top = PREV_MARGIN_TOP;
1825 unsigned int bottom = sink->height - PREV_MARGIN_BOTTOM;
1826
1827 /* When processing data on-the-fly from the CCDC, at least 2 pixels must
1828 * be cropped from the left and right sides of the image. As we don't
1829 * know which filters will be enabled, increase the left and right
1830 * margins by two.
1831 */
1832 if (prev->input == PREVIEW_INPUT_CCDC) {
1833 left += 2;
1834 right -= 2;
1835 }
1836
1837 /* Restrict left/top to even values to keep the Bayer pattern. */
1838 crop->left &= ~1;
1839 crop->top &= ~1;
1840
1841 crop->left = clamp_t(u32, crop->left, left, right - PREV_MIN_OUT_WIDTH);
1842 crop->top = clamp_t(u32, crop->top, top, bottom - PREV_MIN_OUT_HEIGHT);
1843 crop->width = clamp_t(u32, crop->width, PREV_MIN_OUT_WIDTH,
1844 right - crop->left);
1845 crop->height = clamp_t(u32, crop->height, PREV_MIN_OUT_HEIGHT,
1846 bottom - crop->top);
1847}
1848
1849/*
1850 * preview_enum_mbus_code - Handle pixel format enumeration
1851 * @sd : pointer to v4l2 subdev structure
1852 * @fh : V4L2 subdev file handle
1853 * @code : pointer to v4l2_subdev_mbus_code_enum structure
1854 * return -EINVAL or zero on success
1855 */
1856static int preview_enum_mbus_code(struct v4l2_subdev *sd,
1857 struct v4l2_subdev_fh *fh,
1858 struct v4l2_subdev_mbus_code_enum *code)
1859{
1860 switch (code->pad) {
1861 case PREV_PAD_SINK:
1862 if (code->index >= ARRAY_SIZE(preview_input_fmts))
1863 return -EINVAL;
1864
1865 code->code = preview_input_fmts[code->index];
1866 break;
1867 case PREV_PAD_SOURCE:
1868 if (code->index >= ARRAY_SIZE(preview_output_fmts))
1869 return -EINVAL;
1870
1871 code->code = preview_output_fmts[code->index];
1872 break;
1873 default:
1874 return -EINVAL;
1875 }
1876
1877 return 0;
1878}
1879
1880static int preview_enum_frame_size(struct v4l2_subdev *sd,
1881 struct v4l2_subdev_fh *fh,
1882 struct v4l2_subdev_frame_size_enum *fse)
1883{
1884 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1885 struct v4l2_mbus_framefmt format;
1886
1887 if (fse->index != 0)
1888 return -EINVAL;
1889
1890 format.code = fse->code;
1891 format.width = 1;
1892 format.height = 1;
1893 preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1894 fse->min_width = format.width;
1895 fse->min_height = format.height;
1896
1897 if (format.code != fse->code)
1898 return -EINVAL;
1899
1900 format.code = fse->code;
1901 format.width = -1;
1902 format.height = -1;
1903 preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1904 fse->max_width = format.width;
1905 fse->max_height = format.height;
1906
1907 return 0;
1908}
1909
1910/*
1911 * preview_get_selection - Retrieve a selection rectangle on a pad
1912 * @sd: ISP preview V4L2 subdevice
1913 * @fh: V4L2 subdev file handle
1914 * @sel: Selection rectangle
1915 *
1916 * The only supported rectangles are the crop rectangles on the sink pad.
1917 *
1918 * Return 0 on success or a negative error code otherwise.
1919 */
1920static int preview_get_selection(struct v4l2_subdev *sd,
1921 struct v4l2_subdev_fh *fh,
1922 struct v4l2_subdev_selection *sel)
1923{
1924 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1925 struct v4l2_mbus_framefmt *format;
1926
1927 if (sel->pad != PREV_PAD_SINK)
1928 return -EINVAL;
1929
1930 switch (sel->target) {
1931 case V4L2_SEL_TGT_CROP_BOUNDS:
1932 sel->r.left = 0;
1933 sel->r.top = 0;
1934 sel->r.width = INT_MAX;
1935 sel->r.height = INT_MAX;
1936
1937 format = __preview_get_format(prev, fh, PREV_PAD_SINK,
1938 sel->which);
1939 preview_try_crop(prev, format, &sel->r);
1940 break;
1941
1942 case V4L2_SEL_TGT_CROP:
1943 sel->r = *__preview_get_crop(prev, fh, sel->which);
1944 break;
1945
1946 default:
1947 return -EINVAL;
1948 }
1949
1950 return 0;
1951}
1952
1953/*
1954 * preview_set_selection - Set a selection rectangle on a pad
1955 * @sd: ISP preview V4L2 subdevice
1956 * @fh: V4L2 subdev file handle
1957 * @sel: Selection rectangle
1958 *
1959 * The only supported rectangle is the actual crop rectangle on the sink pad.
1960 *
1961 * Return 0 on success or a negative error code otherwise.
1962 */
1963static int preview_set_selection(struct v4l2_subdev *sd,
1964 struct v4l2_subdev_fh *fh,
1965 struct v4l2_subdev_selection *sel)
1966{
1967 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1968 struct v4l2_mbus_framefmt *format;
1969
1970 if (sel->target != V4L2_SEL_TGT_CROP ||
1971 sel->pad != PREV_PAD_SINK)
1972 return -EINVAL;
1973
1974 /* The crop rectangle can't be changed while streaming. */
1975 if (prev->state != ISP_PIPELINE_STREAM_STOPPED)
1976 return -EBUSY;
1977
1978 /* Modifying the crop rectangle always changes the format on the source
1979 * pad. If the KEEP_CONFIG flag is set, just return the current crop
1980 * rectangle.
1981 */
1982 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
1983 sel->r = *__preview_get_crop(prev, fh, sel->which);
1984 return 0;
1985 }
1986
1987 format = __preview_get_format(prev, fh, PREV_PAD_SINK, sel->which);
1988 preview_try_crop(prev, format, &sel->r);
1989 *__preview_get_crop(prev, fh, sel->which) = sel->r;
1990
1991 /* Update the source format. */
1992 format = __preview_get_format(prev, fh, PREV_PAD_SOURCE, sel->which);
1993 preview_try_format(prev, fh, PREV_PAD_SOURCE, format, sel->which);
1994
1995 return 0;
1996}
1997
1998/*
1999 * preview_get_format - Handle get format by pads subdev method
2000 * @sd : pointer to v4l2 subdev structure
2001 * @fh : V4L2 subdev file handle
2002 * @fmt: pointer to v4l2 subdev format structure
2003 * return -EINVAL or zero on success
2004 */
2005static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
2006 struct v4l2_subdev_format *fmt)
2007{
2008 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2009 struct v4l2_mbus_framefmt *format;
2010
2011 format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
2012 if (format == NULL)
2013 return -EINVAL;
2014
2015 fmt->format = *format;
2016 return 0;
2017}
2018
2019/*
2020 * preview_set_format - Handle set format by pads subdev method
2021 * @sd : pointer to v4l2 subdev structure
2022 * @fh : V4L2 subdev file handle
2023 * @fmt: pointer to v4l2 subdev format structure
2024 * return -EINVAL or zero on success
2025 */
2026static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
2027 struct v4l2_subdev_format *fmt)
2028{
2029 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2030 struct v4l2_mbus_framefmt *format;
2031 struct v4l2_rect *crop;
2032
2033 format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
2034 if (format == NULL)
2035 return -EINVAL;
2036
2037 preview_try_format(prev, fh, fmt->pad, &fmt->format, fmt->which);
2038 *format = fmt->format;
2039
2040 /* Propagate the format from sink to source */
2041 if (fmt->pad == PREV_PAD_SINK) {
2042 /* Reset the crop rectangle. */
2043 crop = __preview_get_crop(prev, fh, fmt->which);
2044 crop->left = 0;
2045 crop->top = 0;
2046 crop->width = fmt->format.width;
2047 crop->height = fmt->format.height;
2048
2049 preview_try_crop(prev, &fmt->format, crop);
2050
2051 /* Update the source format. */
2052 format = __preview_get_format(prev, fh, PREV_PAD_SOURCE,
2053 fmt->which);
2054 preview_try_format(prev, fh, PREV_PAD_SOURCE, format,
2055 fmt->which);
2056 }
2057
2058 return 0;
2059}
2060
2061/*
2062 * preview_init_formats - Initialize formats on all pads
2063 * @sd: ISP preview V4L2 subdevice
2064 * @fh: V4L2 subdev file handle
2065 *
2066 * Initialize all pad formats with default values. If fh is not NULL, try
2067 * formats are initialized on the file handle. Otherwise active formats are
2068 * initialized on the device.
2069 */
2070static int preview_init_formats(struct v4l2_subdev *sd,
2071 struct v4l2_subdev_fh *fh)
2072{
2073 struct v4l2_subdev_format format;
2074
2075 memset(&format, 0, sizeof(format));
2076 format.pad = PREV_PAD_SINK;
2077 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
2078 format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
2079 format.format.width = 4096;
2080 format.format.height = 4096;
2081 preview_set_format(sd, fh, &format);
2082
2083 return 0;
2084}
2085
2086/* subdev core operations */
2087static const struct v4l2_subdev_core_ops preview_v4l2_core_ops = {
2088 .ioctl = preview_ioctl,
2089};
2090
2091/* subdev video operations */
2092static const struct v4l2_subdev_video_ops preview_v4l2_video_ops = {
2093 .s_stream = preview_set_stream,
2094};
2095
2096/* subdev pad operations */
2097static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
2098 .enum_mbus_code = preview_enum_mbus_code,
2099 .enum_frame_size = preview_enum_frame_size,
2100 .get_fmt = preview_get_format,
2101 .set_fmt = preview_set_format,
2102 .get_selection = preview_get_selection,
2103 .set_selection = preview_set_selection,
2104};
2105
2106/* subdev operations */
2107static const struct v4l2_subdev_ops preview_v4l2_ops = {
2108 .core = &preview_v4l2_core_ops,
2109 .video = &preview_v4l2_video_ops,
2110 .pad = &preview_v4l2_pad_ops,
2111};
2112
2113/* subdev internal operations */
2114static const struct v4l2_subdev_internal_ops preview_v4l2_internal_ops = {
2115 .open = preview_init_formats,
2116};
2117
2118/* -----------------------------------------------------------------------------
2119 * Media entity operations
2120 */
2121
2122/*
2123 * preview_link_setup - Setup previewer connections.
2124 * @entity : Pointer to media entity structure
2125 * @local : Pointer to local pad array
2126 * @remote : Pointer to remote pad array
2127 * @flags : Link flags
2128 * return -EINVAL or zero on success
2129 */
2130static int preview_link_setup(struct media_entity *entity,
2131 const struct media_pad *local,
2132 const struct media_pad *remote, u32 flags)
2133{
2134 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
2135 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2136
2137 switch (local->index | media_entity_type(remote->entity)) {
2138 case PREV_PAD_SINK | MEDIA_ENT_T_DEVNODE:
2139 /* read from memory */
2140 if (flags & MEDIA_LNK_FL_ENABLED) {
2141 if (prev->input == PREVIEW_INPUT_CCDC)
2142 return -EBUSY;
2143 prev->input = PREVIEW_INPUT_MEMORY;
2144 } else {
2145 if (prev->input == PREVIEW_INPUT_MEMORY)
2146 prev->input = PREVIEW_INPUT_NONE;
2147 }
2148 break;
2149
2150 case PREV_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
2151 /* read from ccdc */
2152 if (flags & MEDIA_LNK_FL_ENABLED) {
2153 if (prev->input == PREVIEW_INPUT_MEMORY)
2154 return -EBUSY;
2155 prev->input = PREVIEW_INPUT_CCDC;
2156 } else {
2157 if (prev->input == PREVIEW_INPUT_CCDC)
2158 prev->input = PREVIEW_INPUT_NONE;
2159 }
2160 break;
2161
2162 /*
2163 * The ISP core doesn't support pipelines with multiple video outputs.
2164 * Revisit this when it will be implemented, and return -EBUSY for now.
2165 */
2166
2167 case PREV_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
2168 /* write to memory */
2169 if (flags & MEDIA_LNK_FL_ENABLED) {
2170 if (prev->output & ~PREVIEW_OUTPUT_MEMORY)
2171 return -EBUSY;
2172 prev->output |= PREVIEW_OUTPUT_MEMORY;
2173 } else {
2174 prev->output &= ~PREVIEW_OUTPUT_MEMORY;
2175 }
2176 break;
2177
2178 case PREV_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
2179 /* write to resizer */
2180 if (flags & MEDIA_LNK_FL_ENABLED) {
2181 if (prev->output & ~PREVIEW_OUTPUT_RESIZER)
2182 return -EBUSY;
2183 prev->output |= PREVIEW_OUTPUT_RESIZER;
2184 } else {
2185 prev->output &= ~PREVIEW_OUTPUT_RESIZER;
2186 }
2187 break;
2188
2189 default:
2190 return -EINVAL;
2191 }
2192
2193 return 0;
2194}
2195
2196/* media operations */
2197static const struct media_entity_operations preview_media_ops = {
2198 .link_setup = preview_link_setup,
2199 .link_validate = v4l2_subdev_link_validate,
2200};
2201
2202void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
2203{
2204 v4l2_device_unregister_subdev(&prev->subdev);
2205 omap3isp_video_unregister(&prev->video_in);
2206 omap3isp_video_unregister(&prev->video_out);
2207}
2208
2209int omap3isp_preview_register_entities(struct isp_prev_device *prev,
2210 struct v4l2_device *vdev)
2211{
2212 int ret;
2213
2214 /* Register the subdev and video nodes. */
2215 ret = v4l2_device_register_subdev(vdev, &prev->subdev);
2216 if (ret < 0)
2217 goto error;
2218
2219 ret = omap3isp_video_register(&prev->video_in, vdev);
2220 if (ret < 0)
2221 goto error;
2222
2223 ret = omap3isp_video_register(&prev->video_out, vdev);
2224 if (ret < 0)
2225 goto error;
2226
2227 return 0;
2228
2229error:
2230 omap3isp_preview_unregister_entities(prev);
2231 return ret;
2232}
2233
2234/* -----------------------------------------------------------------------------
2235 * ISP previewer initialisation and cleanup
2236 */
2237
2238/*
2239 * preview_init_entities - Initialize subdev and media entity.
2240 * @prev : Pointer to preview structure
2241 * return -ENOMEM or zero on success
2242 */
2243static int preview_init_entities(struct isp_prev_device *prev)
2244{
2245 struct v4l2_subdev *sd = &prev->subdev;
2246 struct media_pad *pads = prev->pads;
2247 struct media_entity *me = &sd->entity;
2248 int ret;
2249
2250 prev->input = PREVIEW_INPUT_NONE;
2251
2252 v4l2_subdev_init(sd, &preview_v4l2_ops);
2253 sd->internal_ops = &preview_v4l2_internal_ops;
2254 strlcpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name));
2255 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
2256 v4l2_set_subdevdata(sd, prev);
2257 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
2258
2259 v4l2_ctrl_handler_init(&prev->ctrls, 2);
2260 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_BRIGHTNESS,
2261 ISPPRV_BRIGHT_LOW, ISPPRV_BRIGHT_HIGH,
2262 ISPPRV_BRIGHT_STEP, ISPPRV_BRIGHT_DEF);
2263 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_CONTRAST,
2264 ISPPRV_CONTRAST_LOW, ISPPRV_CONTRAST_HIGH,
2265 ISPPRV_CONTRAST_STEP, ISPPRV_CONTRAST_DEF);
2266 v4l2_ctrl_handler_setup(&prev->ctrls);
2267 sd->ctrl_handler = &prev->ctrls;
2268
2269 pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
2270 pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
2271
2272 me->ops = &preview_media_ops;
2273 ret = media_entity_init(me, PREV_PADS_NUM, pads, 0);
2274 if (ret < 0)
2275 return ret;
2276
2277 preview_init_formats(sd, NULL);
2278
2279 /* According to the OMAP34xx TRM, video buffers need to be aligned on a
2280 * 32 bytes boundary. However, an undocumented hardware bug requires a
2281 * 64 bytes boundary at the preview engine input.
2282 */
2283 prev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2284 prev->video_in.ops = &preview_video_ops;
2285 prev->video_in.isp = to_isp_device(prev);
2286 prev->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2287 prev->video_in.bpl_alignment = 64;
2288 prev->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2289 prev->video_out.ops = &preview_video_ops;
2290 prev->video_out.isp = to_isp_device(prev);
2291 prev->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2292 prev->video_out.bpl_alignment = 32;
2293
2294 ret = omap3isp_video_init(&prev->video_in, "preview");
2295 if (ret < 0)
2296 goto error_video_in;
2297
2298 ret = omap3isp_video_init(&prev->video_out, "preview");
2299 if (ret < 0)
2300 goto error_video_out;
2301
2302 /* Connect the video nodes to the previewer subdev. */
2303 ret = media_entity_create_link(&prev->video_in.video.entity, 0,
2304 &prev->subdev.entity, PREV_PAD_SINK, 0);
2305 if (ret < 0)
2306 goto error_link;
2307
2308 ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
2309 &prev->video_out.video.entity, 0, 0);
2310 if (ret < 0)
2311 goto error_link;
2312
2313 return 0;
2314
2315error_link:
2316 omap3isp_video_cleanup(&prev->video_out);
2317error_video_out:
2318 omap3isp_video_cleanup(&prev->video_in);
2319error_video_in:
2320 media_entity_cleanup(&prev->subdev.entity);
2321 return ret;
2322}
2323
2324/*
2325 * omap3isp_preview_init - Previewer initialization.
2326 * @dev : Pointer to ISP device
2327 * return -ENOMEM or zero on success
2328 */
2329int omap3isp_preview_init(struct isp_device *isp)
2330{
2331 struct isp_prev_device *prev = &isp->isp_prev;
2332
2333 init_waitqueue_head(&prev->wait);
2334
2335 preview_init_params(prev);
2336
2337 return preview_init_entities(prev);
2338}
2339
2340void omap3isp_preview_cleanup(struct isp_device *isp)
2341{
2342 struct isp_prev_device *prev = &isp->isp_prev;
2343
2344 v4l2_ctrl_handler_free(&prev->ctrls);
2345 omap3isp_video_cleanup(&prev->video_in);
2346 omap3isp_video_cleanup(&prev->video_out);
2347 media_entity_cleanup(&prev->subdev.entity);
2348}
diff --git a/drivers/media/platform/omap3isp/isppreview.h b/drivers/media/platform/omap3isp/isppreview.h
new file mode 100644
index 000000000000..f66923407f8c
--- /dev/null
+++ b/drivers/media/platform/omap3isp/isppreview.h
@@ -0,0 +1,174 @@
1/*
2 * isppreview.h
3 *
4 * TI OMAP3 ISP - Preview module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#ifndef OMAP3_ISP_PREVIEW_H
28#define OMAP3_ISP_PREVIEW_H
29
30#include <linux/omap3isp.h>
31#include <linux/types.h>
32#include <media/v4l2-ctrls.h>
33
34#include "ispvideo.h"
35
36#define ISPPRV_BRIGHT_STEP 0x1
37#define ISPPRV_BRIGHT_DEF 0x0
38#define ISPPRV_BRIGHT_LOW 0x0
39#define ISPPRV_BRIGHT_HIGH 0xFF
40#define ISPPRV_BRIGHT_UNITS 0x1
41
42#define ISPPRV_CONTRAST_STEP 0x1
43#define ISPPRV_CONTRAST_DEF 0x10
44#define ISPPRV_CONTRAST_LOW 0x0
45#define ISPPRV_CONTRAST_HIGH 0xFF
46#define ISPPRV_CONTRAST_UNITS 0x1
47
48/* Additional features not listed in linux/omap3isp.h */
49#define OMAP3ISP_PREV_CONTRAST (1 << 17)
50#define OMAP3ISP_PREV_BRIGHTNESS (1 << 18)
51#define OMAP3ISP_PREV_FEATURES_END (1 << 19)
52
53enum preview_input_entity {
54 PREVIEW_INPUT_NONE,
55 PREVIEW_INPUT_CCDC,
56 PREVIEW_INPUT_MEMORY,
57};
58
59#define PREVIEW_OUTPUT_RESIZER (1 << 1)
60#define PREVIEW_OUTPUT_MEMORY (1 << 2)
61
62/* Configure byte layout of YUV image */
63enum preview_ycpos_mode {
64 YCPOS_YCrYCb = 0,
65 YCPOS_YCbYCr = 1,
66 YCPOS_CbYCrY = 2,
67 YCPOS_CrYCbY = 3
68};
69
70/*
71 * struct prev_params - Structure for all configuration
72 * @busy: Bitmask of busy parameters (being updated or used)
73 * @update: Bitmask of the parameters to be updated
74 * @features: Set of features enabled.
75 * @cfa: CFA coefficients.
76 * @csup: Chroma suppression coefficients.
77 * @luma: Luma enhancement coefficients.
78 * @nf: Noise filter coefficients.
79 * @dcor: Noise filter coefficients.
80 * @gamma: Gamma coefficients.
81 * @wbal: White Balance parameters.
82 * @blkadj: Black adjustment parameters.
83 * @rgb2rgb: RGB blending parameters.
84 * @csc: Color space conversion (RGB to YCbCr) parameters.
85 * @hmed: Horizontal median filter.
86 * @yclimit: YC limits parameters.
87 * @contrast: Contrast.
88 * @brightness: Brightness.
89 */
90struct prev_params {
91 u32 busy;
92 u32 update;
93 u32 features;
94 struct omap3isp_prev_cfa cfa;
95 struct omap3isp_prev_csup csup;
96 struct omap3isp_prev_luma luma;
97 struct omap3isp_prev_nf nf;
98 struct omap3isp_prev_dcor dcor;
99 struct omap3isp_prev_gtables gamma;
100 struct omap3isp_prev_wbal wbal;
101 struct omap3isp_prev_blkadj blkadj;
102 struct omap3isp_prev_rgbtorgb rgb2rgb;
103 struct omap3isp_prev_csc csc;
104 struct omap3isp_prev_hmed hmed;
105 struct omap3isp_prev_yclimit yclimit;
106 u8 contrast;
107 u8 brightness;
108};
109
110/* Sink and source previewer pads */
111#define PREV_PAD_SINK 0
112#define PREV_PAD_SOURCE 1
113#define PREV_PADS_NUM 2
114
115/*
116 * struct isp_prev_device - Structure for storing ISP Preview module information
117 * @subdev: V4L2 subdevice
118 * @pads: Media entity pads
119 * @formats: Active formats at the subdev pad
120 * @crop: Active crop rectangle
121 * @input: Module currently connected to the input pad
122 * @output: Bitmask of the active output
123 * @video_in: Input video entity
124 * @video_out: Output video entity
125 * @params.params : Active and shadow parameters sets
126 * @params.active: Bitmask of parameters active in set 0
127 * @params.lock: Parameters lock, protects params.active and params.shadow
128 * @underrun: Whether the preview entity has queued buffers on the output
129 * @state: Current preview pipeline state
130 *
131 * This structure is used to store the OMAP ISP Preview module Information.
132 */
133struct isp_prev_device {
134 struct v4l2_subdev subdev;
135 struct media_pad pads[PREV_PADS_NUM];
136 struct v4l2_mbus_framefmt formats[PREV_PADS_NUM];
137 struct v4l2_rect crop;
138
139 struct v4l2_ctrl_handler ctrls;
140
141 enum preview_input_entity input;
142 unsigned int output;
143 struct isp_video video_in;
144 struct isp_video video_out;
145
146 struct {
147 unsigned int cfa_order;
148 struct prev_params params[2];
149 u32 active;
150 spinlock_t lock;
151 } params;
152
153 enum isp_pipeline_stream_state state;
154 wait_queue_head_t wait;
155 atomic_t stopping;
156};
157
158struct isp_device;
159
160int omap3isp_preview_init(struct isp_device *isp);
161void omap3isp_preview_cleanup(struct isp_device *isp);
162
163int omap3isp_preview_register_entities(struct isp_prev_device *prv,
164 struct v4l2_device *vdev);
165void omap3isp_preview_unregister_entities(struct isp_prev_device *prv);
166
167void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev);
168void omap3isp_preview_isr(struct isp_prev_device *prev);
169
170int omap3isp_preview_busy(struct isp_prev_device *isp_prev);
171
172void omap3isp_preview_restore_context(struct isp_device *isp);
173
174#endif /* OMAP3_ISP_PREVIEW_H */
diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
new file mode 100644
index 000000000000..15bf3eab2224
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -0,0 +1,1158 @@
1/*
2 * ispqueue.c
3 *
4 * TI OMAP3 ISP - Video buffers queue handling
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 *
8 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9 * Sakari Ailus <sakari.ailus@iki.fi>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA
24 */
25
26#include <asm/cacheflush.h>
27#include <linux/dma-mapping.h>
28#include <linux/mm.h>
29#include <linux/pagemap.h>
30#include <linux/poll.h>
31#include <linux/scatterlist.h>
32#include <linux/sched.h>
33#include <linux/slab.h>
34#include <linux/vmalloc.h>
35
36#include "ispqueue.h"
37
38/* -----------------------------------------------------------------------------
39 * Video buffers management
40 */
41
42/*
43 * isp_video_buffer_cache_sync - Keep the buffers coherent between CPU and ISP
44 *
45 * The typical operation required here is Cache Invalidation across
46 * the (user space) buffer address range. And this _must_ be done
47 * at QBUF stage (and *only* at QBUF).
48 *
49 * We try to use optimal cache invalidation function:
50 * - dmac_map_area:
51 * - used when the number of pages are _low_.
52 * - it becomes quite slow as the number of pages increase.
53 * - for 648x492 viewfinder (150 pages) it takes 1.3 ms.
54 * - for 5 Mpix buffer (2491 pages) it takes between 25-50 ms.
55 *
56 * - flush_cache_all:
57 * - used when the number of pages are _high_.
58 * - time taken in the range of 500-900 us.
59 * - has a higher penalty but, as whole dcache + icache is invalidated
60 */
61/*
62 * FIXME: dmac_inv_range crashes randomly on the user space buffer
63 * address. Fall back to flush_cache_all for now.
64 */
65#define ISP_CACHE_FLUSH_PAGES_MAX 0
66
67static void isp_video_buffer_cache_sync(struct isp_video_buffer *buf)
68{
69 if (buf->skip_cache)
70 return;
71
72 if (buf->vbuf.m.userptr == 0 || buf->npages == 0 ||
73 buf->npages > ISP_CACHE_FLUSH_PAGES_MAX)
74 flush_cache_all();
75 else {
76 dmac_map_area((void *)buf->vbuf.m.userptr, buf->vbuf.length,
77 DMA_FROM_DEVICE);
78 outer_inv_range(buf->vbuf.m.userptr,
79 buf->vbuf.m.userptr + buf->vbuf.length);
80 }
81}
82
83/*
84 * isp_video_buffer_lock_vma - Prevent VMAs from being unmapped
85 *
86 * Lock the VMAs underlying the given buffer into memory. This avoids the
87 * userspace buffer mapping from being swapped out, making VIPT cache handling
88 * easier.
89 *
90 * Note that the pages will not be freed as the buffers have been locked to
91 * memory using by a call to get_user_pages(), but the userspace mapping could
92 * still disappear if the VMAs are not locked. This is caused by the memory
93 * management code trying to be as lock-less as possible, which results in the
94 * userspace mapping manager not finding out that the pages are locked under
95 * some conditions.
96 */
97static int isp_video_buffer_lock_vma(struct isp_video_buffer *buf, int lock)
98{
99 struct vm_area_struct *vma;
100 unsigned long start;
101 unsigned long end;
102 int ret = 0;
103
104 if (buf->vbuf.memory == V4L2_MEMORY_MMAP)
105 return 0;
106
107 /* We can be called from workqueue context if the current task dies to
108 * unlock the VMAs. In that case there's no current memory management
109 * context so unlocking can't be performed, but the VMAs have been or
110 * are getting destroyed anyway so it doesn't really matter.
111 */
112 if (!current || !current->mm)
113 return lock ? -EINVAL : 0;
114
115 start = buf->vbuf.m.userptr;
116 end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
117
118 down_write(&current->mm->mmap_sem);
119 spin_lock(&current->mm->page_table_lock);
120
121 do {
122 vma = find_vma(current->mm, start);
123 if (vma == NULL) {
124 ret = -EFAULT;
125 goto out;
126 }
127
128 if (lock)
129 vma->vm_flags |= VM_LOCKED;
130 else
131 vma->vm_flags &= ~VM_LOCKED;
132
133 start = vma->vm_end + 1;
134 } while (vma->vm_end < end);
135
136 if (lock)
137 buf->vm_flags |= VM_LOCKED;
138 else
139 buf->vm_flags &= ~VM_LOCKED;
140
141out:
142 spin_unlock(&current->mm->page_table_lock);
143 up_write(&current->mm->mmap_sem);
144 return ret;
145}
146
147/*
148 * isp_video_buffer_sglist_kernel - Build a scatter list for a vmalloc'ed buffer
149 *
150 * Iterate over the vmalloc'ed area and create a scatter list entry for every
151 * page.
152 */
153static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
154{
155 struct scatterlist *sglist;
156 unsigned int npages;
157 unsigned int i;
158 void *addr;
159
160 addr = buf->vaddr;
161 npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT;
162
163 sglist = vmalloc(npages * sizeof(*sglist));
164 if (sglist == NULL)
165 return -ENOMEM;
166
167 sg_init_table(sglist, npages);
168
169 for (i = 0; i < npages; ++i, addr += PAGE_SIZE) {
170 struct page *page = vmalloc_to_page(addr);
171
172 if (page == NULL || PageHighMem(page)) {
173 vfree(sglist);
174 return -EINVAL;
175 }
176
177 sg_set_page(&sglist[i], page, PAGE_SIZE, 0);
178 }
179
180 buf->sglen = npages;
181 buf->sglist = sglist;
182
183 return 0;
184}
185
186/*
187 * isp_video_buffer_sglist_user - Build a scatter list for a userspace buffer
188 *
189 * Walk the buffer pages list and create a 1:1 mapping to a scatter list.
190 */
191static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf)
192{
193 struct scatterlist *sglist;
194 unsigned int offset = buf->offset;
195 unsigned int i;
196
197 sglist = vmalloc(buf->npages * sizeof(*sglist));
198 if (sglist == NULL)
199 return -ENOMEM;
200
201 sg_init_table(sglist, buf->npages);
202
203 for (i = 0; i < buf->npages; ++i) {
204 if (PageHighMem(buf->pages[i])) {
205 vfree(sglist);
206 return -EINVAL;
207 }
208
209 sg_set_page(&sglist[i], buf->pages[i], PAGE_SIZE - offset,
210 offset);
211 offset = 0;
212 }
213
214 buf->sglen = buf->npages;
215 buf->sglist = sglist;
216
217 return 0;
218}
219
220/*
221 * isp_video_buffer_sglist_pfnmap - Build a scatter list for a VM_PFNMAP buffer
222 *
223 * Create a scatter list of physically contiguous pages starting at the buffer
224 * memory physical address.
225 */
226static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf)
227{
228 struct scatterlist *sglist;
229 unsigned int offset = buf->offset;
230 unsigned long pfn = buf->paddr >> PAGE_SHIFT;
231 unsigned int i;
232
233 sglist = vmalloc(buf->npages * sizeof(*sglist));
234 if (sglist == NULL)
235 return -ENOMEM;
236
237 sg_init_table(sglist, buf->npages);
238
239 for (i = 0; i < buf->npages; ++i, ++pfn) {
240 sg_set_page(&sglist[i], pfn_to_page(pfn), PAGE_SIZE - offset,
241 offset);
242 /* PFNMAP buffers will not get DMA-mapped, set the DMA address
243 * manually.
244 */
245 sg_dma_address(&sglist[i]) = (pfn << PAGE_SHIFT) + offset;
246 offset = 0;
247 }
248
249 buf->sglen = buf->npages;
250 buf->sglist = sglist;
251
252 return 0;
253}
254
255/*
256 * isp_video_buffer_cleanup - Release pages for a userspace VMA.
257 *
258 * Release pages locked by a call isp_video_buffer_prepare_user and free the
259 * pages table.
260 */
261static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
262{
263 enum dma_data_direction direction;
264 unsigned int i;
265
266 if (buf->queue->ops->buffer_cleanup)
267 buf->queue->ops->buffer_cleanup(buf);
268
269 if (!(buf->vm_flags & VM_PFNMAP)) {
270 direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
271 ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
272 dma_unmap_sg(buf->queue->dev, buf->sglist, buf->sglen,
273 direction);
274 }
275
276 vfree(buf->sglist);
277 buf->sglist = NULL;
278 buf->sglen = 0;
279
280 if (buf->pages != NULL) {
281 isp_video_buffer_lock_vma(buf, 0);
282
283 for (i = 0; i < buf->npages; ++i)
284 page_cache_release(buf->pages[i]);
285
286 vfree(buf->pages);
287 buf->pages = NULL;
288 }
289
290 buf->npages = 0;
291 buf->skip_cache = false;
292}
293
294/*
295 * isp_video_buffer_prepare_user - Pin userspace VMA pages to memory.
296 *
297 * This function creates a list of pages for a userspace VMA. The number of
298 * pages is first computed based on the buffer size, and pages are then
299 * retrieved by a call to get_user_pages.
300 *
301 * Pages are pinned to memory by get_user_pages, making them available for DMA
302 * transfers. However, due to memory management optimization, it seems the
303 * get_user_pages doesn't guarantee that the pinned pages will not be written
304 * to swap and removed from the userspace mapping(s). When this happens, a page
305 * fault can be generated when accessing those unmapped pages.
306 *
307 * If the fault is triggered by a page table walk caused by VIPT cache
308 * management operations, the page fault handler might oops if the MM semaphore
309 * is held, as it can't handle kernel page faults in that case. To fix that, a
310 * fixup entry needs to be added to the cache management code, or the userspace
311 * VMA must be locked to avoid removing pages from the userspace mapping in the
312 * first place.
313 *
314 * If the number of pages retrieved is smaller than the number required by the
315 * buffer size, the function returns -EFAULT.
316 */
317static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
318{
319 unsigned long data;
320 unsigned int first;
321 unsigned int last;
322 int ret;
323
324 data = buf->vbuf.m.userptr;
325 first = (data & PAGE_MASK) >> PAGE_SHIFT;
326 last = ((data + buf->vbuf.length - 1) & PAGE_MASK) >> PAGE_SHIFT;
327
328 buf->offset = data & ~PAGE_MASK;
329 buf->npages = last - first + 1;
330 buf->pages = vmalloc(buf->npages * sizeof(buf->pages[0]));
331 if (buf->pages == NULL)
332 return -ENOMEM;
333
334 down_read(&current->mm->mmap_sem);
335 ret = get_user_pages(current, current->mm, data & PAGE_MASK,
336 buf->npages,
337 buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
338 buf->pages, NULL);
339 up_read(&current->mm->mmap_sem);
340
341 if (ret != buf->npages) {
342 buf->npages = ret < 0 ? 0 : ret;
343 isp_video_buffer_cleanup(buf);
344 return -EFAULT;
345 }
346
347 ret = isp_video_buffer_lock_vma(buf, 1);
348 if (ret < 0)
349 isp_video_buffer_cleanup(buf);
350
351 return ret;
352}
353
354/*
355 * isp_video_buffer_prepare_pfnmap - Validate a VM_PFNMAP userspace buffer
356 *
357 * Userspace VM_PFNMAP buffers are supported only if they are contiguous in
358 * memory and if they span a single VMA.
359 *
360 * Return 0 if the buffer is valid, or -EFAULT otherwise.
361 */
362static int isp_video_buffer_prepare_pfnmap(struct isp_video_buffer *buf)
363{
364 struct vm_area_struct *vma;
365 unsigned long prev_pfn;
366 unsigned long this_pfn;
367 unsigned long start;
368 unsigned long end;
369 dma_addr_t pa;
370 int ret = -EFAULT;
371
372 start = buf->vbuf.m.userptr;
373 end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
374
375 buf->offset = start & ~PAGE_MASK;
376 buf->npages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
377 buf->pages = NULL;
378
379 down_read(&current->mm->mmap_sem);
380 vma = find_vma(current->mm, start);
381 if (vma == NULL || vma->vm_end < end)
382 goto done;
383
384 for (prev_pfn = 0; start <= end; start += PAGE_SIZE) {
385 ret = follow_pfn(vma, start, &this_pfn);
386 if (ret)
387 goto done;
388
389 if (prev_pfn == 0)
390 pa = this_pfn << PAGE_SHIFT;
391 else if (this_pfn != prev_pfn + 1) {
392 ret = -EFAULT;
393 goto done;
394 }
395
396 prev_pfn = this_pfn;
397 }
398
399 buf->paddr = pa + buf->offset;
400 ret = 0;
401
402done:
403 up_read(&current->mm->mmap_sem);
404 return ret;
405}
406
407/*
408 * isp_video_buffer_prepare_vm_flags - Get VMA flags for a userspace address
409 *
410 * This function locates the VMAs for the buffer's userspace address and checks
411 * that their flags match. The only flag that we need to care for at the moment
412 * is VM_PFNMAP.
413 *
414 * The buffer vm_flags field is set to the first VMA flags.
415 *
416 * Return -EFAULT if no VMA can be found for part of the buffer, or if the VMAs
417 * have incompatible flags.
418 */
419static int isp_video_buffer_prepare_vm_flags(struct isp_video_buffer *buf)
420{
421 struct vm_area_struct *vma;
422 pgprot_t vm_page_prot;
423 unsigned long start;
424 unsigned long end;
425 int ret = -EFAULT;
426
427 start = buf->vbuf.m.userptr;
428 end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
429
430 down_read(&current->mm->mmap_sem);
431
432 do {
433 vma = find_vma(current->mm, start);
434 if (vma == NULL)
435 goto done;
436
437 if (start == buf->vbuf.m.userptr) {
438 buf->vm_flags = vma->vm_flags;
439 vm_page_prot = vma->vm_page_prot;
440 }
441
442 if ((buf->vm_flags ^ vma->vm_flags) & VM_PFNMAP)
443 goto done;
444
445 if (vm_page_prot != vma->vm_page_prot)
446 goto done;
447
448 start = vma->vm_end + 1;
449 } while (vma->vm_end < end);
450
451 /* Skip cache management to enhance performances for non-cached or
452 * write-combining buffers.
453 */
454 if (vm_page_prot == pgprot_noncached(vm_page_prot) ||
455 vm_page_prot == pgprot_writecombine(vm_page_prot))
456 buf->skip_cache = true;
457
458 ret = 0;
459
460done:
461 up_read(&current->mm->mmap_sem);
462 return ret;
463}
464
465/*
466 * isp_video_buffer_prepare - Make a buffer ready for operation
467 *
468 * Preparing a buffer involves:
469 *
470 * - validating VMAs (userspace buffers only)
471 * - locking pages and VMAs into memory (userspace buffers only)
472 * - building page and scatter-gather lists
473 * - mapping buffers for DMA operation
474 * - performing driver-specific preparation
475 *
476 * The function must be called in userspace context with a valid mm context
477 * (this excludes cleanup paths such as sys_close when the userspace process
478 * segfaults).
479 */
480static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
481{
482 enum dma_data_direction direction;
483 int ret;
484
485 switch (buf->vbuf.memory) {
486 case V4L2_MEMORY_MMAP:
487 ret = isp_video_buffer_sglist_kernel(buf);
488 break;
489
490 case V4L2_MEMORY_USERPTR:
491 ret = isp_video_buffer_prepare_vm_flags(buf);
492 if (ret < 0)
493 return ret;
494
495 if (buf->vm_flags & VM_PFNMAP) {
496 ret = isp_video_buffer_prepare_pfnmap(buf);
497 if (ret < 0)
498 return ret;
499
500 ret = isp_video_buffer_sglist_pfnmap(buf);
501 } else {
502 ret = isp_video_buffer_prepare_user(buf);
503 if (ret < 0)
504 return ret;
505
506 ret = isp_video_buffer_sglist_user(buf);
507 }
508 break;
509
510 default:
511 return -EINVAL;
512 }
513
514 if (ret < 0)
515 goto done;
516
517 if (!(buf->vm_flags & VM_PFNMAP)) {
518 direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
519 ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
520 ret = dma_map_sg(buf->queue->dev, buf->sglist, buf->sglen,
521 direction);
522 if (ret != buf->sglen) {
523 ret = -EFAULT;
524 goto done;
525 }
526 }
527
528 if (buf->queue->ops->buffer_prepare)
529 ret = buf->queue->ops->buffer_prepare(buf);
530
531done:
532 if (ret < 0) {
533 isp_video_buffer_cleanup(buf);
534 return ret;
535 }
536
537 return ret;
538}
539
540/*
541 * isp_video_queue_query - Query the status of a given buffer
542 *
543 * Locking: must be called with the queue lock held.
544 */
545static void isp_video_buffer_query(struct isp_video_buffer *buf,
546 struct v4l2_buffer *vbuf)
547{
548 memcpy(vbuf, &buf->vbuf, sizeof(*vbuf));
549
550 if (buf->vma_use_count)
551 vbuf->flags |= V4L2_BUF_FLAG_MAPPED;
552
553 switch (buf->state) {
554 case ISP_BUF_STATE_ERROR:
555 vbuf->flags |= V4L2_BUF_FLAG_ERROR;
556 case ISP_BUF_STATE_DONE:
557 vbuf->flags |= V4L2_BUF_FLAG_DONE;
558 case ISP_BUF_STATE_QUEUED:
559 case ISP_BUF_STATE_ACTIVE:
560 vbuf->flags |= V4L2_BUF_FLAG_QUEUED;
561 break;
562 case ISP_BUF_STATE_IDLE:
563 default:
564 break;
565 }
566}
567
568/*
569 * isp_video_buffer_wait - Wait for a buffer to be ready
570 *
571 * In non-blocking mode, return immediately with 0 if the buffer is ready or
572 * -EAGAIN if the buffer is in the QUEUED or ACTIVE state.
573 *
574 * In blocking mode, wait (interruptibly but with no timeout) on the buffer wait
575 * queue using the same condition.
576 */
577static int isp_video_buffer_wait(struct isp_video_buffer *buf, int nonblocking)
578{
579 if (nonblocking) {
580 return (buf->state != ISP_BUF_STATE_QUEUED &&
581 buf->state != ISP_BUF_STATE_ACTIVE)
582 ? 0 : -EAGAIN;
583 }
584
585 return wait_event_interruptible(buf->wait,
586 buf->state != ISP_BUF_STATE_QUEUED &&
587 buf->state != ISP_BUF_STATE_ACTIVE);
588}
589
590/* -----------------------------------------------------------------------------
591 * Queue management
592 */
593
594/*
595 * isp_video_queue_free - Free video buffers memory
596 *
597 * Buffers can only be freed if the queue isn't streaming and if no buffer is
598 * mapped to userspace. Return -EBUSY if those conditions aren't statisfied.
599 *
600 * This function must be called with the queue lock held.
601 */
602static int isp_video_queue_free(struct isp_video_queue *queue)
603{
604 unsigned int i;
605
606 if (queue->streaming)
607 return -EBUSY;
608
609 for (i = 0; i < queue->count; ++i) {
610 if (queue->buffers[i]->vma_use_count != 0)
611 return -EBUSY;
612 }
613
614 for (i = 0; i < queue->count; ++i) {
615 struct isp_video_buffer *buf = queue->buffers[i];
616
617 isp_video_buffer_cleanup(buf);
618
619 vfree(buf->vaddr);
620 buf->vaddr = NULL;
621
622 kfree(buf);
623 queue->buffers[i] = NULL;
624 }
625
626 INIT_LIST_HEAD(&queue->queue);
627 queue->count = 0;
628 return 0;
629}
630
631/*
632 * isp_video_queue_alloc - Allocate video buffers memory
633 *
634 * This function must be called with the queue lock held.
635 */
636static int isp_video_queue_alloc(struct isp_video_queue *queue,
637 unsigned int nbuffers,
638 unsigned int size, enum v4l2_memory memory)
639{
640 struct isp_video_buffer *buf;
641 unsigned int i;
642 void *mem;
643 int ret;
644
645 /* Start by freeing the buffers. */
646 ret = isp_video_queue_free(queue);
647 if (ret < 0)
648 return ret;
649
650 /* Bail out if no buffers should be allocated. */
651 if (nbuffers == 0)
652 return 0;
653
654 /* Initialize the allocated buffers. */
655 for (i = 0; i < nbuffers; ++i) {
656 buf = kzalloc(queue->bufsize, GFP_KERNEL);
657 if (buf == NULL)
658 break;
659
660 if (memory == V4L2_MEMORY_MMAP) {
661 /* Allocate video buffers memory for mmap mode. Align
662 * the size to the page size.
663 */
664 mem = vmalloc_32_user(PAGE_ALIGN(size));
665 if (mem == NULL) {
666 kfree(buf);
667 break;
668 }
669
670 buf->vbuf.m.offset = i * PAGE_ALIGN(size);
671 buf->vaddr = mem;
672 }
673
674 buf->vbuf.index = i;
675 buf->vbuf.length = size;
676 buf->vbuf.type = queue->type;
677 buf->vbuf.field = V4L2_FIELD_NONE;
678 buf->vbuf.memory = memory;
679
680 buf->queue = queue;
681 init_waitqueue_head(&buf->wait);
682
683 queue->buffers[i] = buf;
684 }
685
686 if (i == 0)
687 return -ENOMEM;
688
689 queue->count = i;
690 return nbuffers;
691}
692
693/**
694 * omap3isp_video_queue_cleanup - Clean up the video buffers queue
695 * @queue: Video buffers queue
696 *
697 * Free all allocated resources and clean up the video buffers queue. The queue
698 * must not be busy (no ongoing video stream) and buffers must have been
699 * unmapped.
700 *
701 * Return 0 on success or -EBUSY if the queue is busy or buffers haven't been
702 * unmapped.
703 */
704int omap3isp_video_queue_cleanup(struct isp_video_queue *queue)
705{
706 return isp_video_queue_free(queue);
707}
708
709/**
710 * omap3isp_video_queue_init - Initialize the video buffers queue
711 * @queue: Video buffers queue
712 * @type: V4L2 buffer type (capture or output)
713 * @ops: Driver-specific queue operations
714 * @dev: Device used for DMA operations
715 * @bufsize: Size of the driver-specific buffer structure
716 *
717 * Initialize the video buffers queue with the supplied parameters.
718 *
719 * The queue type must be one of V4L2_BUF_TYPE_VIDEO_CAPTURE or
720 * V4L2_BUF_TYPE_VIDEO_OUTPUT. Other buffer types are not supported yet.
721 *
722 * Buffer objects will be allocated using the given buffer size to allow room
723 * for driver-specific fields. Driver-specific buffer structures must start
724 * with a struct isp_video_buffer field. Drivers with no driver-specific buffer
725 * structure must pass the size of the isp_video_buffer structure in the bufsize
726 * parameter.
727 *
728 * Return 0 on success.
729 */
730int omap3isp_video_queue_init(struct isp_video_queue *queue,
731 enum v4l2_buf_type type,
732 const struct isp_video_queue_operations *ops,
733 struct device *dev, unsigned int bufsize)
734{
735 INIT_LIST_HEAD(&queue->queue);
736 mutex_init(&queue->lock);
737 spin_lock_init(&queue->irqlock);
738
739 queue->type = type;
740 queue->ops = ops;
741 queue->dev = dev;
742 queue->bufsize = bufsize;
743
744 return 0;
745}
746
747/* -----------------------------------------------------------------------------
748 * V4L2 operations
749 */
750
751/**
752 * omap3isp_video_queue_reqbufs - Allocate video buffers memory
753 *
754 * This function is intended to be used as a VIDIOC_REQBUFS ioctl handler. It
755 * allocated video buffer objects and, for MMAP buffers, buffer memory.
756 *
757 * If the number of buffers is 0, all buffers are freed and the function returns
758 * without performing any allocation.
759 *
760 * If the number of buffers is not 0, currently allocated buffers (if any) are
761 * freed and the requested number of buffers are allocated. Depending on
762 * driver-specific requirements and on memory availability, a number of buffer
763 * smaller or bigger than requested can be allocated. This isn't considered as
764 * an error.
765 *
766 * Return 0 on success or one of the following error codes:
767 *
768 * -EINVAL if the buffer type or index are invalid
769 * -EBUSY if the queue is busy (streaming or buffers mapped)
770 * -ENOMEM if the buffers can't be allocated due to an out-of-memory condition
771 */
772int omap3isp_video_queue_reqbufs(struct isp_video_queue *queue,
773 struct v4l2_requestbuffers *rb)
774{
775 unsigned int nbuffers = rb->count;
776 unsigned int size;
777 int ret;
778
779 if (rb->type != queue->type)
780 return -EINVAL;
781
782 queue->ops->queue_prepare(queue, &nbuffers, &size);
783 if (size == 0)
784 return -EINVAL;
785
786 nbuffers = min_t(unsigned int, nbuffers, ISP_VIDEO_MAX_BUFFERS);
787
788 mutex_lock(&queue->lock);
789
790 ret = isp_video_queue_alloc(queue, nbuffers, size, rb->memory);
791 if (ret < 0)
792 goto done;
793
794 rb->count = ret;
795 ret = 0;
796
797done:
798 mutex_unlock(&queue->lock);
799 return ret;
800}
801
802/**
803 * omap3isp_video_queue_querybuf - Query the status of a buffer in a queue
804 *
805 * This function is intended to be used as a VIDIOC_QUERYBUF ioctl handler. It
806 * returns the status of a given video buffer.
807 *
808 * Return 0 on success or -EINVAL if the buffer type or index are invalid.
809 */
810int omap3isp_video_queue_querybuf(struct isp_video_queue *queue,
811 struct v4l2_buffer *vbuf)
812{
813 struct isp_video_buffer *buf;
814 int ret = 0;
815
816 if (vbuf->type != queue->type)
817 return -EINVAL;
818
819 mutex_lock(&queue->lock);
820
821 if (vbuf->index >= queue->count) {
822 ret = -EINVAL;
823 goto done;
824 }
825
826 buf = queue->buffers[vbuf->index];
827 isp_video_buffer_query(buf, vbuf);
828
829done:
830 mutex_unlock(&queue->lock);
831 return ret;
832}
833
834/**
835 * omap3isp_video_queue_qbuf - Queue a buffer
836 *
837 * This function is intended to be used as a VIDIOC_QBUF ioctl handler.
838 *
839 * The v4l2_buffer structure passed from userspace is first sanity tested. If
840 * sane, the buffer is then processed and added to the main queue and, if the
841 * queue is streaming, to the IRQ queue.
842 *
843 * Before being enqueued, USERPTR buffers are checked for address changes. If
844 * the buffer has a different userspace address, the old memory area is unlocked
845 * and the new memory area is locked.
846 */
847int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
848 struct v4l2_buffer *vbuf)
849{
850 struct isp_video_buffer *buf;
851 unsigned long flags;
852 int ret = -EINVAL;
853
854 if (vbuf->type != queue->type)
855 goto done;
856
857 mutex_lock(&queue->lock);
858
859 if (vbuf->index >= queue->count)
860 goto done;
861
862 buf = queue->buffers[vbuf->index];
863
864 if (vbuf->memory != buf->vbuf.memory)
865 goto done;
866
867 if (buf->state != ISP_BUF_STATE_IDLE)
868 goto done;
869
870 if (vbuf->memory == V4L2_MEMORY_USERPTR &&
871 vbuf->length < buf->vbuf.length)
872 goto done;
873
874 if (vbuf->memory == V4L2_MEMORY_USERPTR &&
875 vbuf->m.userptr != buf->vbuf.m.userptr) {
876 isp_video_buffer_cleanup(buf);
877 buf->vbuf.m.userptr = vbuf->m.userptr;
878 buf->prepared = 0;
879 }
880
881 if (!buf->prepared) {
882 ret = isp_video_buffer_prepare(buf);
883 if (ret < 0)
884 goto done;
885 buf->prepared = 1;
886 }
887
888 isp_video_buffer_cache_sync(buf);
889
890 buf->state = ISP_BUF_STATE_QUEUED;
891 list_add_tail(&buf->stream, &queue->queue);
892
893 if (queue->streaming) {
894 spin_lock_irqsave(&queue->irqlock, flags);
895 queue->ops->buffer_queue(buf);
896 spin_unlock_irqrestore(&queue->irqlock, flags);
897 }
898
899 ret = 0;
900
901done:
902 mutex_unlock(&queue->lock);
903 return ret;
904}
905
906/**
907 * omap3isp_video_queue_dqbuf - Dequeue a buffer
908 *
909 * This function is intended to be used as a VIDIOC_DQBUF ioctl handler.
910 *
911 * Wait until a buffer is ready to be dequeued, remove it from the queue and
912 * copy its information to the v4l2_buffer structure.
913 *
914 * If the nonblocking argument is not zero and no buffer is ready, return
915 * -EAGAIN immediately instead of waiting.
916 *
917 * If no buffer has been enqueued, or if the requested buffer type doesn't match
918 * the queue type, return -EINVAL.
919 */
920int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
921 struct v4l2_buffer *vbuf, int nonblocking)
922{
923 struct isp_video_buffer *buf;
924 int ret;
925
926 if (vbuf->type != queue->type)
927 return -EINVAL;
928
929 mutex_lock(&queue->lock);
930
931 if (list_empty(&queue->queue)) {
932 ret = -EINVAL;
933 goto done;
934 }
935
936 buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
937 ret = isp_video_buffer_wait(buf, nonblocking);
938 if (ret < 0)
939 goto done;
940
941 list_del(&buf->stream);
942
943 isp_video_buffer_query(buf, vbuf);
944 buf->state = ISP_BUF_STATE_IDLE;
945 vbuf->flags &= ~V4L2_BUF_FLAG_QUEUED;
946
947done:
948 mutex_unlock(&queue->lock);
949 return ret;
950}
951
952/**
953 * omap3isp_video_queue_streamon - Start streaming
954 *
955 * This function is intended to be used as a VIDIOC_STREAMON ioctl handler. It
956 * starts streaming on the queue and calls the buffer_queue operation for all
957 * queued buffers.
958 *
959 * Return 0 on success.
960 */
961int omap3isp_video_queue_streamon(struct isp_video_queue *queue)
962{
963 struct isp_video_buffer *buf;
964 unsigned long flags;
965
966 mutex_lock(&queue->lock);
967
968 if (queue->streaming)
969 goto done;
970
971 queue->streaming = 1;
972
973 spin_lock_irqsave(&queue->irqlock, flags);
974 list_for_each_entry(buf, &queue->queue, stream)
975 queue->ops->buffer_queue(buf);
976 spin_unlock_irqrestore(&queue->irqlock, flags);
977
978done:
979 mutex_unlock(&queue->lock);
980 return 0;
981}
982
983/**
984 * omap3isp_video_queue_streamoff - Stop streaming
985 *
986 * This function is intended to be used as a VIDIOC_STREAMOFF ioctl handler. It
987 * stops streaming on the queue and wakes up all the buffers.
988 *
989 * Drivers must stop the hardware and synchronize with interrupt handlers and/or
990 * delayed works before calling this function to make sure no buffer will be
991 * touched by the driver and/or hardware.
992 */
993void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
994{
995 struct isp_video_buffer *buf;
996 unsigned long flags;
997 unsigned int i;
998
999 mutex_lock(&queue->lock);
1000
1001 if (!queue->streaming)
1002 goto done;
1003
1004 queue->streaming = 0;
1005
1006 spin_lock_irqsave(&queue->irqlock, flags);
1007 for (i = 0; i < queue->count; ++i) {
1008 buf = queue->buffers[i];
1009
1010 if (buf->state == ISP_BUF_STATE_ACTIVE)
1011 wake_up(&buf->wait);
1012
1013 buf->state = ISP_BUF_STATE_IDLE;
1014 }
1015 spin_unlock_irqrestore(&queue->irqlock, flags);
1016
1017 INIT_LIST_HEAD(&queue->queue);
1018
1019done:
1020 mutex_unlock(&queue->lock);
1021}
1022
1023/**
1024 * omap3isp_video_queue_discard_done - Discard all buffers marked as DONE
1025 *
1026 * This function is intended to be used with suspend/resume operations. It
1027 * discards all 'done' buffers as they would be too old to be requested after
1028 * resume.
1029 *
1030 * Drivers must stop the hardware and synchronize with interrupt handlers and/or
1031 * delayed works before calling this function to make sure no buffer will be
1032 * touched by the driver and/or hardware.
1033 */
1034void omap3isp_video_queue_discard_done(struct isp_video_queue *queue)
1035{
1036 struct isp_video_buffer *buf;
1037 unsigned int i;
1038
1039 mutex_lock(&queue->lock);
1040
1041 if (!queue->streaming)
1042 goto done;
1043
1044 for (i = 0; i < queue->count; ++i) {
1045 buf = queue->buffers[i];
1046
1047 if (buf->state == ISP_BUF_STATE_DONE)
1048 buf->state = ISP_BUF_STATE_ERROR;
1049 }
1050
1051done:
1052 mutex_unlock(&queue->lock);
1053}
1054
1055static void isp_video_queue_vm_open(struct vm_area_struct *vma)
1056{
1057 struct isp_video_buffer *buf = vma->vm_private_data;
1058
1059 buf->vma_use_count++;
1060}
1061
1062static void isp_video_queue_vm_close(struct vm_area_struct *vma)
1063{
1064 struct isp_video_buffer *buf = vma->vm_private_data;
1065
1066 buf->vma_use_count--;
1067}
1068
1069static const struct vm_operations_struct isp_video_queue_vm_ops = {
1070 .open = isp_video_queue_vm_open,
1071 .close = isp_video_queue_vm_close,
1072};
1073
1074/**
1075 * omap3isp_video_queue_mmap - Map buffers to userspace
1076 *
1077 * This function is intended to be used as an mmap() file operation handler. It
1078 * maps a buffer to userspace based on the VMA offset.
1079 *
1080 * Only buffers of memory type MMAP are supported.
1081 */
1082int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
1083 struct vm_area_struct *vma)
1084{
1085 struct isp_video_buffer *uninitialized_var(buf);
1086 unsigned long size;
1087 unsigned int i;
1088 int ret = 0;
1089
1090 mutex_lock(&queue->lock);
1091
1092 for (i = 0; i < queue->count; ++i) {
1093 buf = queue->buffers[i];
1094 if ((buf->vbuf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
1095 break;
1096 }
1097
1098 if (i == queue->count) {
1099 ret = -EINVAL;
1100 goto done;
1101 }
1102
1103 size = vma->vm_end - vma->vm_start;
1104
1105 if (buf->vbuf.memory != V4L2_MEMORY_MMAP ||
1106 size != PAGE_ALIGN(buf->vbuf.length)) {
1107 ret = -EINVAL;
1108 goto done;
1109 }
1110
1111 ret = remap_vmalloc_range(vma, buf->vaddr, 0);
1112 if (ret < 0)
1113 goto done;
1114
1115 vma->vm_ops = &isp_video_queue_vm_ops;
1116 vma->vm_private_data = buf;
1117 isp_video_queue_vm_open(vma);
1118
1119done:
1120 mutex_unlock(&queue->lock);
1121 return ret;
1122}
1123
1124/**
1125 * omap3isp_video_queue_poll - Poll video queue state
1126 *
1127 * This function is intended to be used as a poll() file operation handler. It
1128 * polls the state of the video buffer at the front of the queue and returns an
1129 * events mask.
1130 *
1131 * If no buffer is present at the front of the queue, POLLERR is returned.
1132 */
1133unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
1134 struct file *file, poll_table *wait)
1135{
1136 struct isp_video_buffer *buf;
1137 unsigned int mask = 0;
1138
1139 mutex_lock(&queue->lock);
1140 if (list_empty(&queue->queue)) {
1141 mask |= POLLERR;
1142 goto done;
1143 }
1144 buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
1145
1146 poll_wait(file, &buf->wait, wait);
1147 if (buf->state == ISP_BUF_STATE_DONE ||
1148 buf->state == ISP_BUF_STATE_ERROR) {
1149 if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1150 mask |= POLLIN | POLLRDNORM;
1151 else
1152 mask |= POLLOUT | POLLWRNORM;
1153 }
1154
1155done:
1156 mutex_unlock(&queue->lock);
1157 return mask;
1158}
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
new file mode 100644
index 000000000000..908dfd712e8e
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -0,0 +1,187 @@
1/*
2 * ispqueue.h
3 *
4 * TI OMAP3 ISP - Video buffers queue handling
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 *
8 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9 * Sakari Ailus <sakari.ailus@iki.fi>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA
24 */
25
26#ifndef OMAP3_ISP_QUEUE_H
27#define OMAP3_ISP_QUEUE_H
28
29#include <linux/kernel.h>
30#include <linux/list.h>
31#include <linux/mutex.h>
32#include <linux/videodev2.h>
33#include <linux/wait.h>
34
35struct isp_video_queue;
36struct page;
37struct scatterlist;
38
39#define ISP_VIDEO_MAX_BUFFERS 16
40
41/**
42 * enum isp_video_buffer_state - ISP video buffer state
43 * @ISP_BUF_STATE_IDLE: The buffer is under userspace control (dequeued
44 * or not queued yet).
45 * @ISP_BUF_STATE_QUEUED: The buffer has been queued but isn't used by the
46 * device yet.
47 * @ISP_BUF_STATE_ACTIVE: The buffer is in use for an active video transfer.
48 * @ISP_BUF_STATE_ERROR: The device is done with the buffer and an error
49 * occurred. For capture device the buffer likely contains corrupted data or
50 * no data at all.
51 * @ISP_BUF_STATE_DONE: The device is done with the buffer and no error occurred.
52 * For capture devices the buffer contains valid data.
53 */
54enum isp_video_buffer_state {
55 ISP_BUF_STATE_IDLE,
56 ISP_BUF_STATE_QUEUED,
57 ISP_BUF_STATE_ACTIVE,
58 ISP_BUF_STATE_ERROR,
59 ISP_BUF_STATE_DONE,
60};
61
62/**
63 * struct isp_video_buffer - ISP video buffer
64 * @vma_use_count: Number of times the buffer is mmap'ed to userspace
65 * @stream: List head for insertion into main queue
66 * @queue: ISP buffers queue this buffer belongs to
67 * @prepared: Whether the buffer has been prepared
68 * @skip_cache: Whether to skip cache management operations for this buffer
69 * @vaddr: Memory virtual address (for kernel buffers)
70 * @vm_flags: Buffer VMA flags (for userspace buffers)
71 * @offset: Offset inside the first page (for userspace buffers)
72 * @npages: Number of pages (for userspace buffers)
73 * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
74 * @paddr: Memory physical address (for userspace VM_PFNMAP buffers)
75 * @sglen: Number of elements in the scatter list (for non-VM_PFNMAP buffers)
76 * @sglist: Scatter list (for non-VM_PFNMAP buffers)
77 * @vbuf: V4L2 buffer
78 * @irqlist: List head for insertion into IRQ queue
79 * @state: Current buffer state
80 * @wait: Wait queue to signal buffer completion
81 */
82struct isp_video_buffer {
83 unsigned long vma_use_count;
84 struct list_head stream;
85 struct isp_video_queue *queue;
86 unsigned int prepared:1;
87 bool skip_cache;
88
89 /* For kernel buffers. */
90 void *vaddr;
91
92 /* For userspace buffers. */
93 vm_flags_t vm_flags;
94 unsigned long offset;
95 unsigned int npages;
96 struct page **pages;
97 dma_addr_t paddr;
98
99 /* For all buffers except VM_PFNMAP. */
100 unsigned int sglen;
101 struct scatterlist *sglist;
102
103 /* Touched by the interrupt handler. */
104 struct v4l2_buffer vbuf;
105 struct list_head irqlist;
106 enum isp_video_buffer_state state;
107 wait_queue_head_t wait;
108};
109
110#define to_isp_video_buffer(vb) container_of(vb, struct isp_video_buffer, vb)
111
112/**
113 * struct isp_video_queue_operations - Driver-specific operations
114 * @queue_prepare: Called before allocating buffers. Drivers should clamp the
115 * number of buffers according to their requirements, and must return the
116 * buffer size in bytes.
117 * @buffer_prepare: Called the first time a buffer is queued, or after changing
118 * the userspace memory address for a USERPTR buffer, with the queue lock
119 * held. Drivers should perform device-specific buffer preparation (such as
120 * mapping the buffer memory in an IOMMU). This operation is optional.
121 * @buffer_queue: Called when a buffer is being added to the queue with the
122 * queue irqlock spinlock held.
123 * @buffer_cleanup: Called before freeing buffers, or before changing the
124 * userspace memory address for a USERPTR buffer, with the queue lock held.
125 * Drivers must perform cleanup operations required to undo the
126 * buffer_prepare call. This operation is optional.
127 */
128struct isp_video_queue_operations {
129 void (*queue_prepare)(struct isp_video_queue *queue,
130 unsigned int *nbuffers, unsigned int *size);
131 int (*buffer_prepare)(struct isp_video_buffer *buf);
132 void (*buffer_queue)(struct isp_video_buffer *buf);
133 void (*buffer_cleanup)(struct isp_video_buffer *buf);
134};
135
136/**
137 * struct isp_video_queue - ISP video buffers queue
138 * @type: Type of video buffers handled by this queue
139 * @ops: Queue operations
140 * @dev: Device used for DMA operations
141 * @bufsize: Size of a driver-specific buffer object
142 * @count: Number of currently allocated buffers
143 * @buffers: ISP video buffers
144 * @lock: Mutex to protect access to the buffers, main queue and state
145 * @irqlock: Spinlock to protect access to the IRQ queue
146 * @streaming: Queue state, indicates whether the queue is streaming
147 * @queue: List of all queued buffers
148 */
149struct isp_video_queue {
150 enum v4l2_buf_type type;
151 const struct isp_video_queue_operations *ops;
152 struct device *dev;
153 unsigned int bufsize;
154
155 unsigned int count;
156 struct isp_video_buffer *buffers[ISP_VIDEO_MAX_BUFFERS];
157 struct mutex lock;
158 spinlock_t irqlock;
159
160 unsigned int streaming:1;
161
162 struct list_head queue;
163};
164
165int omap3isp_video_queue_cleanup(struct isp_video_queue *queue);
166int omap3isp_video_queue_init(struct isp_video_queue *queue,
167 enum v4l2_buf_type type,
168 const struct isp_video_queue_operations *ops,
169 struct device *dev, unsigned int bufsize);
170
171int omap3isp_video_queue_reqbufs(struct isp_video_queue *queue,
172 struct v4l2_requestbuffers *rb);
173int omap3isp_video_queue_querybuf(struct isp_video_queue *queue,
174 struct v4l2_buffer *vbuf);
175int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
176 struct v4l2_buffer *vbuf);
177int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
178 struct v4l2_buffer *vbuf, int nonblocking);
179int omap3isp_video_queue_streamon(struct isp_video_queue *queue);
180void omap3isp_video_queue_streamoff(struct isp_video_queue *queue);
181void omap3isp_video_queue_discard_done(struct isp_video_queue *queue);
182int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
183 struct vm_area_struct *vma);
184unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
185 struct file *file, poll_table *wait);
186
187#endif /* OMAP3_ISP_QUEUE_H */
diff --git a/drivers/media/platform/omap3isp/ispreg.h b/drivers/media/platform/omap3isp/ispreg.h
new file mode 100644
index 000000000000..084ea77d65a7
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispreg.h
@@ -0,0 +1,1586 @@
1/*
2 * ispreg.h
3 *
4 * TI OMAP3 ISP - Registers definitions
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#ifndef OMAP3_ISP_REG_H
28#define OMAP3_ISP_REG_H
29
30#include <plat/omap34xx.h>
31
32
33#define CM_CAM_MCLK_HZ 172800000 /* Hz */
34
35/* ISP Submodules offset */
36
37#define OMAP3ISP_REG_BASE OMAP3430_ISP_BASE
38#define OMAP3ISP_REG(offset) (OMAP3ISP_REG_BASE + (offset))
39
40#define OMAP3ISP_CCP2_REG_OFFSET 0x0400
41#define OMAP3ISP_CCP2_REG_BASE (OMAP3ISP_REG_BASE + \
42 OMAP3ISP_CCP2_REG_OFFSET)
43#define OMAP3ISP_CCP2_REG(offset) (OMAP3ISP_CCP2_REG_BASE + (offset))
44
45#define OMAP3ISP_CCDC_REG_OFFSET 0x0600
46#define OMAP3ISP_CCDC_REG_BASE (OMAP3ISP_REG_BASE + \
47 OMAP3ISP_CCDC_REG_OFFSET)
48#define OMAP3ISP_CCDC_REG(offset) (OMAP3ISP_CCDC_REG_BASE + (offset))
49
50#define OMAP3ISP_HIST_REG_OFFSET 0x0A00
51#define OMAP3ISP_HIST_REG_BASE (OMAP3ISP_REG_BASE + \
52 OMAP3ISP_HIST_REG_OFFSET)
53#define OMAP3ISP_HIST_REG(offset) (OMAP3ISP_HIST_REG_BASE + (offset))
54
55#define OMAP3ISP_H3A_REG_OFFSET 0x0C00
56#define OMAP3ISP_H3A_REG_BASE (OMAP3ISP_REG_BASE + \
57 OMAP3ISP_H3A_REG_OFFSET)
58#define OMAP3ISP_H3A_REG(offset) (OMAP3ISP_H3A_REG_BASE + (offset))
59
60#define OMAP3ISP_PREV_REG_OFFSET 0x0E00
61#define OMAP3ISP_PREV_REG_BASE (OMAP3ISP_REG_BASE + \
62 OMAP3ISP_PREV_REG_OFFSET)
63#define OMAP3ISP_PREV_REG(offset) (OMAP3ISP_PREV_REG_BASE + (offset))
64
65#define OMAP3ISP_RESZ_REG_OFFSET 0x1000
66#define OMAP3ISP_RESZ_REG_BASE (OMAP3ISP_REG_BASE + \
67 OMAP3ISP_RESZ_REG_OFFSET)
68#define OMAP3ISP_RESZ_REG(offset) (OMAP3ISP_RESZ_REG_BASE + (offset))
69
70#define OMAP3ISP_SBL_REG_OFFSET 0x1200
71#define OMAP3ISP_SBL_REG_BASE (OMAP3ISP_REG_BASE + \
72 OMAP3ISP_SBL_REG_OFFSET)
73#define OMAP3ISP_SBL_REG(offset) (OMAP3ISP_SBL_REG_BASE + (offset))
74
75#define OMAP3ISP_CSI2A_REGS1_REG_OFFSET 0x1800
76#define OMAP3ISP_CSI2A_REGS1_REG_BASE (OMAP3ISP_REG_BASE + \
77 OMAP3ISP_CSI2A_REGS1_REG_OFFSET)
78#define OMAP3ISP_CSI2A_REGS1_REG(offset) \
79 (OMAP3ISP_CSI2A_REGS1_REG_BASE + (offset))
80
81#define OMAP3ISP_CSIPHY2_REG_OFFSET 0x1970
82#define OMAP3ISP_CSIPHY2_REG_BASE (OMAP3ISP_REG_BASE + \
83 OMAP3ISP_CSIPHY2_REG_OFFSET)
84#define OMAP3ISP_CSIPHY2_REG(offset) (OMAP3ISP_CSIPHY2_REG_BASE + (offset))
85
86#define OMAP3ISP_CSI2A_REGS2_REG_OFFSET 0x19C0
87#define OMAP3ISP_CSI2A_REGS2_REG_BASE (OMAP3ISP_REG_BASE + \
88 OMAP3ISP_CSI2A_REGS2_REG_OFFSET)
89#define OMAP3ISP_CSI2A_REGS2_REG(offset) \
90 (OMAP3ISP_CSI2A_REGS2_REG_BASE + (offset))
91
92#define OMAP3ISP_CSI2C_REGS1_REG_OFFSET 0x1C00
93#define OMAP3ISP_CSI2C_REGS1_REG_BASE (OMAP3ISP_REG_BASE + \
94 OMAP3ISP_CSI2C_REGS1_REG_OFFSET)
95#define OMAP3ISP_CSI2C_REGS1_REG(offset) \
96 (OMAP3ISP_CSI2C_REGS1_REG_BASE + (offset))
97
98#define OMAP3ISP_CSIPHY1_REG_OFFSET 0x1D70
99#define OMAP3ISP_CSIPHY1_REG_BASE (OMAP3ISP_REG_BASE + \
100 OMAP3ISP_CSIPHY1_REG_OFFSET)
101#define OMAP3ISP_CSIPHY1_REG(offset) (OMAP3ISP_CSIPHY1_REG_BASE + (offset))
102
103#define OMAP3ISP_CSI2C_REGS2_REG_OFFSET 0x1DC0
104#define OMAP3ISP_CSI2C_REGS2_REG_BASE (OMAP3ISP_REG_BASE + \
105 OMAP3ISP_CSI2C_REGS2_REG_OFFSET)
106#define OMAP3ISP_CSI2C_REGS2_REG(offset) \
107 (OMAP3ISP_CSI2C_REGS2_REG_BASE + (offset))
108
109/* ISP module register offset */
110
111#define ISP_REVISION (0x000)
112#define ISP_SYSCONFIG (0x004)
113#define ISP_SYSSTATUS (0x008)
114#define ISP_IRQ0ENABLE (0x00C)
115#define ISP_IRQ0STATUS (0x010)
116#define ISP_IRQ1ENABLE (0x014)
117#define ISP_IRQ1STATUS (0x018)
118#define ISP_TCTRL_GRESET_LENGTH (0x030)
119#define ISP_TCTRL_PSTRB_REPLAY (0x034)
120#define ISP_CTRL (0x040)
121#define ISP_SECURE (0x044)
122#define ISP_TCTRL_CTRL (0x050)
123#define ISP_TCTRL_FRAME (0x054)
124#define ISP_TCTRL_PSTRB_DELAY (0x058)
125#define ISP_TCTRL_STRB_DELAY (0x05C)
126#define ISP_TCTRL_SHUT_DELAY (0x060)
127#define ISP_TCTRL_PSTRB_LENGTH (0x064)
128#define ISP_TCTRL_STRB_LENGTH (0x068)
129#define ISP_TCTRL_SHUT_LENGTH (0x06C)
130#define ISP_PING_PONG_ADDR (0x070)
131#define ISP_PING_PONG_MEM_RANGE (0x074)
132#define ISP_PING_PONG_BUF_SIZE (0x078)
133
134/* CCP2 receiver registers */
135
136#define ISPCCP2_REVISION (0x000)
137#define ISPCCP2_SYSCONFIG (0x004)
138#define ISPCCP2_SYSCONFIG_SOFT_RESET (1 << 1)
139#define ISPCCP2_SYSCONFIG_AUTO_IDLE 0x1
140#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT 12
141#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_FORCE \
142 (0x0 << ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
143#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_NO \
144 (0x1 << ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
145#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SMART \
146 (0x2 << ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
147#define ISPCCP2_SYSSTATUS (0x008)
148#define ISPCCP2_SYSSTATUS_RESET_DONE (1 << 0)
149#define ISPCCP2_LC01_IRQENABLE (0x00C)
150#define ISPCCP2_LC01_IRQSTATUS (0x010)
151#define ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ (1 << 11)
152#define ISPCCP2_LC01_IRQSTATUS_LC0_LE_IRQ (1 << 10)
153#define ISPCCP2_LC01_IRQSTATUS_LC0_LS_IRQ (1 << 9)
154#define ISPCCP2_LC01_IRQSTATUS_LC0_FE_IRQ (1 << 8)
155#define ISPCCP2_LC01_IRQSTATUS_LC0_COUNT_IRQ (1 << 7)
156#define ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ (1 << 5)
157#define ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ (1 << 4)
158#define ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ (1 << 3)
159#define ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ (1 << 2)
160#define ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ (1 << 1)
161#define ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ (1 << 0)
162
163#define ISPCCP2_LC23_IRQENABLE (0x014)
164#define ISPCCP2_LC23_IRQSTATUS (0x018)
165#define ISPCCP2_LCM_IRQENABLE (0x02C)
166#define ISPCCP2_LCM_IRQSTATUS_EOF_IRQ (1 << 0)
167#define ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ (1 << 1)
168#define ISPCCP2_LCM_IRQSTATUS (0x030)
169#define ISPCCP2_CTRL (0x040)
170#define ISPCCP2_CTRL_IF_EN (1 << 0)
171#define ISPCCP2_CTRL_PHY_SEL (1 << 1)
172#define ISPCCP2_CTRL_PHY_SEL_CLOCK (0 << 1)
173#define ISPCCP2_CTRL_PHY_SEL_STROBE (1 << 1)
174#define ISPCCP2_CTRL_PHY_SEL_MASK 0x1
175#define ISPCCP2_CTRL_PHY_SEL_SHIFT 1
176#define ISPCCP2_CTRL_IO_OUT_SEL (1 << 2)
177#define ISPCCP2_CTRL_MODE (1 << 4)
178#define ISPCCP2_CTRL_VP_CLK_FORCE_ON (1 << 9)
179#define ISPCCP2_CTRL_INV (1 << 10)
180#define ISPCCP2_CTRL_INV_MASK 0x1
181#define ISPCCP2_CTRL_INV_SHIFT 10
182#define ISPCCP2_CTRL_VP_ONLY_EN (1 << 11)
183#define ISPCCP2_CTRL_VP_CLK_POL (1 << 12)
184#define ISPCCP2_CTRL_VPCLK_DIV_SHIFT 15
185#define ISPCCP2_CTRL_VPCLK_DIV_MASK 0x1ffff /* [31:15] */
186#define ISPCCP2_CTRL_VP_OUT_CTRL_SHIFT 8 /* 3430 bits */
187#define ISPCCP2_CTRL_VP_OUT_CTRL_MASK 0x3 /* 3430 bits */
188#define ISPCCP2_DBG (0x044)
189#define ISPCCP2_GNQ (0x048)
190#define ISPCCP2_LCx_CTRL(x) ((0x050)+0x30*(x))
191#define ISPCCP2_LCx_CTRL_CHAN_EN (1 << 0)
192#define ISPCCP2_LCx_CTRL_CRC_EN (1 << 19)
193#define ISPCCP2_LCx_CTRL_CRC_MASK 0x1
194#define ISPCCP2_LCx_CTRL_CRC_SHIFT 2
195#define ISPCCP2_LCx_CTRL_CRC_SHIFT_15_0 19
196#define ISPCCP2_LCx_CTRL_REGION_EN (1 << 1)
197#define ISPCCP2_LCx_CTRL_REGION_MASK 0x1
198#define ISPCCP2_LCx_CTRL_REGION_SHIFT 1
199#define ISPCCP2_LCx_CTRL_FORMAT_MASK_15_0 0x3f
200#define ISPCCP2_LCx_CTRL_FORMAT_SHIFT_15_0 0x2
201#define ISPCCP2_LCx_CTRL_FORMAT_MASK 0x1f
202#define ISPCCP2_LCx_CTRL_FORMAT_SHIFT 0x3
203#define ISPCCP2_LCx_CODE(x) ((0x054)+0x30*(x))
204#define ISPCCP2_LCx_STAT_START(x) ((0x058)+0x30*(x))
205#define ISPCCP2_LCx_STAT_SIZE(x) ((0x05C)+0x30*(x))
206#define ISPCCP2_LCx_SOF_ADDR(x) ((0x060)+0x30*(x))
207#define ISPCCP2_LCx_EOF_ADDR(x) ((0x064)+0x30*(x))
208#define ISPCCP2_LCx_DAT_START(x) ((0x068)+0x30*(x))
209#define ISPCCP2_LCx_DAT_SIZE(x) ((0x06C)+0x30*(x))
210#define ISPCCP2_LCx_DAT_MASK 0xFFF
211#define ISPCCP2_LCx_DAT_SHIFT 16
212#define ISPCCP2_LCx_DAT_PING_ADDR(x) ((0x070)+0x30*(x))
213#define ISPCCP2_LCx_DAT_PONG_ADDR(x) ((0x074)+0x30*(x))
214#define ISPCCP2_LCx_DAT_OFST(x) ((0x078)+0x30*(x))
215#define ISPCCP2_LCM_CTRL (0x1D0)
216#define ISPCCP2_LCM_CTRL_CHAN_EN (1 << 0)
217#define ISPCCP2_LCM_CTRL_DST_PORT (1 << 2)
218#define ISPCCP2_LCM_CTRL_DST_PORT_SHIFT 2
219#define ISPCCP2_LCM_CTRL_READ_THROTTLE_SHIFT 3
220#define ISPCCP2_LCM_CTRL_READ_THROTTLE_MASK 0x11
221#define ISPCCP2_LCM_CTRL_BURST_SIZE_SHIFT 5
222#define ISPCCP2_LCM_CTRL_BURST_SIZE_MASK 0x7
223#define ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT 16
224#define ISPCCP2_LCM_CTRL_SRC_FORMAT_MASK 0x7
225#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_SHIFT 20
226#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_MASK 0x3
227#define ISPCCP2_LCM_CTRL_SRC_DPCM_PRED (1 << 22)
228#define ISPCCP2_LCM_CTRL_SRC_PACK (1 << 23)
229#define ISPCCP2_LCM_CTRL_DST_FORMAT_SHIFT 24
230#define ISPCCP2_LCM_CTRL_DST_FORMAT_MASK 0x7
231#define ISPCCP2_LCM_VSIZE (0x1D4)
232#define ISPCCP2_LCM_VSIZE_SHIFT 16
233#define ISPCCP2_LCM_HSIZE (0x1D8)
234#define ISPCCP2_LCM_HSIZE_SHIFT 16
235#define ISPCCP2_LCM_PREFETCH (0x1DC)
236#define ISPCCP2_LCM_PREFETCH_SHIFT 3
237#define ISPCCP2_LCM_SRC_ADDR (0x1E0)
238#define ISPCCP2_LCM_SRC_OFST (0x1E4)
239#define ISPCCP2_LCM_DST_ADDR (0x1E8)
240#define ISPCCP2_LCM_DST_OFST (0x1EC)
241
242/* CCDC module register offset */
243
244#define ISPCCDC_PID (0x000)
245#define ISPCCDC_PCR (0x004)
246#define ISPCCDC_SYN_MODE (0x008)
247#define ISPCCDC_HD_VD_WID (0x00C)
248#define ISPCCDC_PIX_LINES (0x010)
249#define ISPCCDC_HORZ_INFO (0x014)
250#define ISPCCDC_VERT_START (0x018)
251#define ISPCCDC_VERT_LINES (0x01C)
252#define ISPCCDC_CULLING (0x020)
253#define ISPCCDC_HSIZE_OFF (0x024)
254#define ISPCCDC_SDOFST (0x028)
255#define ISPCCDC_SDR_ADDR (0x02C)
256#define ISPCCDC_CLAMP (0x030)
257#define ISPCCDC_DCSUB (0x034)
258#define ISPCCDC_COLPTN (0x038)
259#define ISPCCDC_BLKCMP (0x03C)
260#define ISPCCDC_FPC (0x040)
261#define ISPCCDC_FPC_ADDR (0x044)
262#define ISPCCDC_VDINT (0x048)
263#define ISPCCDC_ALAW (0x04C)
264#define ISPCCDC_REC656IF (0x050)
265#define ISPCCDC_CFG (0x054)
266#define ISPCCDC_FMTCFG (0x058)
267#define ISPCCDC_FMT_HORZ (0x05C)
268#define ISPCCDC_FMT_VERT (0x060)
269#define ISPCCDC_FMT_ADDR0 (0x064)
270#define ISPCCDC_FMT_ADDR1 (0x068)
271#define ISPCCDC_FMT_ADDR2 (0x06C)
272#define ISPCCDC_FMT_ADDR3 (0x070)
273#define ISPCCDC_FMT_ADDR4 (0x074)
274#define ISPCCDC_FMT_ADDR5 (0x078)
275#define ISPCCDC_FMT_ADDR6 (0x07C)
276#define ISPCCDC_FMT_ADDR7 (0x080)
277#define ISPCCDC_PRGEVEN0 (0x084)
278#define ISPCCDC_PRGEVEN1 (0x088)
279#define ISPCCDC_PRGODD0 (0x08C)
280#define ISPCCDC_PRGODD1 (0x090)
281#define ISPCCDC_VP_OUT (0x094)
282
283#define ISPCCDC_LSC_CONFIG (0x098)
284#define ISPCCDC_LSC_INITIAL (0x09C)
285#define ISPCCDC_LSC_TABLE_BASE (0x0A0)
286#define ISPCCDC_LSC_TABLE_OFFSET (0x0A4)
287
288/* SBL */
289#define ISPSBL_PCR 0x4
290#define ISPSBL_PCR_H3A_AEAWB_WBL_OVF (1 << 16)
291#define ISPSBL_PCR_H3A_AF_WBL_OVF (1 << 17)
292#define ISPSBL_PCR_RSZ4_WBL_OVF (1 << 18)
293#define ISPSBL_PCR_RSZ3_WBL_OVF (1 << 19)
294#define ISPSBL_PCR_RSZ2_WBL_OVF (1 << 20)
295#define ISPSBL_PCR_RSZ1_WBL_OVF (1 << 21)
296#define ISPSBL_PCR_PRV_WBL_OVF (1 << 22)
297#define ISPSBL_PCR_CCDC_WBL_OVF (1 << 23)
298#define ISPSBL_PCR_CCDCPRV_2_RSZ_OVF (1 << 24)
299#define ISPSBL_PCR_CSIA_WBL_OVF (1 << 25)
300#define ISPSBL_PCR_CSIB_WBL_OVF (1 << 26)
301#define ISPSBL_CCDC_WR_0 (0x028)
302#define ISPSBL_CCDC_WR_0_DATA_READY (1 << 21)
303#define ISPSBL_CCDC_WR_1 (0x02C)
304#define ISPSBL_CCDC_WR_2 (0x030)
305#define ISPSBL_CCDC_WR_3 (0x034)
306
307#define ISPSBL_SDR_REQ_EXP 0xF8
308#define ISPSBL_SDR_REQ_HIST_EXP_SHIFT 0
309#define ISPSBL_SDR_REQ_HIST_EXP_MASK (0x3FF)
310#define ISPSBL_SDR_REQ_RSZ_EXP_SHIFT 10
311#define ISPSBL_SDR_REQ_RSZ_EXP_MASK (0x3FF << ISPSBL_SDR_REQ_RSZ_EXP_SHIFT)
312#define ISPSBL_SDR_REQ_PRV_EXP_SHIFT 20
313#define ISPSBL_SDR_REQ_PRV_EXP_MASK (0x3FF << ISPSBL_SDR_REQ_PRV_EXP_SHIFT)
314
315/* Histogram registers */
316#define ISPHIST_PID (0x000)
317#define ISPHIST_PCR (0x004)
318#define ISPHIST_CNT (0x008)
319#define ISPHIST_WB_GAIN (0x00C)
320#define ISPHIST_R0_HORZ (0x010)
321#define ISPHIST_R0_VERT (0x014)
322#define ISPHIST_R1_HORZ (0x018)
323#define ISPHIST_R1_VERT (0x01C)
324#define ISPHIST_R2_HORZ (0x020)
325#define ISPHIST_R2_VERT (0x024)
326#define ISPHIST_R3_HORZ (0x028)
327#define ISPHIST_R3_VERT (0x02C)
328#define ISPHIST_ADDR (0x030)
329#define ISPHIST_DATA (0x034)
330#define ISPHIST_RADD (0x038)
331#define ISPHIST_RADD_OFF (0x03C)
332#define ISPHIST_H_V_INFO (0x040)
333
334/* H3A module registers */
335#define ISPH3A_PID (0x000)
336#define ISPH3A_PCR (0x004)
337#define ISPH3A_AEWWIN1 (0x04C)
338#define ISPH3A_AEWINSTART (0x050)
339#define ISPH3A_AEWINBLK (0x054)
340#define ISPH3A_AEWSUBWIN (0x058)
341#define ISPH3A_AEWBUFST (0x05C)
342#define ISPH3A_AFPAX1 (0x008)
343#define ISPH3A_AFPAX2 (0x00C)
344#define ISPH3A_AFPAXSTART (0x010)
345#define ISPH3A_AFIIRSH (0x014)
346#define ISPH3A_AFBUFST (0x018)
347#define ISPH3A_AFCOEF010 (0x01C)
348#define ISPH3A_AFCOEF032 (0x020)
349#define ISPH3A_AFCOEF054 (0x024)
350#define ISPH3A_AFCOEF076 (0x028)
351#define ISPH3A_AFCOEF098 (0x02C)
352#define ISPH3A_AFCOEF0010 (0x030)
353#define ISPH3A_AFCOEF110 (0x034)
354#define ISPH3A_AFCOEF132 (0x038)
355#define ISPH3A_AFCOEF154 (0x03C)
356#define ISPH3A_AFCOEF176 (0x040)
357#define ISPH3A_AFCOEF198 (0x044)
358#define ISPH3A_AFCOEF1010 (0x048)
359
360#define ISPPRV_PCR (0x004)
361#define ISPPRV_HORZ_INFO (0x008)
362#define ISPPRV_VERT_INFO (0x00C)
363#define ISPPRV_RSDR_ADDR (0x010)
364#define ISPPRV_RADR_OFFSET (0x014)
365#define ISPPRV_DSDR_ADDR (0x018)
366#define ISPPRV_DRKF_OFFSET (0x01C)
367#define ISPPRV_WSDR_ADDR (0x020)
368#define ISPPRV_WADD_OFFSET (0x024)
369#define ISPPRV_AVE (0x028)
370#define ISPPRV_HMED (0x02C)
371#define ISPPRV_NF (0x030)
372#define ISPPRV_WB_DGAIN (0x034)
373#define ISPPRV_WBGAIN (0x038)
374#define ISPPRV_WBSEL (0x03C)
375#define ISPPRV_CFA (0x040)
376#define ISPPRV_BLKADJOFF (0x044)
377#define ISPPRV_RGB_MAT1 (0x048)
378#define ISPPRV_RGB_MAT2 (0x04C)
379#define ISPPRV_RGB_MAT3 (0x050)
380#define ISPPRV_RGB_MAT4 (0x054)
381#define ISPPRV_RGB_MAT5 (0x058)
382#define ISPPRV_RGB_OFF1 (0x05C)
383#define ISPPRV_RGB_OFF2 (0x060)
384#define ISPPRV_CSC0 (0x064)
385#define ISPPRV_CSC1 (0x068)
386#define ISPPRV_CSC2 (0x06C)
387#define ISPPRV_CSC_OFFSET (0x070)
388#define ISPPRV_CNT_BRT (0x074)
389#define ISPPRV_CSUP (0x078)
390#define ISPPRV_SETUP_YC (0x07C)
391#define ISPPRV_SET_TBL_ADDR (0x080)
392#define ISPPRV_SET_TBL_DATA (0x084)
393#define ISPPRV_CDC_THR0 (0x090)
394#define ISPPRV_CDC_THR1 (ISPPRV_CDC_THR0 + (0x4))
395#define ISPPRV_CDC_THR2 (ISPPRV_CDC_THR0 + (0x4) * 2)
396#define ISPPRV_CDC_THR3 (ISPPRV_CDC_THR0 + (0x4) * 3)
397
398#define ISPPRV_REDGAMMA_TABLE_ADDR 0x0000
399#define ISPPRV_GREENGAMMA_TABLE_ADDR 0x0400
400#define ISPPRV_BLUEGAMMA_TABLE_ADDR 0x0800
401#define ISPPRV_NF_TABLE_ADDR 0x0C00
402#define ISPPRV_YENH_TABLE_ADDR 0x1000
403#define ISPPRV_CFA_TABLE_ADDR 0x1400
404
405#define ISPRSZ_MIN_OUTPUT 64
406#define ISPRSZ_MAX_OUTPUT 3312
407
408/* Resizer module register offset */
409#define ISPRSZ_PID (0x000)
410#define ISPRSZ_PCR (0x004)
411#define ISPRSZ_CNT (0x008)
412#define ISPRSZ_OUT_SIZE (0x00C)
413#define ISPRSZ_IN_START (0x010)
414#define ISPRSZ_IN_SIZE (0x014)
415#define ISPRSZ_SDR_INADD (0x018)
416#define ISPRSZ_SDR_INOFF (0x01C)
417#define ISPRSZ_SDR_OUTADD (0x020)
418#define ISPRSZ_SDR_OUTOFF (0x024)
419#define ISPRSZ_HFILT10 (0x028)
420#define ISPRSZ_HFILT32 (0x02C)
421#define ISPRSZ_HFILT54 (0x030)
422#define ISPRSZ_HFILT76 (0x034)
423#define ISPRSZ_HFILT98 (0x038)
424#define ISPRSZ_HFILT1110 (0x03C)
425#define ISPRSZ_HFILT1312 (0x040)
426#define ISPRSZ_HFILT1514 (0x044)
427#define ISPRSZ_HFILT1716 (0x048)
428#define ISPRSZ_HFILT1918 (0x04C)
429#define ISPRSZ_HFILT2120 (0x050)
430#define ISPRSZ_HFILT2322 (0x054)
431#define ISPRSZ_HFILT2524 (0x058)
432#define ISPRSZ_HFILT2726 (0x05C)
433#define ISPRSZ_HFILT2928 (0x060)
434#define ISPRSZ_HFILT3130 (0x064)
435#define ISPRSZ_VFILT10 (0x068)
436#define ISPRSZ_VFILT32 (0x06C)
437#define ISPRSZ_VFILT54 (0x070)
438#define ISPRSZ_VFILT76 (0x074)
439#define ISPRSZ_VFILT98 (0x078)
440#define ISPRSZ_VFILT1110 (0x07C)
441#define ISPRSZ_VFILT1312 (0x080)
442#define ISPRSZ_VFILT1514 (0x084)
443#define ISPRSZ_VFILT1716 (0x088)
444#define ISPRSZ_VFILT1918 (0x08C)
445#define ISPRSZ_VFILT2120 (0x090)
446#define ISPRSZ_VFILT2322 (0x094)
447#define ISPRSZ_VFILT2524 (0x098)
448#define ISPRSZ_VFILT2726 (0x09C)
449#define ISPRSZ_VFILT2928 (0x0A0)
450#define ISPRSZ_VFILT3130 (0x0A4)
451#define ISPRSZ_YENH (0x0A8)
452
453#define ISP_INT_CLR 0xFF113F11
454#define ISPPRV_PCR_EN 1
455#define ISPPRV_PCR_BUSY (1 << 1)
456#define ISPPRV_PCR_SOURCE (1 << 2)
457#define ISPPRV_PCR_ONESHOT (1 << 3)
458#define ISPPRV_PCR_WIDTH (1 << 4)
459#define ISPPRV_PCR_INVALAW (1 << 5)
460#define ISPPRV_PCR_DRKFEN (1 << 6)
461#define ISPPRV_PCR_DRKFCAP (1 << 7)
462#define ISPPRV_PCR_HMEDEN (1 << 8)
463#define ISPPRV_PCR_NFEN (1 << 9)
464#define ISPPRV_PCR_CFAEN (1 << 10)
465#define ISPPRV_PCR_CFAFMT_SHIFT 11
466#define ISPPRV_PCR_CFAFMT_MASK 0x7800
467#define ISPPRV_PCR_CFAFMT_BAYER (0 << 11)
468#define ISPPRV_PCR_CFAFMT_SONYVGA (1 << 11)
469#define ISPPRV_PCR_CFAFMT_RGBFOVEON (2 << 11)
470#define ISPPRV_PCR_CFAFMT_DNSPL (3 << 11)
471#define ISPPRV_PCR_CFAFMT_HONEYCOMB (4 << 11)
472#define ISPPRV_PCR_CFAFMT_RRGGBBFOVEON (5 << 11)
473#define ISPPRV_PCR_YNENHEN (1 << 15)
474#define ISPPRV_PCR_SUPEN (1 << 16)
475#define ISPPRV_PCR_YCPOS_SHIFT 17
476#define ISPPRV_PCR_YCPOS_YCrYCb (0 << 17)
477#define ISPPRV_PCR_YCPOS_YCbYCr (1 << 17)
478#define ISPPRV_PCR_YCPOS_CbYCrY (2 << 17)
479#define ISPPRV_PCR_YCPOS_CrYCbY (3 << 17)
480#define ISPPRV_PCR_RSZPORT (1 << 19)
481#define ISPPRV_PCR_SDRPORT (1 << 20)
482#define ISPPRV_PCR_SCOMP_EN (1 << 21)
483#define ISPPRV_PCR_SCOMP_SFT_SHIFT (22)
484#define ISPPRV_PCR_SCOMP_SFT_MASK (7 << 22)
485#define ISPPRV_PCR_GAMMA_BYPASS (1 << 26)
486#define ISPPRV_PCR_DCOREN (1 << 27)
487#define ISPPRV_PCR_DCCOUP (1 << 28)
488#define ISPPRV_PCR_DRK_FAIL (1 << 31)
489
490#define ISPPRV_HORZ_INFO_EPH_SHIFT 0
491#define ISPPRV_HORZ_INFO_EPH_MASK 0x3fff
492#define ISPPRV_HORZ_INFO_SPH_SHIFT 16
493#define ISPPRV_HORZ_INFO_SPH_MASK 0x3fff0
494
495#define ISPPRV_VERT_INFO_ELV_SHIFT 0
496#define ISPPRV_VERT_INFO_ELV_MASK 0x3fff
497#define ISPPRV_VERT_INFO_SLV_SHIFT 16
498#define ISPPRV_VERT_INFO_SLV_MASK 0x3fff0
499
500#define ISPPRV_AVE_EVENDIST_SHIFT 2
501#define ISPPRV_AVE_EVENDIST_1 0x0
502#define ISPPRV_AVE_EVENDIST_2 0x1
503#define ISPPRV_AVE_EVENDIST_3 0x2
504#define ISPPRV_AVE_EVENDIST_4 0x3
505#define ISPPRV_AVE_ODDDIST_SHIFT 4
506#define ISPPRV_AVE_ODDDIST_1 0x0
507#define ISPPRV_AVE_ODDDIST_2 0x1
508#define ISPPRV_AVE_ODDDIST_3 0x2
509#define ISPPRV_AVE_ODDDIST_4 0x3
510
511#define ISPPRV_HMED_THRESHOLD_SHIFT 0
512#define ISPPRV_HMED_EVENDIST (1 << 8)
513#define ISPPRV_HMED_ODDDIST (1 << 9)
514
515#define ISPPRV_WBGAIN_COEF0_SHIFT 0
516#define ISPPRV_WBGAIN_COEF1_SHIFT 8
517#define ISPPRV_WBGAIN_COEF2_SHIFT 16
518#define ISPPRV_WBGAIN_COEF3_SHIFT 24
519
520#define ISPPRV_WBSEL_COEF0 0x0
521#define ISPPRV_WBSEL_COEF1 0x1
522#define ISPPRV_WBSEL_COEF2 0x2
523#define ISPPRV_WBSEL_COEF3 0x3
524
525#define ISPPRV_WBSEL_N0_0_SHIFT 0
526#define ISPPRV_WBSEL_N0_1_SHIFT 2
527#define ISPPRV_WBSEL_N0_2_SHIFT 4
528#define ISPPRV_WBSEL_N0_3_SHIFT 6
529#define ISPPRV_WBSEL_N1_0_SHIFT 8
530#define ISPPRV_WBSEL_N1_1_SHIFT 10
531#define ISPPRV_WBSEL_N1_2_SHIFT 12
532#define ISPPRV_WBSEL_N1_3_SHIFT 14
533#define ISPPRV_WBSEL_N2_0_SHIFT 16
534#define ISPPRV_WBSEL_N2_1_SHIFT 18
535#define ISPPRV_WBSEL_N2_2_SHIFT 20
536#define ISPPRV_WBSEL_N2_3_SHIFT 22
537#define ISPPRV_WBSEL_N3_0_SHIFT 24
538#define ISPPRV_WBSEL_N3_1_SHIFT 26
539#define ISPPRV_WBSEL_N3_2_SHIFT 28
540#define ISPPRV_WBSEL_N3_3_SHIFT 30
541
542#define ISPPRV_CFA_GRADTH_HOR_SHIFT 0
543#define ISPPRV_CFA_GRADTH_VER_SHIFT 8
544
545#define ISPPRV_BLKADJOFF_B_SHIFT 0
546#define ISPPRV_BLKADJOFF_G_SHIFT 8
547#define ISPPRV_BLKADJOFF_R_SHIFT 16
548
549#define ISPPRV_RGB_MAT1_MTX_RR_SHIFT 0
550#define ISPPRV_RGB_MAT1_MTX_GR_SHIFT 16
551
552#define ISPPRV_RGB_MAT2_MTX_BR_SHIFT 0
553#define ISPPRV_RGB_MAT2_MTX_RG_SHIFT 16
554
555#define ISPPRV_RGB_MAT3_MTX_GG_SHIFT 0
556#define ISPPRV_RGB_MAT3_MTX_BG_SHIFT 16
557
558#define ISPPRV_RGB_MAT4_MTX_RB_SHIFT 0
559#define ISPPRV_RGB_MAT4_MTX_GB_SHIFT 16
560
561#define ISPPRV_RGB_MAT5_MTX_BB_SHIFT 0
562
563#define ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT 0
564#define ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT 16
565
566#define ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT 0
567
568#define ISPPRV_CSC0_RY_SHIFT 0
569#define ISPPRV_CSC0_GY_SHIFT 10
570#define ISPPRV_CSC0_BY_SHIFT 20
571
572#define ISPPRV_CSC1_RCB_SHIFT 0
573#define ISPPRV_CSC1_GCB_SHIFT 10
574#define ISPPRV_CSC1_BCB_SHIFT 20
575
576#define ISPPRV_CSC2_RCR_SHIFT 0
577#define ISPPRV_CSC2_GCR_SHIFT 10
578#define ISPPRV_CSC2_BCR_SHIFT 20
579
580#define ISPPRV_CSC_OFFSET_CR_SHIFT 0
581#define ISPPRV_CSC_OFFSET_CB_SHIFT 8
582#define ISPPRV_CSC_OFFSET_Y_SHIFT 16
583
584#define ISPPRV_CNT_BRT_BRT_SHIFT 0
585#define ISPPRV_CNT_BRT_CNT_SHIFT 8
586
587#define ISPPRV_CONTRAST_MAX 0x10
588#define ISPPRV_CONTRAST_MIN 0xFF
589#define ISPPRV_BRIGHT_MIN 0x00
590#define ISPPRV_BRIGHT_MAX 0xFF
591
592#define ISPPRV_CSUP_CSUPG_SHIFT 0
593#define ISPPRV_CSUP_THRES_SHIFT 8
594#define ISPPRV_CSUP_HPYF_SHIFT 16
595
596#define ISPPRV_SETUP_YC_MINC_SHIFT 0
597#define ISPPRV_SETUP_YC_MAXC_SHIFT 8
598#define ISPPRV_SETUP_YC_MINY_SHIFT 16
599#define ISPPRV_SETUP_YC_MAXY_SHIFT 24
600#define ISPPRV_YC_MAX 0xFF
601#define ISPPRV_YC_MIN 0x0
602
603/* Define bit fields within selected registers */
604#define ISP_REVISION_SHIFT 0
605
606#define ISP_SYSCONFIG_AUTOIDLE (1 << 0)
607#define ISP_SYSCONFIG_SOFTRESET (1 << 1)
608#define ISP_SYSCONFIG_MIDLEMODE_SHIFT 12
609#define ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY 0x0
610#define ISP_SYSCONFIG_MIDLEMODE_NOSTANBY 0x1
611#define ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY 0x2
612
613#define ISP_SYSSTATUS_RESETDONE 0
614
615#define IRQ0ENABLE_CSIA_IRQ (1 << 0)
616#define IRQ0ENABLE_CSIC_IRQ (1 << 1)
617#define IRQ0ENABLE_CCP2_LCM_IRQ (1 << 3)
618#define IRQ0ENABLE_CCP2_LC0_IRQ (1 << 4)
619#define IRQ0ENABLE_CCP2_LC1_IRQ (1 << 5)
620#define IRQ0ENABLE_CCP2_LC2_IRQ (1 << 6)
621#define IRQ0ENABLE_CCP2_LC3_IRQ (1 << 7)
622#define IRQ0ENABLE_CSIB_IRQ (IRQ0ENABLE_CCP2_LCM_IRQ | \
623 IRQ0ENABLE_CCP2_LC0_IRQ | \
624 IRQ0ENABLE_CCP2_LC1_IRQ | \
625 IRQ0ENABLE_CCP2_LC2_IRQ | \
626 IRQ0ENABLE_CCP2_LC3_IRQ)
627
628#define IRQ0ENABLE_CCDC_VD0_IRQ (1 << 8)
629#define IRQ0ENABLE_CCDC_VD1_IRQ (1 << 9)
630#define IRQ0ENABLE_CCDC_VD2_IRQ (1 << 10)
631#define IRQ0ENABLE_CCDC_ERR_IRQ (1 << 11)
632#define IRQ0ENABLE_H3A_AF_DONE_IRQ (1 << 12)
633#define IRQ0ENABLE_H3A_AWB_DONE_IRQ (1 << 13)
634#define IRQ0ENABLE_HIST_DONE_IRQ (1 << 16)
635#define IRQ0ENABLE_CCDC_LSC_DONE_IRQ (1 << 17)
636#define IRQ0ENABLE_CCDC_LSC_PREF_COMP_IRQ (1 << 18)
637#define IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ (1 << 19)
638#define IRQ0ENABLE_PRV_DONE_IRQ (1 << 20)
639#define IRQ0ENABLE_RSZ_DONE_IRQ (1 << 24)
640#define IRQ0ENABLE_OVF_IRQ (1 << 25)
641#define IRQ0ENABLE_PING_IRQ (1 << 26)
642#define IRQ0ENABLE_PONG_IRQ (1 << 27)
643#define IRQ0ENABLE_MMU_ERR_IRQ (1 << 28)
644#define IRQ0ENABLE_OCP_ERR_IRQ (1 << 29)
645#define IRQ0ENABLE_SEC_ERR_IRQ (1 << 30)
646#define IRQ0ENABLE_HS_VS_IRQ (1 << 31)
647
648#define IRQ0STATUS_CSIA_IRQ (1 << 0)
649#define IRQ0STATUS_CSI2C_IRQ (1 << 1)
650#define IRQ0STATUS_CCP2_LCM_IRQ (1 << 3)
651#define IRQ0STATUS_CCP2_LC0_IRQ (1 << 4)
652#define IRQ0STATUS_CSIB_IRQ (IRQ0STATUS_CCP2_LCM_IRQ | \
653 IRQ0STATUS_CCP2_LC0_IRQ)
654
655#define IRQ0STATUS_CSIB_LC1_IRQ (1 << 5)
656#define IRQ0STATUS_CSIB_LC2_IRQ (1 << 6)
657#define IRQ0STATUS_CSIB_LC3_IRQ (1 << 7)
658#define IRQ0STATUS_CCDC_VD0_IRQ (1 << 8)
659#define IRQ0STATUS_CCDC_VD1_IRQ (1 << 9)
660#define IRQ0STATUS_CCDC_VD2_IRQ (1 << 10)
661#define IRQ0STATUS_CCDC_ERR_IRQ (1 << 11)
662#define IRQ0STATUS_H3A_AF_DONE_IRQ (1 << 12)
663#define IRQ0STATUS_H3A_AWB_DONE_IRQ (1 << 13)
664#define IRQ0STATUS_HIST_DONE_IRQ (1 << 16)
665#define IRQ0STATUS_CCDC_LSC_DONE_IRQ (1 << 17)
666#define IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ (1 << 18)
667#define IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ (1 << 19)
668#define IRQ0STATUS_PRV_DONE_IRQ (1 << 20)
669#define IRQ0STATUS_RSZ_DONE_IRQ (1 << 24)
670#define IRQ0STATUS_OVF_IRQ (1 << 25)
671#define IRQ0STATUS_PING_IRQ (1 << 26)
672#define IRQ0STATUS_PONG_IRQ (1 << 27)
673#define IRQ0STATUS_MMU_ERR_IRQ (1 << 28)
674#define IRQ0STATUS_OCP_ERR_IRQ (1 << 29)
675#define IRQ0STATUS_SEC_ERR_IRQ (1 << 30)
676#define IRQ0STATUS_HS_VS_IRQ (1 << 31)
677
678#define TCTRL_GRESET_LEN 0
679
680#define TCTRL_PSTRB_REPLAY_DELAY 0
681#define TCTRL_PSTRB_REPLAY_COUNTER_SHIFT 25
682
683#define ISPCTRL_PAR_SER_CLK_SEL_PARALLEL 0x0
684#define ISPCTRL_PAR_SER_CLK_SEL_CSIA 0x1
685#define ISPCTRL_PAR_SER_CLK_SEL_CSIB 0x2
686#define ISPCTRL_PAR_SER_CLK_SEL_CSIC 0x3
687#define ISPCTRL_PAR_SER_CLK_SEL_MASK 0x3
688
689#define ISPCTRL_PAR_BRIDGE_SHIFT 2
690#define ISPCTRL_PAR_BRIDGE_DISABLE (0x0 << 2)
691#define ISPCTRL_PAR_BRIDGE_LENDIAN (0x2 << 2)
692#define ISPCTRL_PAR_BRIDGE_BENDIAN (0x3 << 2)
693#define ISPCTRL_PAR_BRIDGE_MASK (0x3 << 2)
694
695#define ISPCTRL_PAR_CLK_POL_SHIFT 4
696#define ISPCTRL_PAR_CLK_POL_INV (1 << 4)
697#define ISPCTRL_PING_PONG_EN (1 << 5)
698#define ISPCTRL_SHIFT_SHIFT 6
699#define ISPCTRL_SHIFT_0 (0x0 << 6)
700#define ISPCTRL_SHIFT_2 (0x1 << 6)
701#define ISPCTRL_SHIFT_4 (0x2 << 6)
702#define ISPCTRL_SHIFT_MASK (0x3 << 6)
703
704#define ISPCTRL_CCDC_CLK_EN (1 << 8)
705#define ISPCTRL_SCMP_CLK_EN (1 << 9)
706#define ISPCTRL_H3A_CLK_EN (1 << 10)
707#define ISPCTRL_HIST_CLK_EN (1 << 11)
708#define ISPCTRL_PREV_CLK_EN (1 << 12)
709#define ISPCTRL_RSZ_CLK_EN (1 << 13)
710#define ISPCTRL_SYNC_DETECT_SHIFT 14
711#define ISPCTRL_SYNC_DETECT_HSFALL (0x0 << ISPCTRL_SYNC_DETECT_SHIFT)
712#define ISPCTRL_SYNC_DETECT_HSRISE (0x1 << ISPCTRL_SYNC_DETECT_SHIFT)
713#define ISPCTRL_SYNC_DETECT_VSFALL (0x2 << ISPCTRL_SYNC_DETECT_SHIFT)
714#define ISPCTRL_SYNC_DETECT_VSRISE (0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
715#define ISPCTRL_SYNC_DETECT_MASK (0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
716
717#define ISPCTRL_CCDC_RAM_EN (1 << 16)
718#define ISPCTRL_PREV_RAM_EN (1 << 17)
719#define ISPCTRL_SBL_RD_RAM_EN (1 << 18)
720#define ISPCTRL_SBL_WR1_RAM_EN (1 << 19)
721#define ISPCTRL_SBL_WR0_RAM_EN (1 << 20)
722#define ISPCTRL_SBL_AUTOIDLE (1 << 21)
723#define ISPCTRL_SBL_SHARED_WPORTC (1 << 26)
724#define ISPCTRL_SBL_SHARED_RPORTA (1 << 27)
725#define ISPCTRL_SBL_SHARED_RPORTB (1 << 28)
726#define ISPCTRL_JPEG_FLUSH (1 << 30)
727#define ISPCTRL_CCDC_FLUSH (1 << 31)
728
729#define ISPSECURE_SECUREMODE 0
730
731#define ISPTCTRL_CTRL_DIV_LOW 0x0
732#define ISPTCTRL_CTRL_DIV_HIGH 0x1
733#define ISPTCTRL_CTRL_DIV_BYPASS 0x1F
734
735#define ISPTCTRL_CTRL_DIVA_SHIFT 0
736#define ISPTCTRL_CTRL_DIVA_MASK (0x1F << ISPTCTRL_CTRL_DIVA_SHIFT)
737
738#define ISPTCTRL_CTRL_DIVB_SHIFT 5
739#define ISPTCTRL_CTRL_DIVB_MASK (0x1F << ISPTCTRL_CTRL_DIVB_SHIFT)
740
741#define ISPTCTRL_CTRL_DIVC_SHIFT 10
742#define ISPTCTRL_CTRL_DIVC_NOCLOCK (0x0 << 10)
743
744#define ISPTCTRL_CTRL_SHUTEN (1 << 21)
745#define ISPTCTRL_CTRL_PSTRBEN (1 << 22)
746#define ISPTCTRL_CTRL_STRBEN (1 << 23)
747#define ISPTCTRL_CTRL_SHUTPOL (1 << 24)
748#define ISPTCTRL_CTRL_STRBPSTRBPOL (1 << 26)
749
750#define ISPTCTRL_CTRL_INSEL_SHIFT 27
751#define ISPTCTRL_CTRL_INSEL_PARALLEL (0x0 << 27)
752#define ISPTCTRL_CTRL_INSEL_CSIA (0x1 << 27)
753#define ISPTCTRL_CTRL_INSEL_CSIB (0x2 << 27)
754
755#define ISPTCTRL_CTRL_GRESETEn (1 << 29)
756#define ISPTCTRL_CTRL_GRESETPOL (1 << 30)
757#define ISPTCTRL_CTRL_GRESETDIR (1 << 31)
758
759#define ISPTCTRL_FRAME_SHUT_SHIFT 0
760#define ISPTCTRL_FRAME_PSTRB_SHIFT 6
761#define ISPTCTRL_FRAME_STRB_SHIFT 12
762
763#define ISPCCDC_PID_PREV_SHIFT 0
764#define ISPCCDC_PID_CID_SHIFT 8
765#define ISPCCDC_PID_TID_SHIFT 16
766
767#define ISPCCDC_PCR_EN 1
768#define ISPCCDC_PCR_BUSY (1 << 1)
769
770#define ISPCCDC_SYN_MODE_VDHDOUT 0x1
771#define ISPCCDC_SYN_MODE_FLDOUT (1 << 1)
772#define ISPCCDC_SYN_MODE_VDPOL (1 << 2)
773#define ISPCCDC_SYN_MODE_HDPOL (1 << 3)
774#define ISPCCDC_SYN_MODE_FLDPOL (1 << 4)
775#define ISPCCDC_SYN_MODE_EXWEN (1 << 5)
776#define ISPCCDC_SYN_MODE_DATAPOL (1 << 6)
777#define ISPCCDC_SYN_MODE_FLDMODE (1 << 7)
778#define ISPCCDC_SYN_MODE_DATSIZ_MASK (0x7 << 8)
779#define ISPCCDC_SYN_MODE_DATSIZ_8_16 (0x0 << 8)
780#define ISPCCDC_SYN_MODE_DATSIZ_12 (0x4 << 8)
781#define ISPCCDC_SYN_MODE_DATSIZ_11 (0x5 << 8)
782#define ISPCCDC_SYN_MODE_DATSIZ_10 (0x6 << 8)
783#define ISPCCDC_SYN_MODE_DATSIZ_8 (0x7 << 8)
784#define ISPCCDC_SYN_MODE_PACK8 (1 << 11)
785#define ISPCCDC_SYN_MODE_INPMOD_MASK (3 << 12)
786#define ISPCCDC_SYN_MODE_INPMOD_RAW (0 << 12)
787#define ISPCCDC_SYN_MODE_INPMOD_YCBCR16 (1 << 12)
788#define ISPCCDC_SYN_MODE_INPMOD_YCBCR8 (2 << 12)
789#define ISPCCDC_SYN_MODE_LPF (1 << 14)
790#define ISPCCDC_SYN_MODE_FLDSTAT (1 << 15)
791#define ISPCCDC_SYN_MODE_VDHDEN (1 << 16)
792#define ISPCCDC_SYN_MODE_WEN (1 << 17)
793#define ISPCCDC_SYN_MODE_VP2SDR (1 << 18)
794#define ISPCCDC_SYN_MODE_SDR2RSZ (1 << 19)
795
796#define ISPCCDC_HD_VD_WID_VDW_SHIFT 0
797#define ISPCCDC_HD_VD_WID_HDW_SHIFT 16
798
799#define ISPCCDC_PIX_LINES_HLPRF_SHIFT 0
800#define ISPCCDC_PIX_LINES_PPLN_SHIFT 16
801
802#define ISPCCDC_HORZ_INFO_NPH_SHIFT 0
803#define ISPCCDC_HORZ_INFO_NPH_MASK 0x00007fff
804#define ISPCCDC_HORZ_INFO_SPH_SHIFT 16
805#define ISPCCDC_HORZ_INFO_SPH_MASK 0x7fff0000
806
807#define ISPCCDC_VERT_START_SLV1_SHIFT 0
808#define ISPCCDC_VERT_START_SLV0_SHIFT 16
809#define ISPCCDC_VERT_START_SLV0_MASK 0x7fff0000
810
811#define ISPCCDC_VERT_LINES_NLV_SHIFT 0
812#define ISPCCDC_VERT_LINES_NLV_MASK 0x00007fff
813
814#define ISPCCDC_CULLING_CULV_SHIFT 0
815#define ISPCCDC_CULLING_CULHODD_SHIFT 16
816#define ISPCCDC_CULLING_CULHEVN_SHIFT 24
817
818#define ISPCCDC_HSIZE_OFF_SHIFT 0
819
820#define ISPCCDC_SDOFST_FINV (1 << 14)
821#define ISPCCDC_SDOFST_FOFST_1L 0
822#define ISPCCDC_SDOFST_FOFST_4L (3 << 12)
823#define ISPCCDC_SDOFST_LOFST3_SHIFT 0
824#define ISPCCDC_SDOFST_LOFST2_SHIFT 3
825#define ISPCCDC_SDOFST_LOFST1_SHIFT 6
826#define ISPCCDC_SDOFST_LOFST0_SHIFT 9
827#define EVENEVEN 1
828#define ODDEVEN 2
829#define EVENODD 3
830#define ODDODD 4
831
832#define ISPCCDC_CLAMP_OBGAIN_SHIFT 0
833#define ISPCCDC_CLAMP_OBST_SHIFT 10
834#define ISPCCDC_CLAMP_OBSLN_SHIFT 25
835#define ISPCCDC_CLAMP_OBSLEN_SHIFT 28
836#define ISPCCDC_CLAMP_CLAMPEN (1 << 31)
837
838#define ISPCCDC_COLPTN_R_Ye 0x0
839#define ISPCCDC_COLPTN_Gr_Cy 0x1
840#define ISPCCDC_COLPTN_Gb_G 0x2
841#define ISPCCDC_COLPTN_B_Mg 0x3
842#define ISPCCDC_COLPTN_CP0PLC0_SHIFT 0
843#define ISPCCDC_COLPTN_CP0PLC1_SHIFT 2
844#define ISPCCDC_COLPTN_CP0PLC2_SHIFT 4
845#define ISPCCDC_COLPTN_CP0PLC3_SHIFT 6
846#define ISPCCDC_COLPTN_CP1PLC0_SHIFT 8
847#define ISPCCDC_COLPTN_CP1PLC1_SHIFT 10
848#define ISPCCDC_COLPTN_CP1PLC2_SHIFT 12
849#define ISPCCDC_COLPTN_CP1PLC3_SHIFT 14
850#define ISPCCDC_COLPTN_CP2PLC0_SHIFT 16
851#define ISPCCDC_COLPTN_CP2PLC1_SHIFT 18
852#define ISPCCDC_COLPTN_CP2PLC2_SHIFT 20
853#define ISPCCDC_COLPTN_CP2PLC3_SHIFT 22
854#define ISPCCDC_COLPTN_CP3PLC0_SHIFT 24
855#define ISPCCDC_COLPTN_CP3PLC1_SHIFT 26
856#define ISPCCDC_COLPTN_CP3PLC2_SHIFT 28
857#define ISPCCDC_COLPTN_CP3PLC3_SHIFT 30
858
859#define ISPCCDC_BLKCMP_B_MG_SHIFT 0
860#define ISPCCDC_BLKCMP_GB_G_SHIFT 8
861#define ISPCCDC_BLKCMP_GR_CY_SHIFT 16
862#define ISPCCDC_BLKCMP_R_YE_SHIFT 24
863
864#define ISPCCDC_FPC_FPNUM_SHIFT 0
865#define ISPCCDC_FPC_FPCEN (1 << 15)
866#define ISPCCDC_FPC_FPERR (1 << 16)
867
868#define ISPCCDC_VDINT_1_SHIFT 0
869#define ISPCCDC_VDINT_1_MASK 0x00007fff
870#define ISPCCDC_VDINT_0_SHIFT 16
871#define ISPCCDC_VDINT_0_MASK 0x7fff0000
872
873#define ISPCCDC_ALAW_GWDI_12_3 (0x3 << 0)
874#define ISPCCDC_ALAW_GWDI_11_2 (0x4 << 0)
875#define ISPCCDC_ALAW_GWDI_10_1 (0x5 << 0)
876#define ISPCCDC_ALAW_GWDI_9_0 (0x6 << 0)
877#define ISPCCDC_ALAW_CCDTBL (1 << 3)
878
879#define ISPCCDC_REC656IF_R656ON 1
880#define ISPCCDC_REC656IF_ECCFVH (1 << 1)
881
882#define ISPCCDC_CFG_BW656 (1 << 5)
883#define ISPCCDC_CFG_FIDMD_SHIFT 6
884#define ISPCCDC_CFG_WENLOG (1 << 8)
885#define ISPCCDC_CFG_WENLOG_AND (0 << 8)
886#define ISPCCDC_CFG_WENLOG_OR (1 << 8)
887#define ISPCCDC_CFG_Y8POS (1 << 11)
888#define ISPCCDC_CFG_BSWD (1 << 12)
889#define ISPCCDC_CFG_MSBINVI (1 << 13)
890#define ISPCCDC_CFG_VDLC (1 << 15)
891
892#define ISPCCDC_FMTCFG_FMTEN 0x1
893#define ISPCCDC_FMTCFG_LNALT (1 << 1)
894#define ISPCCDC_FMTCFG_LNUM_SHIFT 2
895#define ISPCCDC_FMTCFG_PLEN_ODD_SHIFT 4
896#define ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT 8
897#define ISPCCDC_FMTCFG_VPIN_MASK 0x00007000
898#define ISPCCDC_FMTCFG_VPIN_12_3 (0x3 << 12)
899#define ISPCCDC_FMTCFG_VPIN_11_2 (0x4 << 12)
900#define ISPCCDC_FMTCFG_VPIN_10_1 (0x5 << 12)
901#define ISPCCDC_FMTCFG_VPIN_9_0 (0x6 << 12)
902#define ISPCCDC_FMTCFG_VPEN (1 << 15)
903
904#define ISPCCDC_FMTCFG_VPIF_FRQ_MASK 0x003f0000
905#define ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT 16
906#define ISPCCDC_FMTCFG_VPIF_FRQ_BY2 (0x0 << 16)
907#define ISPCCDC_FMTCFG_VPIF_FRQ_BY3 (0x1 << 16)
908#define ISPCCDC_FMTCFG_VPIF_FRQ_BY4 (0x2 << 16)
909#define ISPCCDC_FMTCFG_VPIF_FRQ_BY5 (0x3 << 16)
910#define ISPCCDC_FMTCFG_VPIF_FRQ_BY6 (0x4 << 16)
911
912#define ISPCCDC_FMT_HORZ_FMTLNH_SHIFT 0
913#define ISPCCDC_FMT_HORZ_FMTSPH_SHIFT 16
914
915#define ISPCCDC_FMT_VERT_FMTLNV_SHIFT 0
916#define ISPCCDC_FMT_VERT_FMTSLV_SHIFT 16
917
918#define ISPCCDC_FMT_HORZ_FMTSPH_MASK 0x1fff0000
919#define ISPCCDC_FMT_HORZ_FMTLNH_MASK 0x00001fff
920
921#define ISPCCDC_FMT_VERT_FMTSLV_MASK 0x1fff0000
922#define ISPCCDC_FMT_VERT_FMTLNV_MASK 0x00001fff
923
924#define ISPCCDC_VP_OUT_HORZ_ST_SHIFT 0
925#define ISPCCDC_VP_OUT_HORZ_NUM_SHIFT 4
926#define ISPCCDC_VP_OUT_VERT_NUM_SHIFT 17
927
928#define ISPRSZ_PID_PREV_SHIFT 0
929#define ISPRSZ_PID_CID_SHIFT 8
930#define ISPRSZ_PID_TID_SHIFT 16
931
932#define ISPRSZ_PCR_ENABLE (1 << 0)
933#define ISPRSZ_PCR_BUSY (1 << 1)
934#define ISPRSZ_PCR_ONESHOT (1 << 2)
935
936#define ISPRSZ_CNT_HRSZ_SHIFT 0
937#define ISPRSZ_CNT_HRSZ_MASK \
938 (0x3FF << ISPRSZ_CNT_HRSZ_SHIFT)
939#define ISPRSZ_CNT_VRSZ_SHIFT 10
940#define ISPRSZ_CNT_VRSZ_MASK \
941 (0x3FF << ISPRSZ_CNT_VRSZ_SHIFT)
942#define ISPRSZ_CNT_HSTPH_SHIFT 20
943#define ISPRSZ_CNT_HSTPH_MASK (0x7 << ISPRSZ_CNT_HSTPH_SHIFT)
944#define ISPRSZ_CNT_VSTPH_SHIFT 23
945#define ISPRSZ_CNT_VSTPH_MASK (0x7 << ISPRSZ_CNT_VSTPH_SHIFT)
946#define ISPRSZ_CNT_YCPOS (1 << 26)
947#define ISPRSZ_CNT_INPTYP (1 << 27)
948#define ISPRSZ_CNT_INPSRC (1 << 28)
949#define ISPRSZ_CNT_CBILIN (1 << 29)
950
951#define ISPRSZ_OUT_SIZE_HORZ_SHIFT 0
952#define ISPRSZ_OUT_SIZE_HORZ_MASK \
953 (0xFFF << ISPRSZ_OUT_SIZE_HORZ_SHIFT)
954#define ISPRSZ_OUT_SIZE_VERT_SHIFT 16
955#define ISPRSZ_OUT_SIZE_VERT_MASK \
956 (0xFFF << ISPRSZ_OUT_SIZE_VERT_SHIFT)
957
958#define ISPRSZ_IN_START_HORZ_ST_SHIFT 0
959#define ISPRSZ_IN_START_HORZ_ST_MASK \
960 (0x1FFF << ISPRSZ_IN_START_HORZ_ST_SHIFT)
961#define ISPRSZ_IN_START_VERT_ST_SHIFT 16
962#define ISPRSZ_IN_START_VERT_ST_MASK \
963 (0x1FFF << ISPRSZ_IN_START_VERT_ST_SHIFT)
964
965#define ISPRSZ_IN_SIZE_HORZ_SHIFT 0
966#define ISPRSZ_IN_SIZE_HORZ_MASK \
967 (0x1FFF << ISPRSZ_IN_SIZE_HORZ_SHIFT)
968#define ISPRSZ_IN_SIZE_VERT_SHIFT 16
969#define ISPRSZ_IN_SIZE_VERT_MASK \
970 (0x1FFF << ISPRSZ_IN_SIZE_VERT_SHIFT)
971
972#define ISPRSZ_SDR_INADD_ADDR_SHIFT 0
973#define ISPRSZ_SDR_INADD_ADDR_MASK 0xFFFFFFFF
974
975#define ISPRSZ_SDR_INOFF_OFFSET_SHIFT 0
976#define ISPRSZ_SDR_INOFF_OFFSET_MASK \
977 (0xFFFF << ISPRSZ_SDR_INOFF_OFFSET_SHIFT)
978
979#define ISPRSZ_SDR_OUTADD_ADDR_SHIFT 0
980#define ISPRSZ_SDR_OUTADD_ADDR_MASK 0xFFFFFFFF
981
982
983#define ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT 0
984#define ISPRSZ_SDR_OUTOFF_OFFSET_MASK \
985 (0xFFFF << ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT)
986
987#define ISPRSZ_HFILT_COEF0_SHIFT 0
988#define ISPRSZ_HFILT_COEF0_MASK \
989 (0x3FF << ISPRSZ_HFILT_COEF0_SHIFT)
990#define ISPRSZ_HFILT_COEF1_SHIFT 16
991#define ISPRSZ_HFILT_COEF1_MASK \
992 (0x3FF << ISPRSZ_HFILT_COEF1_SHIFT)
993
994#define ISPRSZ_HFILT32_COEF2_SHIFT 0
995#define ISPRSZ_HFILT32_COEF2_MASK 0x3FF
996#define ISPRSZ_HFILT32_COEF3_SHIFT 16
997#define ISPRSZ_HFILT32_COEF3_MASK 0x3FF0000
998
999#define ISPRSZ_HFILT54_COEF4_SHIFT 0
1000#define ISPRSZ_HFILT54_COEF4_MASK 0x3FF
1001#define ISPRSZ_HFILT54_COEF5_SHIFT 16
1002#define ISPRSZ_HFILT54_COEF5_MASK 0x3FF0000
1003
1004#define ISPRSZ_HFILT76_COEFF6_SHIFT 0
1005#define ISPRSZ_HFILT76_COEFF6_MASK 0x3FF
1006#define ISPRSZ_HFILT76_COEFF7_SHIFT 16
1007#define ISPRSZ_HFILT76_COEFF7_MASK 0x3FF0000
1008
1009#define ISPRSZ_HFILT98_COEFF8_SHIFT 0
1010#define ISPRSZ_HFILT98_COEFF8_MASK 0x3FF
1011#define ISPRSZ_HFILT98_COEFF9_SHIFT 16
1012#define ISPRSZ_HFILT98_COEFF9_MASK 0x3FF0000
1013
1014#define ISPRSZ_HFILT1110_COEF10_SHIFT 0
1015#define ISPRSZ_HFILT1110_COEF10_MASK 0x3FF
1016#define ISPRSZ_HFILT1110_COEF11_SHIFT 16
1017#define ISPRSZ_HFILT1110_COEF11_MASK 0x3FF0000
1018
1019#define ISPRSZ_HFILT1312_COEFF12_SHIFT 0
1020#define ISPRSZ_HFILT1312_COEFF12_MASK 0x3FF
1021#define ISPRSZ_HFILT1312_COEFF13_SHIFT 16
1022#define ISPRSZ_HFILT1312_COEFF13_MASK 0x3FF0000
1023
1024#define ISPRSZ_HFILT1514_COEFF14_SHIFT 0
1025#define ISPRSZ_HFILT1514_COEFF14_MASK 0x3FF
1026#define ISPRSZ_HFILT1514_COEFF15_SHIFT 16
1027#define ISPRSZ_HFILT1514_COEFF15_MASK 0x3FF0000
1028
1029#define ISPRSZ_HFILT1716_COEF16_SHIFT 0
1030#define ISPRSZ_HFILT1716_COEF16_MASK 0x3FF
1031#define ISPRSZ_HFILT1716_COEF17_SHIFT 16
1032#define ISPRSZ_HFILT1716_COEF17_MASK 0x3FF0000
1033
1034#define ISPRSZ_HFILT1918_COEF18_SHIFT 0
1035#define ISPRSZ_HFILT1918_COEF18_MASK 0x3FF
1036#define ISPRSZ_HFILT1918_COEF19_SHIFT 16
1037#define ISPRSZ_HFILT1918_COEF19_MASK 0x3FF0000
1038
1039#define ISPRSZ_HFILT2120_COEF20_SHIFT 0
1040#define ISPRSZ_HFILT2120_COEF20_MASK 0x3FF
1041#define ISPRSZ_HFILT2120_COEF21_SHIFT 16
1042#define ISPRSZ_HFILT2120_COEF21_MASK 0x3FF0000
1043
1044#define ISPRSZ_HFILT2322_COEF22_SHIFT 0
1045#define ISPRSZ_HFILT2322_COEF22_MASK 0x3FF
1046#define ISPRSZ_HFILT2322_COEF23_SHIFT 16
1047#define ISPRSZ_HFILT2322_COEF23_MASK 0x3FF0000
1048
1049#define ISPRSZ_HFILT2524_COEF24_SHIFT 0
1050#define ISPRSZ_HFILT2524_COEF24_MASK 0x3FF
1051#define ISPRSZ_HFILT2524_COEF25_SHIFT 16
1052#define ISPRSZ_HFILT2524_COEF25_MASK 0x3FF0000
1053
1054#define ISPRSZ_HFILT2726_COEF26_SHIFT 0
1055#define ISPRSZ_HFILT2726_COEF26_MASK 0x3FF
1056#define ISPRSZ_HFILT2726_COEF27_SHIFT 16
1057#define ISPRSZ_HFILT2726_COEF27_MASK 0x3FF0000
1058
1059#define ISPRSZ_HFILT2928_COEF28_SHIFT 0
1060#define ISPRSZ_HFILT2928_COEF28_MASK 0x3FF
1061#define ISPRSZ_HFILT2928_COEF29_SHIFT 16
1062#define ISPRSZ_HFILT2928_COEF29_MASK 0x3FF0000
1063
1064#define ISPRSZ_HFILT3130_COEF30_SHIFT 0
1065#define ISPRSZ_HFILT3130_COEF30_MASK 0x3FF
1066#define ISPRSZ_HFILT3130_COEF31_SHIFT 16
1067#define ISPRSZ_HFILT3130_COEF31_MASK 0x3FF0000
1068
1069#define ISPRSZ_VFILT_COEF0_SHIFT 0
1070#define ISPRSZ_VFILT_COEF0_MASK \
1071 (0x3FF << ISPRSZ_VFILT_COEF0_SHIFT)
1072#define ISPRSZ_VFILT_COEF1_SHIFT 16
1073#define ISPRSZ_VFILT_COEF1_MASK \
1074 (0x3FF << ISPRSZ_VFILT_COEF1_SHIFT)
1075
1076#define ISPRSZ_VFILT10_COEF0_SHIFT 0
1077#define ISPRSZ_VFILT10_COEF0_MASK 0x3FF
1078#define ISPRSZ_VFILT10_COEF1_SHIFT 16
1079#define ISPRSZ_VFILT10_COEF1_MASK 0x3FF0000
1080
1081#define ISPRSZ_VFILT32_COEF2_SHIFT 0
1082#define ISPRSZ_VFILT32_COEF2_MASK 0x3FF
1083#define ISPRSZ_VFILT32_COEF3_SHIFT 16
1084#define ISPRSZ_VFILT32_COEF3_MASK 0x3FF0000
1085
1086#define ISPRSZ_VFILT54_COEF4_SHIFT 0
1087#define ISPRSZ_VFILT54_COEF4_MASK 0x3FF
1088#define ISPRSZ_VFILT54_COEF5_SHIFT 16
1089#define ISPRSZ_VFILT54_COEF5_MASK 0x3FF0000
1090
1091#define ISPRSZ_VFILT76_COEFF6_SHIFT 0
1092#define ISPRSZ_VFILT76_COEFF6_MASK 0x3FF
1093#define ISPRSZ_VFILT76_COEFF7_SHIFT 16
1094#define ISPRSZ_VFILT76_COEFF7_MASK 0x3FF0000
1095
1096#define ISPRSZ_VFILT98_COEFF8_SHIFT 0
1097#define ISPRSZ_VFILT98_COEFF8_MASK 0x3FF
1098#define ISPRSZ_VFILT98_COEFF9_SHIFT 16
1099#define ISPRSZ_VFILT98_COEFF9_MASK 0x3FF0000
1100
1101#define ISPRSZ_VFILT1110_COEF10_SHIFT 0
1102#define ISPRSZ_VFILT1110_COEF10_MASK 0x3FF
1103#define ISPRSZ_VFILT1110_COEF11_SHIFT 16
1104#define ISPRSZ_VFILT1110_COEF11_MASK 0x3FF0000
1105
1106#define ISPRSZ_VFILT1312_COEFF12_SHIFT 0
1107#define ISPRSZ_VFILT1312_COEFF12_MASK 0x3FF
1108#define ISPRSZ_VFILT1312_COEFF13_SHIFT 16
1109#define ISPRSZ_VFILT1312_COEFF13_MASK 0x3FF0000
1110
1111#define ISPRSZ_VFILT1514_COEFF14_SHIFT 0
1112#define ISPRSZ_VFILT1514_COEFF14_MASK 0x3FF
1113#define ISPRSZ_VFILT1514_COEFF15_SHIFT 16
1114#define ISPRSZ_VFILT1514_COEFF15_MASK 0x3FF0000
1115
1116#define ISPRSZ_VFILT1716_COEF16_SHIFT 0
1117#define ISPRSZ_VFILT1716_COEF16_MASK 0x3FF
1118#define ISPRSZ_VFILT1716_COEF17_SHIFT 16
1119#define ISPRSZ_VFILT1716_COEF17_MASK 0x3FF0000
1120
1121#define ISPRSZ_VFILT1918_COEF18_SHIFT 0
1122#define ISPRSZ_VFILT1918_COEF18_MASK 0x3FF
1123#define ISPRSZ_VFILT1918_COEF19_SHIFT 16
1124#define ISPRSZ_VFILT1918_COEF19_MASK 0x3FF0000
1125
1126#define ISPRSZ_VFILT2120_COEF20_SHIFT 0
1127#define ISPRSZ_VFILT2120_COEF20_MASK 0x3FF
1128#define ISPRSZ_VFILT2120_COEF21_SHIFT 16
1129#define ISPRSZ_VFILT2120_COEF21_MASK 0x3FF0000
1130
1131#define ISPRSZ_VFILT2322_COEF22_SHIFT 0
1132#define ISPRSZ_VFILT2322_COEF22_MASK 0x3FF
1133#define ISPRSZ_VFILT2322_COEF23_SHIFT 16
1134#define ISPRSZ_VFILT2322_COEF23_MASK 0x3FF0000
1135
1136#define ISPRSZ_VFILT2524_COEF24_SHIFT 0
1137#define ISPRSZ_VFILT2524_COEF24_MASK 0x3FF
1138#define ISPRSZ_VFILT2524_COEF25_SHIFT 16
1139#define ISPRSZ_VFILT2524_COEF25_MASK 0x3FF0000
1140
1141#define ISPRSZ_VFILT2726_COEF26_SHIFT 0
1142#define ISPRSZ_VFILT2726_COEF26_MASK 0x3FF
1143#define ISPRSZ_VFILT2726_COEF27_SHIFT 16
1144#define ISPRSZ_VFILT2726_COEF27_MASK 0x3FF0000
1145
1146#define ISPRSZ_VFILT2928_COEF28_SHIFT 0
1147#define ISPRSZ_VFILT2928_COEF28_MASK 0x3FF
1148#define ISPRSZ_VFILT2928_COEF29_SHIFT 16
1149#define ISPRSZ_VFILT2928_COEF29_MASK 0x3FF0000
1150
1151#define ISPRSZ_VFILT3130_COEF30_SHIFT 0
1152#define ISPRSZ_VFILT3130_COEF30_MASK 0x3FF
1153#define ISPRSZ_VFILT3130_COEF31_SHIFT 16
1154#define ISPRSZ_VFILT3130_COEF31_MASK 0x3FF0000
1155
1156#define ISPRSZ_YENH_CORE_SHIFT 0
1157#define ISPRSZ_YENH_CORE_MASK \
1158 (0xFF << ISPRSZ_YENH_CORE_SHIFT)
1159#define ISPRSZ_YENH_SLOP_SHIFT 8
1160#define ISPRSZ_YENH_SLOP_MASK \
1161 (0xF << ISPRSZ_YENH_SLOP_SHIFT)
1162#define ISPRSZ_YENH_GAIN_SHIFT 12
1163#define ISPRSZ_YENH_GAIN_MASK \
1164 (0xF << ISPRSZ_YENH_GAIN_SHIFT)
1165#define ISPRSZ_YENH_ALGO_SHIFT 16
1166#define ISPRSZ_YENH_ALGO_MASK \
1167 (0x3 << ISPRSZ_YENH_ALGO_SHIFT)
1168
1169#define ISPH3A_PCR_AEW_ALAW_EN_SHIFT 1
1170#define ISPH3A_PCR_AF_MED_TH_SHIFT 3
1171#define ISPH3A_PCR_AF_RGBPOS_SHIFT 11
1172#define ISPH3A_PCR_AEW_AVE2LMT_SHIFT 22
1173#define ISPH3A_PCR_AEW_AVE2LMT_MASK 0xFFC00000
1174#define ISPH3A_PCR_BUSYAF (1 << 15)
1175#define ISPH3A_PCR_BUSYAEAWB (1 << 18)
1176
1177#define ISPH3A_AEWWIN1_WINHC_SHIFT 0
1178#define ISPH3A_AEWWIN1_WINHC_MASK 0x3F
1179#define ISPH3A_AEWWIN1_WINVC_SHIFT 6
1180#define ISPH3A_AEWWIN1_WINVC_MASK 0x1FC0
1181#define ISPH3A_AEWWIN1_WINW_SHIFT 13
1182#define ISPH3A_AEWWIN1_WINW_MASK 0xFE000
1183#define ISPH3A_AEWWIN1_WINH_SHIFT 24
1184#define ISPH3A_AEWWIN1_WINH_MASK 0x7F000000
1185
1186#define ISPH3A_AEWINSTART_WINSH_SHIFT 0
1187#define ISPH3A_AEWINSTART_WINSH_MASK 0x0FFF
1188#define ISPH3A_AEWINSTART_WINSV_SHIFT 16
1189#define ISPH3A_AEWINSTART_WINSV_MASK 0x0FFF0000
1190
1191#define ISPH3A_AEWINBLK_WINH_SHIFT 0
1192#define ISPH3A_AEWINBLK_WINH_MASK 0x7F
1193#define ISPH3A_AEWINBLK_WINSV_SHIFT 16
1194#define ISPH3A_AEWINBLK_WINSV_MASK 0x0FFF0000
1195
1196#define ISPH3A_AEWSUBWIN_AEWINCH_SHIFT 0
1197#define ISPH3A_AEWSUBWIN_AEWINCH_MASK 0x0F
1198#define ISPH3A_AEWSUBWIN_AEWINCV_SHIFT 8
1199#define ISPH3A_AEWSUBWIN_AEWINCV_MASK 0x0F00
1200
1201#define ISPHIST_PCR_ENABLE_SHIFT 0
1202#define ISPHIST_PCR_ENABLE_MASK 0x01
1203#define ISPHIST_PCR_ENABLE (1 << ISPHIST_PCR_ENABLE_SHIFT)
1204#define ISPHIST_PCR_BUSY 0x02
1205
1206#define ISPHIST_CNT_DATASIZE_SHIFT 8
1207#define ISPHIST_CNT_DATASIZE_MASK 0x0100
1208#define ISPHIST_CNT_CLEAR_SHIFT 7
1209#define ISPHIST_CNT_CLEAR_MASK 0x080
1210#define ISPHIST_CNT_CLEAR (1 << ISPHIST_CNT_CLEAR_SHIFT)
1211#define ISPHIST_CNT_CFA_SHIFT 6
1212#define ISPHIST_CNT_CFA_MASK 0x040
1213#define ISPHIST_CNT_BINS_SHIFT 4
1214#define ISPHIST_CNT_BINS_MASK 0x030
1215#define ISPHIST_CNT_SOURCE_SHIFT 3
1216#define ISPHIST_CNT_SOURCE_MASK 0x08
1217#define ISPHIST_CNT_SHIFT_SHIFT 0
1218#define ISPHIST_CNT_SHIFT_MASK 0x07
1219
1220#define ISPHIST_WB_GAIN_WG00_SHIFT 24
1221#define ISPHIST_WB_GAIN_WG00_MASK 0xFF000000
1222#define ISPHIST_WB_GAIN_WG01_SHIFT 16
1223#define ISPHIST_WB_GAIN_WG01_MASK 0xFF0000
1224#define ISPHIST_WB_GAIN_WG02_SHIFT 8
1225#define ISPHIST_WB_GAIN_WG02_MASK 0xFF00
1226#define ISPHIST_WB_GAIN_WG03_SHIFT 0
1227#define ISPHIST_WB_GAIN_WG03_MASK 0xFF
1228
1229#define ISPHIST_REG_START_END_MASK 0x3FFF
1230#define ISPHIST_REG_START_SHIFT 16
1231#define ISPHIST_REG_END_SHIFT 0
1232#define ISPHIST_REG_START_MASK (ISPHIST_REG_START_END_MASK << \
1233 ISPHIST_REG_START_SHIFT)
1234#define ISPHIST_REG_END_MASK (ISPHIST_REG_START_END_MASK << \
1235 ISPHIST_REG_END_SHIFT)
1236
1237#define ISPHIST_REG_MASK (ISPHIST_REG_START_MASK | \
1238 ISPHIST_REG_END_MASK)
1239
1240#define ISPHIST_ADDR_SHIFT 0
1241#define ISPHIST_ADDR_MASK 0x3FF
1242
1243#define ISPHIST_DATA_SHIFT 0
1244#define ISPHIST_DATA_MASK 0xFFFFF
1245
1246#define ISPHIST_RADD_SHIFT 0
1247#define ISPHIST_RADD_MASK 0xFFFFFFFF
1248
1249#define ISPHIST_RADD_OFF_SHIFT 0
1250#define ISPHIST_RADD_OFF_MASK 0xFFFF
1251
1252#define ISPHIST_HV_INFO_HSIZE_SHIFT 16
1253#define ISPHIST_HV_INFO_HSIZE_MASK 0x3FFF0000
1254#define ISPHIST_HV_INFO_VSIZE_SHIFT 0
1255#define ISPHIST_HV_INFO_VSIZE_MASK 0x3FFF
1256
1257#define ISPHIST_HV_INFO_MASK 0x3FFF3FFF
1258
1259#define ISPCCDC_LSC_ENABLE 1
1260#define ISPCCDC_LSC_BUSY (1 << 7)
1261#define ISPCCDC_LSC_GAIN_MODE_N_MASK 0x700
1262#define ISPCCDC_LSC_GAIN_MODE_N_SHIFT 8
1263#define ISPCCDC_LSC_GAIN_MODE_M_MASK 0x3800
1264#define ISPCCDC_LSC_GAIN_MODE_M_SHIFT 12
1265#define ISPCCDC_LSC_GAIN_FORMAT_MASK 0xE
1266#define ISPCCDC_LSC_GAIN_FORMAT_SHIFT 1
1267#define ISPCCDC_LSC_AFTER_REFORMATTER_MASK (1<<6)
1268
1269#define ISPCCDC_LSC_INITIAL_X_MASK 0x3F
1270#define ISPCCDC_LSC_INITIAL_X_SHIFT 0
1271#define ISPCCDC_LSC_INITIAL_Y_MASK 0x3F0000
1272#define ISPCCDC_LSC_INITIAL_Y_SHIFT 16
1273
1274/* -----------------------------------------------------------------------------
1275 * CSI2 receiver registers (ES2.0)
1276 */
1277
1278#define ISPCSI2_REVISION (0x000)
1279#define ISPCSI2_SYSCONFIG (0x010)
1280#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT 12
1281#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK \
1282 (0x3 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
1283#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_FORCE \
1284 (0x0 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
1285#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO \
1286 (0x1 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
1287#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART \
1288 (0x2 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
1289#define ISPCSI2_SYSCONFIG_SOFT_RESET (1 << 1)
1290#define ISPCSI2_SYSCONFIG_AUTO_IDLE (1 << 0)
1291
1292#define ISPCSI2_SYSSTATUS (0x014)
1293#define ISPCSI2_SYSSTATUS_RESET_DONE (1 << 0)
1294
1295#define ISPCSI2_IRQSTATUS (0x018)
1296#define ISPCSI2_IRQSTATUS_OCP_ERR_IRQ (1 << 14)
1297#define ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ (1 << 13)
1298#define ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ (1 << 12)
1299#define ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ (1 << 11)
1300#define ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ (1 << 10)
1301#define ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ (1 << 9)
1302#define ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ (1 << 8)
1303#define ISPCSI2_IRQSTATUS_CONTEXT(n) (1 << (n))
1304
1305#define ISPCSI2_IRQENABLE (0x01c)
1306#define ISPCSI2_CTRL (0x040)
1307#define ISPCSI2_CTRL_VP_CLK_EN (1 << 15)
1308#define ISPCSI2_CTRL_VP_ONLY_EN (1 << 11)
1309#define ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT 8
1310#define ISPCSI2_CTRL_VP_OUT_CTRL_MASK \
1311 (3 << ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
1312#define ISPCSI2_CTRL_DBG_EN (1 << 7)
1313#define ISPCSI2_CTRL_BURST_SIZE_SHIFT 5
1314#define ISPCSI2_CTRL_BURST_SIZE_MASK \
1315 (3 << ISPCSI2_CTRL_BURST_SIZE_SHIFT)
1316#define ISPCSI2_CTRL_FRAME (1 << 3)
1317#define ISPCSI2_CTRL_ECC_EN (1 << 2)
1318#define ISPCSI2_CTRL_SECURE (1 << 1)
1319#define ISPCSI2_CTRL_IF_EN (1 << 0)
1320
1321#define ISPCSI2_DBG_H (0x044)
1322#define ISPCSI2_GNQ (0x048)
1323#define ISPCSI2_PHY_CFG (0x050)
1324#define ISPCSI2_PHY_CFG_RESET_CTRL (1 << 30)
1325#define ISPCSI2_PHY_CFG_RESET_DONE (1 << 29)
1326#define ISPCSI2_PHY_CFG_PWR_CMD_SHIFT 27
1327#define ISPCSI2_PHY_CFG_PWR_CMD_MASK \
1328 (0x3 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
1329#define ISPCSI2_PHY_CFG_PWR_CMD_OFF \
1330 (0x0 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
1331#define ISPCSI2_PHY_CFG_PWR_CMD_ON \
1332 (0x1 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
1333#define ISPCSI2_PHY_CFG_PWR_CMD_ULPW \
1334 (0x2 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
1335#define ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT 25
1336#define ISPCSI2_PHY_CFG_PWR_STATUS_MASK \
1337 (0x3 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
1338#define ISPCSI2_PHY_CFG_PWR_STATUS_OFF \
1339 (0x0 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
1340#define ISPCSI2_PHY_CFG_PWR_STATUS_ON \
1341 (0x1 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
1342#define ISPCSI2_PHY_CFG_PWR_STATUS_ULPW \
1343 (0x2 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
1344#define ISPCSI2_PHY_CFG_PWR_AUTO (1 << 24)
1345
1346#define ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n) (3 + ((n) * 4))
1347#define ISPCSI2_PHY_CFG_DATA_POL_MASK(n) \
1348 (0x1 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
1349#define ISPCSI2_PHY_CFG_DATA_POL_PN(n) \
1350 (0x0 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
1351#define ISPCSI2_PHY_CFG_DATA_POL_NP(n) \
1352 (0x1 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
1353
1354#define ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n) ((n) * 4)
1355#define ISPCSI2_PHY_CFG_DATA_POSITION_MASK(n) \
1356 (0x7 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1357#define ISPCSI2_PHY_CFG_DATA_POSITION_NC(n) \
1358 (0x0 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1359#define ISPCSI2_PHY_CFG_DATA_POSITION_1(n) \
1360 (0x1 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1361#define ISPCSI2_PHY_CFG_DATA_POSITION_2(n) \
1362 (0x2 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1363#define ISPCSI2_PHY_CFG_DATA_POSITION_3(n) \
1364 (0x3 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1365#define ISPCSI2_PHY_CFG_DATA_POSITION_4(n) \
1366 (0x4 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1367#define ISPCSI2_PHY_CFG_DATA_POSITION_5(n) \
1368 (0x5 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1369
1370#define ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT 3
1371#define ISPCSI2_PHY_CFG_CLOCK_POL_MASK \
1372 (0x1 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
1373#define ISPCSI2_PHY_CFG_CLOCK_POL_PN \
1374 (0x0 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
1375#define ISPCSI2_PHY_CFG_CLOCK_POL_NP \
1376 (0x1 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
1377
1378#define ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT 0
1379#define ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK \
1380 (0x7 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1381#define ISPCSI2_PHY_CFG_CLOCK_POSITION_1 \
1382 (0x1 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1383#define ISPCSI2_PHY_CFG_CLOCK_POSITION_2 \
1384 (0x2 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1385#define ISPCSI2_PHY_CFG_CLOCK_POSITION_3 \
1386 (0x3 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1387#define ISPCSI2_PHY_CFG_CLOCK_POSITION_4 \
1388 (0x4 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1389#define ISPCSI2_PHY_CFG_CLOCK_POSITION_5 \
1390 (0x5 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1391
1392#define ISPCSI2_PHY_IRQSTATUS (0x054)
1393#define ISPCSI2_PHY_IRQSTATUS_STATEALLULPMEXIT (1 << 26)
1394#define ISPCSI2_PHY_IRQSTATUS_STATEALLULPMENTER (1 << 25)
1395#define ISPCSI2_PHY_IRQSTATUS_STATEULPM5 (1 << 24)
1396#define ISPCSI2_PHY_IRQSTATUS_STATEULPM4 (1 << 23)
1397#define ISPCSI2_PHY_IRQSTATUS_STATEULPM3 (1 << 22)
1398#define ISPCSI2_PHY_IRQSTATUS_STATEULPM2 (1 << 21)
1399#define ISPCSI2_PHY_IRQSTATUS_STATEULPM1 (1 << 20)
1400#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL5 (1 << 19)
1401#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL4 (1 << 18)
1402#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL3 (1 << 17)
1403#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL2 (1 << 16)
1404#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL1 (1 << 15)
1405#define ISPCSI2_PHY_IRQSTATUS_ERRESC5 (1 << 14)
1406#define ISPCSI2_PHY_IRQSTATUS_ERRESC4 (1 << 13)
1407#define ISPCSI2_PHY_IRQSTATUS_ERRESC3 (1 << 12)
1408#define ISPCSI2_PHY_IRQSTATUS_ERRESC2 (1 << 11)
1409#define ISPCSI2_PHY_IRQSTATUS_ERRESC1 (1 << 10)
1410#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS5 (1 << 9)
1411#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS4 (1 << 8)
1412#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS3 (1 << 7)
1413#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS2 (1 << 6)
1414#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS1 (1 << 5)
1415#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS5 (1 << 4)
1416#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS4 (1 << 3)
1417#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS3 (1 << 2)
1418#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS2 (1 << 1)
1419#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS1 1
1420
1421#define ISPCSI2_SHORT_PACKET (0x05c)
1422#define ISPCSI2_PHY_IRQENABLE (0x060)
1423#define ISPCSI2_PHY_IRQENABLE_STATEALLULPMEXIT (1 << 26)
1424#define ISPCSI2_PHY_IRQENABLE_STATEALLULPMENTER (1 << 25)
1425#define ISPCSI2_PHY_IRQENABLE_STATEULPM5 (1 << 24)
1426#define ISPCSI2_PHY_IRQENABLE_STATEULPM4 (1 << 23)
1427#define ISPCSI2_PHY_IRQENABLE_STATEULPM3 (1 << 22)
1428#define ISPCSI2_PHY_IRQENABLE_STATEULPM2 (1 << 21)
1429#define ISPCSI2_PHY_IRQENABLE_STATEULPM1 (1 << 20)
1430#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL5 (1 << 19)
1431#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL4 (1 << 18)
1432#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL3 (1 << 17)
1433#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL2 (1 << 16)
1434#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL1 (1 << 15)
1435#define ISPCSI2_PHY_IRQENABLE_ERRESC5 (1 << 14)
1436#define ISPCSI2_PHY_IRQENABLE_ERRESC4 (1 << 13)
1437#define ISPCSI2_PHY_IRQENABLE_ERRESC3 (1 << 12)
1438#define ISPCSI2_PHY_IRQENABLE_ERRESC2 (1 << 11)
1439#define ISPCSI2_PHY_IRQENABLE_ERRESC1 (1 << 10)
1440#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS5 (1 << 9)
1441#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS4 (1 << 8)
1442#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS3 (1 << 7)
1443#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS2 (1 << 6)
1444#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS1 (1 << 5)
1445#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS5 (1 << 4)
1446#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS4 (1 << 3)
1447#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS3 (1 << 2)
1448#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS2 (1 << 1)
1449#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS1 (1 << 0)
1450
1451#define ISPCSI2_DBG_P (0x068)
1452#define ISPCSI2_TIMING (0x06c)
1453#define ISPCSI2_TIMING_FORCE_RX_MODE_IO(n) (1 << ((16 * ((n) - 1)) + 15))
1454#define ISPCSI2_TIMING_STOP_STATE_X16_IO(n) (1 << ((16 * ((n) - 1)) + 14))
1455#define ISPCSI2_TIMING_STOP_STATE_X4_IO(n) (1 << ((16 * ((n) - 1)) + 13))
1456#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n) (16 * ((n) - 1))
1457#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(n) \
1458 (0x1fff << ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n))
1459
1460#define ISPCSI2_CTX_CTRL1(n) ((0x070) + 0x20 * (n))
1461#define ISPCSI2_CTX_CTRL1_COUNT_SHIFT 8
1462#define ISPCSI2_CTX_CTRL1_COUNT_MASK \
1463 (0xff << ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
1464#define ISPCSI2_CTX_CTRL1_EOF_EN (1 << 7)
1465#define ISPCSI2_CTX_CTRL1_EOL_EN (1 << 6)
1466#define ISPCSI2_CTX_CTRL1_CS_EN (1 << 5)
1467#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK (1 << 4)
1468#define ISPCSI2_CTX_CTRL1_PING_PONG (1 << 3)
1469#define ISPCSI2_CTX_CTRL1_CTX_EN (1 << 0)
1470
1471#define ISPCSI2_CTX_CTRL2(n) ((0x074) + 0x20 * (n))
1472#define ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT 13
1473#define ISPCSI2_CTX_CTRL2_USER_DEF_MAP_MASK \
1474 (0x3 << ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT)
1475#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT 11
1476#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK \
1477 (0x3 << ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT)
1478#define ISPCSI2_CTX_CTRL2_DPCM_PRED (1 << 10)
1479#define ISPCSI2_CTX_CTRL2_FORMAT_SHIFT 0
1480#define ISPCSI2_CTX_CTRL2_FORMAT_MASK \
1481 (0x3ff << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT)
1482#define ISPCSI2_CTX_CTRL2_FRAME_SHIFT 16
1483#define ISPCSI2_CTX_CTRL2_FRAME_MASK \
1484 (0xffff << ISPCSI2_CTX_CTRL2_FRAME_SHIFT)
1485
1486#define ISPCSI2_CTX_DAT_OFST(n) ((0x078) + 0x20 * (n))
1487#define ISPCSI2_CTX_DAT_OFST_OFST_SHIFT 0
1488#define ISPCSI2_CTX_DAT_OFST_OFST_MASK \
1489 (0x1ffe0 << ISPCSI2_CTX_DAT_OFST_OFST_SHIFT)
1490
1491#define ISPCSI2_CTX_DAT_PING_ADDR(n) ((0x07c) + 0x20 * (n))
1492#define ISPCSI2_CTX_DAT_PONG_ADDR(n) ((0x080) + 0x20 * (n))
1493#define ISPCSI2_CTX_IRQENABLE(n) ((0x084) + 0x20 * (n))
1494#define ISPCSI2_CTX_IRQENABLE_ECC_CORRECTION_IRQ (1 << 8)
1495#define ISPCSI2_CTX_IRQENABLE_LINE_NUMBER_IRQ (1 << 7)
1496#define ISPCSI2_CTX_IRQENABLE_FRAME_NUMBER_IRQ (1 << 6)
1497#define ISPCSI2_CTX_IRQENABLE_CS_IRQ (1 << 5)
1498#define ISPCSI2_CTX_IRQENABLE_LE_IRQ (1 << 3)
1499#define ISPCSI2_CTX_IRQENABLE_LS_IRQ (1 << 2)
1500#define ISPCSI2_CTX_IRQENABLE_FE_IRQ (1 << 1)
1501#define ISPCSI2_CTX_IRQENABLE_FS_IRQ (1 << 0)
1502
1503#define ISPCSI2_CTX_IRQSTATUS(n) ((0x088) + 0x20 * (n))
1504#define ISPCSI2_CTX_IRQSTATUS_ECC_CORRECTION_IRQ (1 << 8)
1505#define ISPCSI2_CTX_IRQSTATUS_LINE_NUMBER_IRQ (1 << 7)
1506#define ISPCSI2_CTX_IRQSTATUS_FRAME_NUMBER_IRQ (1 << 6)
1507#define ISPCSI2_CTX_IRQSTATUS_CS_IRQ (1 << 5)
1508#define ISPCSI2_CTX_IRQSTATUS_LE_IRQ (1 << 3)
1509#define ISPCSI2_CTX_IRQSTATUS_LS_IRQ (1 << 2)
1510#define ISPCSI2_CTX_IRQSTATUS_FE_IRQ (1 << 1)
1511#define ISPCSI2_CTX_IRQSTATUS_FS_IRQ (1 << 0)
1512
1513#define ISPCSI2_CTX_CTRL3(n) ((0x08c) + 0x20 * (n))
1514#define ISPCSI2_CTX_CTRL3_ALPHA_SHIFT 5
1515#define ISPCSI2_CTX_CTRL3_ALPHA_MASK \
1516 (0x3fff << ISPCSI2_CTX_CTRL3_ALPHA_SHIFT)
1517
1518/* This instance is for OMAP3630 only */
1519#define ISPCSI2_CTX_TRANSCODEH(n) (0x000 + 0x8 * (n))
1520#define ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT 16
1521#define ISPCSI2_CTX_TRANSCODEH_HCOUNT_MASK \
1522 (0x1fff << ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT)
1523#define ISPCSI2_CTX_TRANSCODEH_HSKIP_SHIFT 0
1524#define ISPCSI2_CTX_TRANSCODEH_HSKIP_MASK \
1525 (0x1fff << ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT)
1526#define ISPCSI2_CTX_TRANSCODEV(n) (0x004 + 0x8 * (n))
1527#define ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT 16
1528#define ISPCSI2_CTX_TRANSCODEV_VCOUNT_MASK \
1529 (0x1fff << ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT)
1530#define ISPCSI2_CTX_TRANSCODEV_VSKIP_SHIFT 0
1531#define ISPCSI2_CTX_TRANSCODEV_VSKIP_MASK \
1532 (0x1fff << ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT)
1533
1534/* -----------------------------------------------------------------------------
1535 * CSI PHY registers
1536 */
1537
1538#define ISPCSIPHY_REG0 (0x000)
1539#define ISPCSIPHY_REG0_THS_TERM_SHIFT 8
1540#define ISPCSIPHY_REG0_THS_TERM_MASK \
1541 (0xff << ISPCSIPHY_REG0_THS_TERM_SHIFT)
1542#define ISPCSIPHY_REG0_THS_SETTLE_SHIFT 0
1543#define ISPCSIPHY_REG0_THS_SETTLE_MASK \
1544 (0xff << ISPCSIPHY_REG0_THS_SETTLE_SHIFT)
1545
1546#define ISPCSIPHY_REG1 (0x004)
1547#define ISPCSIPHY_REG1_RESET_DONE_CTRLCLK (1 << 29)
1548/* This field is for OMAP3630 only */
1549#define ISPCSIPHY_REG1_CLOCK_MISS_DETECTOR_STATUS (1 << 25)
1550#define ISPCSIPHY_REG1_TCLK_TERM_SHIFT 18
1551#define ISPCSIPHY_REG1_TCLK_TERM_MASK \
1552 (0x7f << ISPCSIPHY_REG1_TCLK_TERM_SHIFT)
1553#define ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN_SHIFT 10
1554#define ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN_MASK \
1555 (0xff << ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN)
1556/* This field is for OMAP3430 only */
1557#define ISPCSIPHY_REG1_TCLK_MISS_SHIFT 8
1558#define ISPCSIPHY_REG1_TCLK_MISS_MASK \
1559 (0x3 << ISPCSIPHY_REG1_TCLK_MISS_SHIFT)
1560/* This field is for OMAP3630 only */
1561#define ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_SHIFT 8
1562#define ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_MASK \
1563 (0x3 << ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_SHIFT)
1564#define ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT 0
1565#define ISPCSIPHY_REG1_TCLK_SETTLE_MASK \
1566 (0xff << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT)
1567
1568/* This register is for OMAP3630 only */
1569#define ISPCSIPHY_REG2 (0x008)
1570#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_SHIFT 30
1571#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_MASK \
1572 (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_SHIFT)
1573#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_SHIFT 28
1574#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_MASK \
1575 (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_SHIFT)
1576#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_SHIFT 26
1577#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_MASK \
1578 (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_SHIFT)
1579#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_SHIFT 24
1580#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_MASK \
1581 (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_SHIFT)
1582#define ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_SHIFT 0
1583#define ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_MASK \
1584 (0x7fffff << ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_SHIFT)
1585
1586#endif /* OMAP3_ISP_REG_H */
diff --git a/drivers/media/platform/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c
new file mode 100644
index 000000000000..d11fb261d530
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispresizer.c
@@ -0,0 +1,1778 @@
1/*
2 * ispresizer.c
3 *
4 * TI OMAP3 ISP - Resizer module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#include <linux/device.h>
28#include <linux/mm.h>
29#include <linux/module.h>
30
31#include "isp.h"
32#include "ispreg.h"
33#include "ispresizer.h"
34
35/*
36 * Resizer Constants
37 */
38#define MIN_RESIZE_VALUE 64
39#define MID_RESIZE_VALUE 512
40#define MAX_RESIZE_VALUE 1024
41
42#define MIN_IN_WIDTH 32
43#define MIN_IN_HEIGHT 32
44#define MAX_IN_WIDTH_MEMORY_MODE 4095
45#define MAX_IN_WIDTH_ONTHEFLY_MODE_ES1 1280
46#define MAX_IN_WIDTH_ONTHEFLY_MODE_ES2 4095
47#define MAX_IN_HEIGHT 4095
48
49#define MIN_OUT_WIDTH 16
50#define MIN_OUT_HEIGHT 2
51#define MAX_OUT_HEIGHT 4095
52
53/*
54 * Resizer Use Constraints
55 * "TRM ES3.1, table 12-46"
56 */
57#define MAX_4TAP_OUT_WIDTH_ES1 1280
58#define MAX_7TAP_OUT_WIDTH_ES1 640
59#define MAX_4TAP_OUT_WIDTH_ES2 3312
60#define MAX_7TAP_OUT_WIDTH_ES2 1650
61#define MAX_4TAP_OUT_WIDTH_3630 4096
62#define MAX_7TAP_OUT_WIDTH_3630 2048
63
64/*
65 * Constants for ratio calculation
66 */
67#define RESIZE_DIVISOR 256
68#define DEFAULT_PHASE 1
69
70/*
71 * Default (and only) configuration of filter coefficients.
72 * 7-tap mode is for scale factors 0.25x to 0.5x.
73 * 4-tap mode is for scale factors 0.5x to 4.0x.
74 * There shouldn't be any reason to recalculate these, EVER.
75 */
76static const struct isprsz_coef filter_coefs = {
77 /* For 8-phase 4-tap horizontal filter: */
78 {
79 0x0000, 0x0100, 0x0000, 0x0000,
80 0x03FA, 0x00F6, 0x0010, 0x0000,
81 0x03F9, 0x00DB, 0x002C, 0x0000,
82 0x03FB, 0x00B3, 0x0053, 0x03FF,
83 0x03FD, 0x0082, 0x0084, 0x03FD,
84 0x03FF, 0x0053, 0x00B3, 0x03FB,
85 0x0000, 0x002C, 0x00DB, 0x03F9,
86 0x0000, 0x0010, 0x00F6, 0x03FA
87 },
88 /* For 8-phase 4-tap vertical filter: */
89 {
90 0x0000, 0x0100, 0x0000, 0x0000,
91 0x03FA, 0x00F6, 0x0010, 0x0000,
92 0x03F9, 0x00DB, 0x002C, 0x0000,
93 0x03FB, 0x00B3, 0x0053, 0x03FF,
94 0x03FD, 0x0082, 0x0084, 0x03FD,
95 0x03FF, 0x0053, 0x00B3, 0x03FB,
96 0x0000, 0x002C, 0x00DB, 0x03F9,
97 0x0000, 0x0010, 0x00F6, 0x03FA
98 },
99 /* For 4-phase 7-tap horizontal filter: */
100 #define DUMMY 0
101 {
102 0x0004, 0x0023, 0x005A, 0x0058, 0x0023, 0x0004, 0x0000, DUMMY,
103 0x0002, 0x0018, 0x004d, 0x0060, 0x0031, 0x0008, 0x0000, DUMMY,
104 0x0001, 0x000f, 0x003f, 0x0062, 0x003f, 0x000f, 0x0001, DUMMY,
105 0x0000, 0x0008, 0x0031, 0x0060, 0x004d, 0x0018, 0x0002, DUMMY
106 },
107 /* For 4-phase 7-tap vertical filter: */
108 {
109 0x0004, 0x0023, 0x005A, 0x0058, 0x0023, 0x0004, 0x0000, DUMMY,
110 0x0002, 0x0018, 0x004d, 0x0060, 0x0031, 0x0008, 0x0000, DUMMY,
111 0x0001, 0x000f, 0x003f, 0x0062, 0x003f, 0x000f, 0x0001, DUMMY,
112 0x0000, 0x0008, 0x0031, 0x0060, 0x004d, 0x0018, 0x0002, DUMMY
113 }
114 /*
115 * The dummy padding is required in 7-tap mode because of how the
116 * registers are arranged physically.
117 */
118 #undef DUMMY
119};
120
121/*
122 * __resizer_get_format - helper function for getting resizer format
123 * @res : pointer to resizer private structure
124 * @pad : pad number
125 * @fh : V4L2 subdev file handle
126 * @which : wanted subdev format
127 * return zero
128 */
129static struct v4l2_mbus_framefmt *
130__resizer_get_format(struct isp_res_device *res, struct v4l2_subdev_fh *fh,
131 unsigned int pad, enum v4l2_subdev_format_whence which)
132{
133 if (which == V4L2_SUBDEV_FORMAT_TRY)
134 return v4l2_subdev_get_try_format(fh, pad);
135 else
136 return &res->formats[pad];
137}
138
139/*
140 * __resizer_get_crop - helper function for getting resizer crop rectangle
141 * @res : pointer to resizer private structure
142 * @fh : V4L2 subdev file handle
143 * @which : wanted subdev crop rectangle
144 */
145static struct v4l2_rect *
146__resizer_get_crop(struct isp_res_device *res, struct v4l2_subdev_fh *fh,
147 enum v4l2_subdev_format_whence which)
148{
149 if (which == V4L2_SUBDEV_FORMAT_TRY)
150 return v4l2_subdev_get_try_crop(fh, RESZ_PAD_SINK);
151 else
152 return &res->crop.request;
153}
154
155/*
156 * resizer_set_filters - Set resizer filters
157 * @res: Device context.
158 * @h_coeff: horizontal coefficient
159 * @v_coeff: vertical coefficient
160 * Return none
161 */
162static void resizer_set_filters(struct isp_res_device *res, const u16 *h_coeff,
163 const u16 *v_coeff)
164{
165 struct isp_device *isp = to_isp_device(res);
166 u32 startaddr_h, startaddr_v, tmp_h, tmp_v;
167 int i;
168
169 startaddr_h = ISPRSZ_HFILT10;
170 startaddr_v = ISPRSZ_VFILT10;
171
172 for (i = 0; i < COEFF_CNT; i += 2) {
173 tmp_h = h_coeff[i] |
174 (h_coeff[i + 1] << ISPRSZ_HFILT_COEF1_SHIFT);
175 tmp_v = v_coeff[i] |
176 (v_coeff[i + 1] << ISPRSZ_VFILT_COEF1_SHIFT);
177 isp_reg_writel(isp, tmp_h, OMAP3_ISP_IOMEM_RESZ, startaddr_h);
178 isp_reg_writel(isp, tmp_v, OMAP3_ISP_IOMEM_RESZ, startaddr_v);
179 startaddr_h += 4;
180 startaddr_v += 4;
181 }
182}
183
184/*
185 * resizer_set_bilinear - Chrominance horizontal algorithm select
186 * @res: Device context.
187 * @type: Filtering interpolation type.
188 *
189 * Filtering that is same as luminance processing is
190 * intended only for downsampling, and bilinear interpolation
191 * is intended only for upsampling.
192 */
193static void resizer_set_bilinear(struct isp_res_device *res,
194 enum resizer_chroma_algo type)
195{
196 struct isp_device *isp = to_isp_device(res);
197
198 if (type == RSZ_BILINEAR)
199 isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
200 ISPRSZ_CNT_CBILIN);
201 else
202 isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
203 ISPRSZ_CNT_CBILIN);
204}
205
206/*
207 * resizer_set_ycpos - Luminance and chrominance order
208 * @res: Device context.
209 * @order: order type.
210 */
211static void resizer_set_ycpos(struct isp_res_device *res,
212 enum v4l2_mbus_pixelcode pixelcode)
213{
214 struct isp_device *isp = to_isp_device(res);
215
216 switch (pixelcode) {
217 case V4L2_MBUS_FMT_YUYV8_1X16:
218 isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
219 ISPRSZ_CNT_YCPOS);
220 break;
221 case V4L2_MBUS_FMT_UYVY8_1X16:
222 isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
223 ISPRSZ_CNT_YCPOS);
224 break;
225 default:
226 return;
227 }
228}
229
230/*
231 * resizer_set_phase - Setup horizontal and vertical starting phase
232 * @res: Device context.
233 * @h_phase: horizontal phase parameters.
234 * @v_phase: vertical phase parameters.
235 *
236 * Horizontal and vertical phase range is 0 to 7
237 */
238static void resizer_set_phase(struct isp_res_device *res, u32 h_phase,
239 u32 v_phase)
240{
241 struct isp_device *isp = to_isp_device(res);
242 u32 rgval = 0;
243
244 rgval = isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
245 ~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK);
246 rgval |= (h_phase << ISPRSZ_CNT_HSTPH_SHIFT) & ISPRSZ_CNT_HSTPH_MASK;
247 rgval |= (v_phase << ISPRSZ_CNT_VSTPH_SHIFT) & ISPRSZ_CNT_VSTPH_MASK;
248
249 isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT);
250}
251
252/*
253 * resizer_set_luma - Setup luminance enhancer parameters
254 * @res: Device context.
255 * @luma: Structure for luminance enhancer parameters.
256 *
257 * Algorithm select:
258 * 0x0: Disable
259 * 0x1: [-1 2 -1]/2 high-pass filter
260 * 0x2: [-1 -2 6 -2 -1]/4 high-pass filter
261 *
262 * Maximum gain:
263 * The data is coded in U4Q4 representation.
264 *
265 * Slope:
266 * The data is coded in U4Q4 representation.
267 *
268 * Coring offset:
269 * The data is coded in U8Q0 representation.
270 *
271 * The new luminance value is computed as:
272 * Y += HPF(Y) x max(GAIN, (HPF(Y) - CORE) x SLOP + 8) >> 4.
273 */
274static void resizer_set_luma(struct isp_res_device *res,
275 struct resizer_luma_yenh *luma)
276{
277 struct isp_device *isp = to_isp_device(res);
278 u32 rgval = 0;
279
280 rgval = (luma->algo << ISPRSZ_YENH_ALGO_SHIFT)
281 & ISPRSZ_YENH_ALGO_MASK;
282 rgval |= (luma->gain << ISPRSZ_YENH_GAIN_SHIFT)
283 & ISPRSZ_YENH_GAIN_MASK;
284 rgval |= (luma->slope << ISPRSZ_YENH_SLOP_SHIFT)
285 & ISPRSZ_YENH_SLOP_MASK;
286 rgval |= (luma->core << ISPRSZ_YENH_CORE_SHIFT)
287 & ISPRSZ_YENH_CORE_MASK;
288
289 isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH);
290}
291
292/*
293 * resizer_set_source - Input source select
294 * @res: Device context.
295 * @source: Input source type
296 *
297 * If this field is set to RESIZER_INPUT_VP, the resizer input is fed from
298 * Preview/CCDC engine, otherwise from memory.
299 */
300static void resizer_set_source(struct isp_res_device *res,
301 enum resizer_input_entity source)
302{
303 struct isp_device *isp = to_isp_device(res);
304
305 if (source == RESIZER_INPUT_MEMORY)
306 isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
307 ISPRSZ_CNT_INPSRC);
308 else
309 isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
310 ISPRSZ_CNT_INPSRC);
311}
312
313/*
314 * resizer_set_ratio - Setup horizontal and vertical resizing value
315 * @res: Device context.
316 * @ratio: Structure for ratio parameters.
317 *
318 * Resizing range from 64 to 1024
319 */
320static void resizer_set_ratio(struct isp_res_device *res,
321 const struct resizer_ratio *ratio)
322{
323 struct isp_device *isp = to_isp_device(res);
324 const u16 *h_filter, *v_filter;
325 u32 rgval = 0;
326
327 rgval = isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
328 ~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK);
329 rgval |= ((ratio->horz - 1) << ISPRSZ_CNT_HRSZ_SHIFT)
330 & ISPRSZ_CNT_HRSZ_MASK;
331 rgval |= ((ratio->vert - 1) << ISPRSZ_CNT_VRSZ_SHIFT)
332 & ISPRSZ_CNT_VRSZ_MASK;
333 isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT);
334
335 /* prepare horizontal filter coefficients */
336 if (ratio->horz > MID_RESIZE_VALUE)
337 h_filter = &filter_coefs.h_filter_coef_7tap[0];
338 else
339 h_filter = &filter_coefs.h_filter_coef_4tap[0];
340
341 /* prepare vertical filter coefficients */
342 if (ratio->vert > MID_RESIZE_VALUE)
343 v_filter = &filter_coefs.v_filter_coef_7tap[0];
344 else
345 v_filter = &filter_coefs.v_filter_coef_4tap[0];
346
347 resizer_set_filters(res, h_filter, v_filter);
348}
349
350/*
351 * resizer_set_dst_size - Setup the output height and width
352 * @res: Device context.
353 * @width: Output width.
354 * @height: Output height.
355 *
356 * Width :
357 * The value must be EVEN.
358 *
359 * Height:
360 * The number of bytes written to SDRAM must be
361 * a multiple of 16-bytes if the vertical resizing factor
362 * is greater than 1x (upsizing)
363 */
364static void resizer_set_output_size(struct isp_res_device *res,
365 u32 width, u32 height)
366{
367 struct isp_device *isp = to_isp_device(res);
368 u32 rgval = 0;
369
370 dev_dbg(isp->dev, "Output size[w/h]: %dx%d\n", width, height);
371 rgval = (width << ISPRSZ_OUT_SIZE_HORZ_SHIFT)
372 & ISPRSZ_OUT_SIZE_HORZ_MASK;
373 rgval |= (height << ISPRSZ_OUT_SIZE_VERT_SHIFT)
374 & ISPRSZ_OUT_SIZE_VERT_MASK;
375 isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE);
376}
377
378/*
379 * resizer_set_output_offset - Setup memory offset for the output lines.
380 * @res: Device context.
381 * @offset: Memory offset.
382 *
383 * The 5 LSBs are forced to be zeros by the hardware to align on a 32-byte
384 * boundary; the 5 LSBs are read-only. For optimal use of SDRAM bandwidth,
385 * the SDRAM line offset must be set on a 256-byte boundary
386 */
387static void resizer_set_output_offset(struct isp_res_device *res, u32 offset)
388{
389 struct isp_device *isp = to_isp_device(res);
390
391 isp_reg_writel(isp, offset, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF);
392}
393
394/*
395 * resizer_set_start - Setup vertical and horizontal start position
396 * @res: Device context.
397 * @left: Horizontal start position.
398 * @top: Vertical start position.
399 *
400 * Vertical start line:
401 * This field makes sense only when the resizer obtains its input
402 * from the preview engine/CCDC
403 *
404 * Horizontal start pixel:
405 * Pixels are coded on 16 bits for YUV and 8 bits for color separate data.
406 * When the resizer gets its input from SDRAM, this field must be set
407 * to <= 15 for YUV 16-bit data and <= 31 for 8-bit color separate data
408 */
409static void resizer_set_start(struct isp_res_device *res, u32 left, u32 top)
410{
411 struct isp_device *isp = to_isp_device(res);
412 u32 rgval = 0;
413
414 rgval = (left << ISPRSZ_IN_START_HORZ_ST_SHIFT)
415 & ISPRSZ_IN_START_HORZ_ST_MASK;
416 rgval |= (top << ISPRSZ_IN_START_VERT_ST_SHIFT)
417 & ISPRSZ_IN_START_VERT_ST_MASK;
418
419 isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START);
420}
421
422/*
423 * resizer_set_input_size - Setup the input size
424 * @res: Device context.
425 * @width: The range is 0 to 4095 pixels
426 * @height: The range is 0 to 4095 lines
427 */
428static void resizer_set_input_size(struct isp_res_device *res,
429 u32 width, u32 height)
430{
431 struct isp_device *isp = to_isp_device(res);
432 u32 rgval = 0;
433
434 dev_dbg(isp->dev, "Input size[w/h]: %dx%d\n", width, height);
435
436 rgval = (width << ISPRSZ_IN_SIZE_HORZ_SHIFT)
437 & ISPRSZ_IN_SIZE_HORZ_MASK;
438 rgval |= (height << ISPRSZ_IN_SIZE_VERT_SHIFT)
439 & ISPRSZ_IN_SIZE_VERT_MASK;
440
441 isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE);
442}
443
444/*
445 * resizer_set_src_offs - Setup the memory offset for the input lines
446 * @res: Device context.
447 * @offset: Memory offset.
448 *
449 * The 5 LSBs are forced to be zeros by the hardware to align on a 32-byte
450 * boundary; the 5 LSBs are read-only. This field must be programmed to be
451 * 0x0 if the resizer input is from preview engine/CCDC.
452 */
453static void resizer_set_input_offset(struct isp_res_device *res, u32 offset)
454{
455 struct isp_device *isp = to_isp_device(res);
456
457 isp_reg_writel(isp, offset, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF);
458}
459
460/*
461 * resizer_set_intype - Input type select
462 * @res: Device context.
463 * @type: Pixel format type.
464 */
465static void resizer_set_intype(struct isp_res_device *res,
466 enum resizer_colors_type type)
467{
468 struct isp_device *isp = to_isp_device(res);
469
470 if (type == RSZ_COLOR8)
471 isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
472 ISPRSZ_CNT_INPTYP);
473 else
474 isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
475 ISPRSZ_CNT_INPTYP);
476}
477
478/*
479 * __resizer_set_inaddr - Helper function for set input address
480 * @res : pointer to resizer private data structure
481 * @addr: input address
482 * return none
483 */
484static void __resizer_set_inaddr(struct isp_res_device *res, u32 addr)
485{
486 struct isp_device *isp = to_isp_device(res);
487
488 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);
489}
490
491/*
492 * The data rate at the horizontal resizer output must not exceed half the
493 * functional clock or 100 MP/s, whichever is lower. According to the TRM
494 * there's no similar requirement for the vertical resizer output. However
495 * experience showed that vertical upscaling by 4 leads to SBL overflows (with
496 * data rates at the resizer output exceeding 300 MP/s). Limiting the resizer
497 * output data rate to the functional clock or 200 MP/s, whichever is lower,
498 * seems to get rid of SBL overflows.
499 *
500 * The maximum data rate at the output of the horizontal resizer can thus be
501 * computed with
502 *
503 * max intermediate rate <= L3 clock * input height / output height
504 * max intermediate rate <= L3 clock / 2
505 *
506 * The maximum data rate at the resizer input is then
507 *
508 * max input rate <= max intermediate rate * input width / output width
509 *
510 * where the input width and height are the resizer input crop rectangle size.
511 * The TRM doesn't clearly explain if that's a maximum instant data rate or a
512 * maximum average data rate.
513 */
514void omap3isp_resizer_max_rate(struct isp_res_device *res,
515 unsigned int *max_rate)
516{
517 struct isp_pipeline *pipe = to_isp_pipeline(&res->subdev.entity);
518 const struct v4l2_mbus_framefmt *ofmt = &res->formats[RESZ_PAD_SOURCE];
519 unsigned long limit = min(pipe->l3_ick, 200000000UL);
520 unsigned long clock;
521
522 clock = div_u64((u64)limit * res->crop.active.height, ofmt->height);
523 clock = min(clock, limit / 2);
524 *max_rate = div_u64((u64)clock * res->crop.active.width, ofmt->width);
525}
526
527/*
528 * When the resizer processes images from memory, the driver must slow down read
529 * requests on the input to at least comply with the internal data rate
530 * requirements. If the application real-time requirements can cope with slower
531 * processing, the resizer can be slowed down even more to put less pressure on
532 * the overall system.
533 *
534 * When the resizer processes images on the fly (either from the CCDC or the
535 * preview module), the same data rate requirements apply but they can't be
536 * enforced at the resizer level. The image input module (sensor, CCP2 or
537 * preview module) must not provide image data faster than the resizer can
538 * process.
539 *
540 * For live image pipelines, the data rate is set by the frame format, size and
541 * rate. The sensor output frame rate must not exceed the maximum resizer data
542 * rate.
543 *
544 * The resizer slows down read requests by inserting wait cycles in the SBL
545 * requests. The maximum number of 256-byte requests per second can be computed
546 * as (the data rate is multiplied by 2 to convert from pixels per second to
547 * bytes per second)
548 *
549 * request per second = data rate * 2 / 256
550 * cycles per request = cycles per second / requests per second
551 *
552 * The number of cycles per second is controlled by the L3 clock, leading to
553 *
554 * cycles per request = L3 frequency / 2 * 256 / data rate
555 */
556static void resizer_adjust_bandwidth(struct isp_res_device *res)
557{
558 struct isp_pipeline *pipe = to_isp_pipeline(&res->subdev.entity);
559 struct isp_device *isp = to_isp_device(res);
560 unsigned long l3_ick = pipe->l3_ick;
561 struct v4l2_fract *timeperframe;
562 unsigned int cycles_per_frame;
563 unsigned int requests_per_frame;
564 unsigned int cycles_per_request;
565 unsigned int granularity;
566 unsigned int minimum;
567 unsigned int maximum;
568 unsigned int value;
569
570 if (res->input != RESIZER_INPUT_MEMORY) {
571 isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
572 ISPSBL_SDR_REQ_RSZ_EXP_MASK);
573 return;
574 }
575
576 switch (isp->revision) {
577 case ISP_REVISION_1_0:
578 case ISP_REVISION_2_0:
579 default:
580 granularity = 1024;
581 break;
582
583 case ISP_REVISION_15_0:
584 granularity = 32;
585 break;
586 }
587
588 /* Compute the minimum number of cycles per request, based on the
589 * pipeline maximum data rate. This is an absolute lower bound if we
590 * don't want SBL overflows, so round the value up.
591 */
592 cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1,
593 pipe->max_rate);
594 minimum = DIV_ROUND_UP(cycles_per_request, granularity);
595
596 /* Compute the maximum number of cycles per request, based on the
597 * requested frame rate. This is a soft upper bound to achieve a frame
598 * rate equal or higher than the requested value, so round the value
599 * down.
600 */
601 timeperframe = &pipe->max_timeperframe;
602
603 requests_per_frame = DIV_ROUND_UP(res->crop.active.width * 2, 256)
604 * res->crop.active.height;
605 cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator,
606 timeperframe->denominator);
607 cycles_per_request = cycles_per_frame / requests_per_frame;
608
609 maximum = cycles_per_request / granularity;
610
611 value = max(minimum, maximum);
612
613 dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value);
614 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
615 ISPSBL_SDR_REQ_RSZ_EXP_MASK,
616 value << ISPSBL_SDR_REQ_RSZ_EXP_SHIFT);
617}
618
619/*
620 * omap3isp_resizer_busy - Checks if ISP resizer is busy.
621 *
622 * Returns busy field from ISPRSZ_PCR register.
623 */
624int omap3isp_resizer_busy(struct isp_res_device *res)
625{
626 struct isp_device *isp = to_isp_device(res);
627
628 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) &
629 ISPRSZ_PCR_BUSY;
630}
631
632/*
633 * resizer_set_inaddr - Sets the memory address of the input frame.
634 * @addr: 32bit memory address aligned on 32byte boundary.
635 */
636static void resizer_set_inaddr(struct isp_res_device *res, u32 addr)
637{
638 res->addr_base = addr;
639
640 /* This will handle crop settings in stream off state */
641 if (res->crop_offset)
642 addr += res->crop_offset & ~0x1f;
643
644 __resizer_set_inaddr(res, addr);
645}
646
647/*
648 * Configures the memory address to which the output frame is written.
649 * @addr: 32bit memory address aligned on 32byte boundary.
650 * Note: For SBL efficiency reasons the address should be on a 256-byte
651 * boundary.
652 */
653static void resizer_set_outaddr(struct isp_res_device *res, u32 addr)
654{
655 struct isp_device *isp = to_isp_device(res);
656
657 /*
658 * Set output address. This needs to be in its own function
659 * because it changes often.
660 */
661 isp_reg_writel(isp, addr << ISPRSZ_SDR_OUTADD_ADDR_SHIFT,
662 OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD);
663}
664
665/*
666 * resizer_print_status - Prints the values of the resizer module registers.
667 */
668#define RSZ_PRINT_REGISTER(isp, name)\
669 dev_dbg(isp->dev, "###RSZ " #name "=0x%08x\n", \
670 isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_##name))
671
672static void resizer_print_status(struct isp_res_device *res)
673{
674 struct isp_device *isp = to_isp_device(res);
675
676 dev_dbg(isp->dev, "-------------Resizer Register dump----------\n");
677
678 RSZ_PRINT_REGISTER(isp, PCR);
679 RSZ_PRINT_REGISTER(isp, CNT);
680 RSZ_PRINT_REGISTER(isp, OUT_SIZE);
681 RSZ_PRINT_REGISTER(isp, IN_START);
682 RSZ_PRINT_REGISTER(isp, IN_SIZE);
683 RSZ_PRINT_REGISTER(isp, SDR_INADD);
684 RSZ_PRINT_REGISTER(isp, SDR_INOFF);
685 RSZ_PRINT_REGISTER(isp, SDR_OUTADD);
686 RSZ_PRINT_REGISTER(isp, SDR_OUTOFF);
687 RSZ_PRINT_REGISTER(isp, YENH);
688
689 dev_dbg(isp->dev, "--------------------------------------------\n");
690}
691
692/*
693 * resizer_calc_ratios - Helper function for calculating resizer ratios
694 * @res: pointer to resizer private data structure
695 * @input: input frame size
696 * @output: output frame size
697 * @ratio : return calculated ratios
698 * return none
699 *
700 * The resizer uses a polyphase sample rate converter. The upsampling filter
701 * has a fixed number of phases that depend on the resizing ratio. As the ratio
702 * computation depends on the number of phases, we need to compute a first
703 * approximation and then refine it.
704 *
705 * The input/output/ratio relationship is given by the OMAP34xx TRM:
706 *
707 * - 8-phase, 4-tap mode (RSZ = 64 ~ 512)
708 * iw = (32 * sph + (ow - 1) * hrsz + 16) >> 8 + 7
709 * ih = (32 * spv + (oh - 1) * vrsz + 16) >> 8 + 4
710 * - 4-phase, 7-tap mode (RSZ = 513 ~ 1024)
711 * iw = (64 * sph + (ow - 1) * hrsz + 32) >> 8 + 7
712 * ih = (64 * spv + (oh - 1) * vrsz + 32) >> 8 + 7
713 *
714 * iw and ih are the input width and height after cropping. Those equations need
715 * to be satisfied exactly for the resizer to work correctly.
716 *
717 * The equations can't be easily reverted, as the >> 8 operation is not linear.
718 * In addition, not all input sizes can be achieved for a given output size. To
719 * get the highest input size lower than or equal to the requested input size,
720 * we need to compute the highest resizing ratio that satisfies the following
721 * inequality (taking the 4-tap mode width equation as an example)
722 *
723 * iw >= (32 * sph + (ow - 1) * hrsz + 16) >> 8 - 7
724 *
725 * (where iw is the requested input width) which can be rewritten as
726 *
727 * iw - 7 >= (32 * sph + (ow - 1) * hrsz + 16) >> 8
728 * (iw - 7) << 8 >= 32 * sph + (ow - 1) * hrsz + 16 - b
729 * ((iw - 7) << 8) + b >= 32 * sph + (ow - 1) * hrsz + 16
730 *
731 * where b is the value of the 8 least significant bits of the right hand side
732 * expression of the last inequality. The highest resizing ratio value will be
733 * achieved when b is equal to its maximum value of 255. That resizing ratio
734 * value will still satisfy the original inequality, as b will disappear when
735 * the expression will be shifted right by 8.
736 *
737 * The reverted equations thus become
738 *
739 * - 8-phase, 4-tap mode
740 * hrsz = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / (ow - 1)
741 * vrsz = ((ih - 4) * 256 + 255 - 16 - 32 * spv) / (oh - 1)
742 * - 4-phase, 7-tap mode
743 * hrsz = ((iw - 7) * 256 + 255 - 32 - 64 * sph) / (ow - 1)
744 * vrsz = ((ih - 7) * 256 + 255 - 32 - 64 * spv) / (oh - 1)
745 *
746 * The ratios are integer values, and are rounded down to ensure that the
747 * cropped input size is not bigger than the uncropped input size.
748 *
749 * As the number of phases/taps, used to select the correct equations to compute
750 * the ratio, depends on the ratio, we start with the 4-tap mode equations to
751 * compute an approximation of the ratio, and switch to the 7-tap mode equations
752 * if the approximation is higher than the ratio threshold.
753 *
754 * As the 7-tap mode equations will return a ratio smaller than or equal to the
755 * 4-tap mode equations, the resulting ratio could become lower than or equal to
756 * the ratio threshold. This 'equations loop' isn't an issue as long as the
757 * correct equations are used to compute the final input size. Starting with the
758 * 4-tap mode equations ensure that, in case of values resulting in a 'ratio
759 * loop', the smallest of the ratio values will be used, never exceeding the
760 * requested input size.
761 *
762 * We first clamp the output size according to the hardware capability to avoid
763 * auto-cropping the input more than required to satisfy the TRM equations. The
764 * minimum output size is achieved with a scaling factor of 1024. It is thus
765 * computed using the 7-tap equations.
766 *
767 * min ow = ((iw - 7) * 256 - 32 - 64 * sph) / 1024 + 1
768 * min oh = ((ih - 7) * 256 - 32 - 64 * spv) / 1024 + 1
769 *
770 * Similarly, the maximum output size is achieved with a scaling factor of 64
771 * and computed using the 4-tap equations.
772 *
773 * max ow = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / 64 + 1
774 * max oh = ((ih - 4) * 256 + 255 - 16 - 32 * spv) / 64 + 1
775 *
776 * The additional +255 term compensates for the round down operation performed
777 * by the TRM equations when shifting the value right by 8 bits.
778 *
779 * We then compute and clamp the ratios (x1/4 ~ x4). Clamping the output size to
780 * the maximum value guarantees that the ratio value will never be smaller than
781 * the minimum, but it could still slightly exceed the maximum. Clamping the
782 * ratio will thus result in a resizing factor slightly larger than the
783 * requested value.
784 *
785 * To accommodate that, and make sure the TRM equations are satisfied exactly, we
786 * compute the input crop rectangle as the last step.
787 *
788 * As if the situation wasn't complex enough, the maximum output width depends
789 * on the vertical resizing ratio. Fortunately, the output height doesn't
790 * depend on the horizontal resizing ratio. We can then start by computing the
791 * output height and the vertical ratio, and then move to computing the output
792 * width and the horizontal ratio.
793 */
794static void resizer_calc_ratios(struct isp_res_device *res,
795 struct v4l2_rect *input,
796 struct v4l2_mbus_framefmt *output,
797 struct resizer_ratio *ratio)
798{
799 struct isp_device *isp = to_isp_device(res);
800 const unsigned int spv = DEFAULT_PHASE;
801 const unsigned int sph = DEFAULT_PHASE;
802 unsigned int upscaled_width;
803 unsigned int upscaled_height;
804 unsigned int min_width;
805 unsigned int min_height;
806 unsigned int max_width;
807 unsigned int max_height;
808 unsigned int width_alignment;
809 unsigned int width;
810 unsigned int height;
811
812 /*
813 * Clamp the output height based on the hardware capabilities and
814 * compute the vertical resizing ratio.
815 */
816 min_height = ((input->height - 7) * 256 - 32 - 64 * spv) / 1024 + 1;
817 min_height = max_t(unsigned int, min_height, MIN_OUT_HEIGHT);
818 max_height = ((input->height - 4) * 256 + 255 - 16 - 32 * spv) / 64 + 1;
819 max_height = min_t(unsigned int, max_height, MAX_OUT_HEIGHT);
820 output->height = clamp(output->height, min_height, max_height);
821
822 ratio->vert = ((input->height - 4) * 256 + 255 - 16 - 32 * spv)
823 / (output->height - 1);
824 if (ratio->vert > MID_RESIZE_VALUE)
825 ratio->vert = ((input->height - 7) * 256 + 255 - 32 - 64 * spv)
826 / (output->height - 1);
827 ratio->vert = clamp_t(unsigned int, ratio->vert,
828 MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
829
830 if (ratio->vert <= MID_RESIZE_VALUE) {
831 upscaled_height = (output->height - 1) * ratio->vert
832 + 32 * spv + 16;
833 height = (upscaled_height >> 8) + 4;
834 } else {
835 upscaled_height = (output->height - 1) * ratio->vert
836 + 64 * spv + 32;
837 height = (upscaled_height >> 8) + 7;
838 }
839
840 /*
841 * Compute the minimum and maximum output widths based on the hardware
842 * capabilities. The maximum depends on the vertical resizing ratio.
843 */
844 min_width = ((input->width - 7) * 256 - 32 - 64 * sph) / 1024 + 1;
845 min_width = max_t(unsigned int, min_width, MIN_OUT_WIDTH);
846
847 if (ratio->vert <= MID_RESIZE_VALUE) {
848 switch (isp->revision) {
849 case ISP_REVISION_1_0:
850 max_width = MAX_4TAP_OUT_WIDTH_ES1;
851 break;
852
853 case ISP_REVISION_2_0:
854 default:
855 max_width = MAX_4TAP_OUT_WIDTH_ES2;
856 break;
857
858 case ISP_REVISION_15_0:
859 max_width = MAX_4TAP_OUT_WIDTH_3630;
860 break;
861 }
862 } else {
863 switch (isp->revision) {
864 case ISP_REVISION_1_0:
865 max_width = MAX_7TAP_OUT_WIDTH_ES1;
866 break;
867
868 case ISP_REVISION_2_0:
869 default:
870 max_width = MAX_7TAP_OUT_WIDTH_ES2;
871 break;
872
873 case ISP_REVISION_15_0:
874 max_width = MAX_7TAP_OUT_WIDTH_3630;
875 break;
876 }
877 }
878 max_width = min(((input->width - 7) * 256 + 255 - 16 - 32 * sph) / 64
879 + 1, max_width);
880
881 /*
882 * The output width must be even, and must be a multiple of 16 bytes
883 * when upscaling vertically. Clamp the output width to the valid range.
884 * Take the alignment into account (the maximum width in 7-tap mode on
885 * ES2 isn't a multiple of 8) and align the result up to make sure it
886 * won't be smaller than the minimum.
887 */
888 width_alignment = ratio->vert < 256 ? 8 : 2;
889 output->width = clamp(output->width, min_width,
890 max_width & ~(width_alignment - 1));
891 output->width = ALIGN(output->width, width_alignment);
892
893 ratio->horz = ((input->width - 7) * 256 + 255 - 16 - 32 * sph)
894 / (output->width - 1);
895 if (ratio->horz > MID_RESIZE_VALUE)
896 ratio->horz = ((input->width - 7) * 256 + 255 - 32 - 64 * sph)
897 / (output->width - 1);
898 ratio->horz = clamp_t(unsigned int, ratio->horz,
899 MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
900
901 if (ratio->horz <= MID_RESIZE_VALUE) {
902 upscaled_width = (output->width - 1) * ratio->horz
903 + 32 * sph + 16;
904 width = (upscaled_width >> 8) + 7;
905 } else {
906 upscaled_width = (output->width - 1) * ratio->horz
907 + 64 * sph + 32;
908 width = (upscaled_width >> 8) + 7;
909 }
910
911 /* Center the new crop rectangle. */
912 input->left += (input->width - width) / 2;
913 input->top += (input->height - height) / 2;
914 input->width = width;
915 input->height = height;
916}
917
918/*
919 * resizer_set_crop_params - Setup hardware with cropping parameters
920 * @res : resizer private structure
921 * @crop_rect : current crop rectangle
922 * @ratio : resizer ratios
923 * return none
924 */
925static void resizer_set_crop_params(struct isp_res_device *res,
926 const struct v4l2_mbus_framefmt *input,
927 const struct v4l2_mbus_framefmt *output)
928{
929 resizer_set_ratio(res, &res->ratio);
930
931 /* Set chrominance horizontal algorithm */
932 if (res->ratio.horz >= RESIZE_DIVISOR)
933 resizer_set_bilinear(res, RSZ_THE_SAME);
934 else
935 resizer_set_bilinear(res, RSZ_BILINEAR);
936
937 resizer_adjust_bandwidth(res);
938
939 if (res->input == RESIZER_INPUT_MEMORY) {
940 /* Calculate additional offset for crop */
941 res->crop_offset = (res->crop.active.top * input->width +
942 res->crop.active.left) * 2;
943 /*
944 * Write lowest 4 bits of horizontal pixel offset (in pixels),
945 * vertical start must be 0.
946 */
947 resizer_set_start(res, (res->crop_offset / 2) & 0xf, 0);
948
949 /*
950 * Set start (read) address for cropping, in bytes.
951 * Lowest 5 bits must be zero.
952 */
953 __resizer_set_inaddr(res,
954 res->addr_base + (res->crop_offset & ~0x1f));
955 } else {
956 /*
957 * Set vertical start line and horizontal starting pixel.
958 * If the input is from CCDC/PREV, horizontal start field is
959 * in bytes (twice number of pixels).
960 */
961 resizer_set_start(res, res->crop.active.left * 2,
962 res->crop.active.top);
963 /* Input address and offset must be 0 for preview/ccdc input */
964 __resizer_set_inaddr(res, 0);
965 resizer_set_input_offset(res, 0);
966 }
967
968 /* Set the input size */
969 resizer_set_input_size(res, res->crop.active.width,
970 res->crop.active.height);
971}
972
973static void resizer_configure(struct isp_res_device *res)
974{
975 struct v4l2_mbus_framefmt *informat, *outformat;
976 struct resizer_luma_yenh luma = {0, 0, 0, 0};
977
978 resizer_set_source(res, res->input);
979
980 informat = &res->formats[RESZ_PAD_SINK];
981 outformat = &res->formats[RESZ_PAD_SOURCE];
982
983 /* RESZ_PAD_SINK */
984 if (res->input == RESIZER_INPUT_VP)
985 resizer_set_input_offset(res, 0);
986 else
987 resizer_set_input_offset(res, ALIGN(informat->width, 0x10) * 2);
988
989 /* YUV422 interleaved, default phase, no luma enhancement */
990 resizer_set_intype(res, RSZ_YUV422);
991 resizer_set_ycpos(res, informat->code);
992 resizer_set_phase(res, DEFAULT_PHASE, DEFAULT_PHASE);
993 resizer_set_luma(res, &luma);
994
995 /* RESZ_PAD_SOURCE */
996 resizer_set_output_offset(res, ALIGN(outformat->width * 2, 32));
997 resizer_set_output_size(res, outformat->width, outformat->height);
998
999 resizer_set_crop_params(res, informat, outformat);
1000}
1001
1002/* -----------------------------------------------------------------------------
1003 * Interrupt handling
1004 */
1005
1006static void resizer_enable_oneshot(struct isp_res_device *res)
1007{
1008 struct isp_device *isp = to_isp_device(res);
1009
1010 isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR,
1011 ISPRSZ_PCR_ENABLE | ISPRSZ_PCR_ONESHOT);
1012}
1013
1014void omap3isp_resizer_isr_frame_sync(struct isp_res_device *res)
1015{
1016 /*
1017 * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun
1018 * condition, the module was paused and now we have a buffer queued
1019 * on the output again. Restart the pipeline if running in continuous
1020 * mode.
1021 */
1022 if (res->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
1023 res->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
1024 resizer_enable_oneshot(res);
1025 isp_video_dmaqueue_flags_clr(&res->video_out);
1026 }
1027}
1028
1029static void resizer_isr_buffer(struct isp_res_device *res)
1030{
1031 struct isp_pipeline *pipe = to_isp_pipeline(&res->subdev.entity);
1032 struct isp_buffer *buffer;
1033 int restart = 0;
1034
1035 if (res->state == ISP_PIPELINE_STREAM_STOPPED)
1036 return;
1037
1038 /* Complete the output buffer and, if reading from memory, the input
1039 * buffer.
1040 */
1041 buffer = omap3isp_video_buffer_next(&res->video_out);
1042 if (buffer != NULL) {
1043 resizer_set_outaddr(res, buffer->isp_addr);
1044 restart = 1;
1045 }
1046
1047 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
1048
1049 if (res->input == RESIZER_INPUT_MEMORY) {
1050 buffer = omap3isp_video_buffer_next(&res->video_in);
1051 if (buffer != NULL)
1052 resizer_set_inaddr(res, buffer->isp_addr);
1053 pipe->state |= ISP_PIPELINE_IDLE_INPUT;
1054 }
1055
1056 if (res->state == ISP_PIPELINE_STREAM_SINGLESHOT) {
1057 if (isp_pipeline_ready(pipe))
1058 omap3isp_pipeline_set_stream(pipe,
1059 ISP_PIPELINE_STREAM_SINGLESHOT);
1060 } else {
1061 /* If an underrun occurs, the video queue operation handler will
1062 * restart the resizer. Otherwise restart it immediately.
1063 */
1064 if (restart)
1065 resizer_enable_oneshot(res);
1066 }
1067}
1068
1069/*
1070 * omap3isp_resizer_isr - ISP resizer interrupt handler
1071 *
1072 * Manage the resizer video buffers and configure shadowed and busy-locked
1073 * registers.
1074 */
1075void omap3isp_resizer_isr(struct isp_res_device *res)
1076{
1077 struct v4l2_mbus_framefmt *informat, *outformat;
1078
1079 if (omap3isp_module_sync_is_stopping(&res->wait, &res->stopping))
1080 return;
1081
1082 if (res->applycrop) {
1083 outformat = __resizer_get_format(res, NULL, RESZ_PAD_SOURCE,
1084 V4L2_SUBDEV_FORMAT_ACTIVE);
1085 informat = __resizer_get_format(res, NULL, RESZ_PAD_SINK,
1086 V4L2_SUBDEV_FORMAT_ACTIVE);
1087 resizer_set_crop_params(res, informat, outformat);
1088 res->applycrop = 0;
1089 }
1090
1091 resizer_isr_buffer(res);
1092}
1093
1094/* -----------------------------------------------------------------------------
1095 * ISP video operations
1096 */
1097
1098static int resizer_video_queue(struct isp_video *video,
1099 struct isp_buffer *buffer)
1100{
1101 struct isp_res_device *res = &video->isp->isp_res;
1102
1103 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1104 resizer_set_inaddr(res, buffer->isp_addr);
1105
1106 /*
1107 * We now have a buffer queued on the output. Despite what the
1108 * TRM says, the resizer can't be restarted immediately.
1109 * Enabling it in one shot mode in the middle of a frame (or at
1110 * least asynchronously to the frame) results in the output
1111 * being shifted randomly left/right and up/down, as if the
1112 * hardware didn't synchronize itself to the beginning of the
1113 * frame correctly.
1114 *
1115 * Restart the resizer on the next sync interrupt if running in
1116 * continuous mode or when starting the stream.
1117 */
1118 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1119 resizer_set_outaddr(res, buffer->isp_addr);
1120
1121 return 0;
1122}
1123
1124static const struct isp_video_operations resizer_video_ops = {
1125 .queue = resizer_video_queue,
1126};
1127
1128/* -----------------------------------------------------------------------------
1129 * V4L2 subdev operations
1130 */
1131
1132/*
1133 * resizer_set_stream - Enable/Disable streaming on resizer subdev
1134 * @sd: ISP resizer V4L2 subdev
1135 * @enable: 1 == Enable, 0 == Disable
1136 *
1137 * The resizer hardware can't be enabled without a memory buffer to write to.
1138 * As the s_stream operation is called in response to a STREAMON call without
1139 * any buffer queued yet, just update the state field and return immediately.
1140 * The resizer will be enabled in resizer_video_queue().
1141 */
1142static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
1143{
1144 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1145 struct isp_video *video_out = &res->video_out;
1146 struct isp_device *isp = to_isp_device(res);
1147 struct device *dev = to_device(res);
1148
1149 if (res->state == ISP_PIPELINE_STREAM_STOPPED) {
1150 if (enable == ISP_PIPELINE_STREAM_STOPPED)
1151 return 0;
1152
1153 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER);
1154 resizer_configure(res);
1155 resizer_print_status(res);
1156 }
1157
1158 switch (enable) {
1159 case ISP_PIPELINE_STREAM_CONTINUOUS:
1160 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_WRITE);
1161 if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
1162 resizer_enable_oneshot(res);
1163 isp_video_dmaqueue_flags_clr(video_out);
1164 }
1165 break;
1166
1167 case ISP_PIPELINE_STREAM_SINGLESHOT:
1168 if (res->input == RESIZER_INPUT_MEMORY)
1169 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_READ);
1170 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_WRITE);
1171
1172 resizer_enable_oneshot(res);
1173 break;
1174
1175 case ISP_PIPELINE_STREAM_STOPPED:
1176 if (omap3isp_module_sync_idle(&sd->entity, &res->wait,
1177 &res->stopping))
1178 dev_dbg(dev, "%s: module stop timeout.\n", sd->name);
1179 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_RESIZER_READ |
1180 OMAP3_ISP_SBL_RESIZER_WRITE);
1181 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_RESIZER);
1182 isp_video_dmaqueue_flags_clr(video_out);
1183 break;
1184 }
1185
1186 res->state = enable;
1187 return 0;
1188}
1189
1190/*
1191 * resizer_try_crop - mangles crop parameters.
1192 */
1193static void resizer_try_crop(const struct v4l2_mbus_framefmt *sink,
1194 const struct v4l2_mbus_framefmt *source,
1195 struct v4l2_rect *crop)
1196{
1197 const unsigned int spv = DEFAULT_PHASE;
1198 const unsigned int sph = DEFAULT_PHASE;
1199
1200 /* Crop rectangle is constrained by the output size so that zoom ratio
1201 * cannot exceed +/-4.0.
1202 */
1203 unsigned int min_width =
1204 ((32 * sph + (source->width - 1) * 64 + 16) >> 8) + 7;
1205 unsigned int min_height =
1206 ((32 * spv + (source->height - 1) * 64 + 16) >> 8) + 4;
1207 unsigned int max_width =
1208 ((64 * sph + (source->width - 1) * 1024 + 32) >> 8) + 7;
1209 unsigned int max_height =
1210 ((64 * spv + (source->height - 1) * 1024 + 32) >> 8) + 7;
1211
1212 crop->width = clamp_t(u32, crop->width, min_width, max_width);
1213 crop->height = clamp_t(u32, crop->height, min_height, max_height);
1214
1215 /* Crop can not go beyond of the input rectangle */
1216 crop->left = clamp_t(u32, crop->left, 0, sink->width - MIN_IN_WIDTH);
1217 crop->width = clamp_t(u32, crop->width, MIN_IN_WIDTH,
1218 sink->width - crop->left);
1219 crop->top = clamp_t(u32, crop->top, 0, sink->height - MIN_IN_HEIGHT);
1220 crop->height = clamp_t(u32, crop->height, MIN_IN_HEIGHT,
1221 sink->height - crop->top);
1222}
1223
1224/*
1225 * resizer_get_selection - Retrieve a selection rectangle on a pad
1226 * @sd: ISP resizer V4L2 subdevice
1227 * @fh: V4L2 subdev file handle
1228 * @sel: Selection rectangle
1229 *
1230 * The only supported rectangles are the crop rectangles on the sink pad.
1231 *
1232 * Return 0 on success or a negative error code otherwise.
1233 */
1234static int resizer_get_selection(struct v4l2_subdev *sd,
1235 struct v4l2_subdev_fh *fh,
1236 struct v4l2_subdev_selection *sel)
1237{
1238 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1239 struct v4l2_mbus_framefmt *format_source;
1240 struct v4l2_mbus_framefmt *format_sink;
1241 struct resizer_ratio ratio;
1242
1243 if (sel->pad != RESZ_PAD_SINK)
1244 return -EINVAL;
1245
1246 format_sink = __resizer_get_format(res, fh, RESZ_PAD_SINK,
1247 sel->which);
1248 format_source = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
1249 sel->which);
1250
1251 switch (sel->target) {
1252 case V4L2_SEL_TGT_CROP_BOUNDS:
1253 sel->r.left = 0;
1254 sel->r.top = 0;
1255 sel->r.width = INT_MAX;
1256 sel->r.height = INT_MAX;
1257
1258 resizer_try_crop(format_sink, format_source, &sel->r);
1259 resizer_calc_ratios(res, &sel->r, format_source, &ratio);
1260 break;
1261
1262 case V4L2_SEL_TGT_CROP:
1263 sel->r = *__resizer_get_crop(res, fh, sel->which);
1264 resizer_calc_ratios(res, &sel->r, format_source, &ratio);
1265 break;
1266
1267 default:
1268 return -EINVAL;
1269 }
1270
1271 return 0;
1272}
1273
1274/*
1275 * resizer_set_selection - Set a selection rectangle on a pad
1276 * @sd: ISP resizer V4L2 subdevice
1277 * @fh: V4L2 subdev file handle
1278 * @sel: Selection rectangle
1279 *
1280 * The only supported rectangle is the actual crop rectangle on the sink pad.
1281 *
1282 * FIXME: This function currently behaves as if the KEEP_CONFIG selection flag
1283 * was always set.
1284 *
1285 * Return 0 on success or a negative error code otherwise.
1286 */
1287static int resizer_set_selection(struct v4l2_subdev *sd,
1288 struct v4l2_subdev_fh *fh,
1289 struct v4l2_subdev_selection *sel)
1290{
1291 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1292 struct isp_device *isp = to_isp_device(res);
1293 struct v4l2_mbus_framefmt *format_sink, *format_source;
1294 struct resizer_ratio ratio;
1295
1296 if (sel->target != V4L2_SEL_TGT_CROP ||
1297 sel->pad != RESZ_PAD_SINK)
1298 return -EINVAL;
1299
1300 format_sink = __resizer_get_format(res, fh, RESZ_PAD_SINK,
1301 sel->which);
1302 format_source = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
1303 sel->which);
1304
1305 dev_dbg(isp->dev, "%s: L=%d,T=%d,W=%d,H=%d,which=%d\n", __func__,
1306 sel->r.left, sel->r.top, sel->r.width, sel->r.height,
1307 sel->which);
1308
1309 dev_dbg(isp->dev, "%s: input=%dx%d, output=%dx%d\n", __func__,
1310 format_sink->width, format_sink->height,
1311 format_source->width, format_source->height);
1312
1313 /* Clamp the crop rectangle to the bounds, and then mangle it further to
1314 * fulfill the TRM equations. Store the clamped but otherwise unmangled
1315 * rectangle to avoid cropping the input multiple times: when an
1316 * application sets the output format, the current crop rectangle is
1317 * mangled during crop rectangle computation, which would lead to a new,
1318 * smaller input crop rectangle every time the output size is set if we
1319 * stored the mangled rectangle.
1320 */
1321 resizer_try_crop(format_sink, format_source, &sel->r);
1322 *__resizer_get_crop(res, fh, sel->which) = sel->r;
1323 resizer_calc_ratios(res, &sel->r, format_source, &ratio);
1324
1325 if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
1326 return 0;
1327
1328 res->ratio = ratio;
1329 res->crop.active = sel->r;
1330
1331 /*
1332 * set_selection can be called while streaming is on. In this case the
1333 * crop values will be set in the next IRQ.
1334 */
1335 if (res->state != ISP_PIPELINE_STREAM_STOPPED)
1336 res->applycrop = 1;
1337
1338 return 0;
1339}
1340
1341/* resizer pixel formats */
1342static const unsigned int resizer_formats[] = {
1343 V4L2_MBUS_FMT_UYVY8_1X16,
1344 V4L2_MBUS_FMT_YUYV8_1X16,
1345};
1346
1347static unsigned int resizer_max_in_width(struct isp_res_device *res)
1348{
1349 struct isp_device *isp = to_isp_device(res);
1350
1351 if (res->input == RESIZER_INPUT_MEMORY) {
1352 return MAX_IN_WIDTH_MEMORY_MODE;
1353 } else {
1354 if (isp->revision == ISP_REVISION_1_0)
1355 return MAX_IN_WIDTH_ONTHEFLY_MODE_ES1;
1356 else
1357 return MAX_IN_WIDTH_ONTHEFLY_MODE_ES2;
1358 }
1359}
1360
1361/*
1362 * resizer_try_format - Handle try format by pad subdev method
1363 * @res : ISP resizer device
1364 * @fh : V4L2 subdev file handle
1365 * @pad : pad num
1366 * @fmt : pointer to v4l2 format structure
1367 * @which : wanted subdev format
1368 */
1369static void resizer_try_format(struct isp_res_device *res,
1370 struct v4l2_subdev_fh *fh, unsigned int pad,
1371 struct v4l2_mbus_framefmt *fmt,
1372 enum v4l2_subdev_format_whence which)
1373{
1374 struct v4l2_mbus_framefmt *format;
1375 struct resizer_ratio ratio;
1376 struct v4l2_rect crop;
1377
1378 switch (pad) {
1379 case RESZ_PAD_SINK:
1380 if (fmt->code != V4L2_MBUS_FMT_YUYV8_1X16 &&
1381 fmt->code != V4L2_MBUS_FMT_UYVY8_1X16)
1382 fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
1383
1384 fmt->width = clamp_t(u32, fmt->width, MIN_IN_WIDTH,
1385 resizer_max_in_width(res));
1386 fmt->height = clamp_t(u32, fmt->height, MIN_IN_HEIGHT,
1387 MAX_IN_HEIGHT);
1388 break;
1389
1390 case RESZ_PAD_SOURCE:
1391 format = __resizer_get_format(res, fh, RESZ_PAD_SINK, which);
1392 fmt->code = format->code;
1393
1394 crop = *__resizer_get_crop(res, fh, which);
1395 resizer_calc_ratios(res, &crop, fmt, &ratio);
1396 break;
1397 }
1398
1399 fmt->colorspace = V4L2_COLORSPACE_JPEG;
1400 fmt->field = V4L2_FIELD_NONE;
1401}
1402
1403/*
1404 * resizer_enum_mbus_code - Handle pixel format enumeration
1405 * @sd : pointer to v4l2 subdev structure
1406 * @fh : V4L2 subdev file handle
1407 * @code : pointer to v4l2_subdev_mbus_code_enum structure
1408 * return -EINVAL or zero on success
1409 */
1410static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
1411 struct v4l2_subdev_fh *fh,
1412 struct v4l2_subdev_mbus_code_enum *code)
1413{
1414 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1415 struct v4l2_mbus_framefmt *format;
1416
1417 if (code->pad == RESZ_PAD_SINK) {
1418 if (code->index >= ARRAY_SIZE(resizer_formats))
1419 return -EINVAL;
1420
1421 code->code = resizer_formats[code->index];
1422 } else {
1423 if (code->index != 0)
1424 return -EINVAL;
1425
1426 format = __resizer_get_format(res, fh, RESZ_PAD_SINK,
1427 V4L2_SUBDEV_FORMAT_TRY);
1428 code->code = format->code;
1429 }
1430
1431 return 0;
1432}
1433
1434static int resizer_enum_frame_size(struct v4l2_subdev *sd,
1435 struct v4l2_subdev_fh *fh,
1436 struct v4l2_subdev_frame_size_enum *fse)
1437{
1438 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1439 struct v4l2_mbus_framefmt format;
1440
1441 if (fse->index != 0)
1442 return -EINVAL;
1443
1444 format.code = fse->code;
1445 format.width = 1;
1446 format.height = 1;
1447 resizer_try_format(res, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1448 fse->min_width = format.width;
1449 fse->min_height = format.height;
1450
1451 if (format.code != fse->code)
1452 return -EINVAL;
1453
1454 format.code = fse->code;
1455 format.width = -1;
1456 format.height = -1;
1457 resizer_try_format(res, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1458 fse->max_width = format.width;
1459 fse->max_height = format.height;
1460
1461 return 0;
1462}
1463
1464/*
1465 * resizer_get_format - Handle get format by pads subdev method
1466 * @sd : pointer to v4l2 subdev structure
1467 * @fh : V4L2 subdev file handle
1468 * @fmt : pointer to v4l2 subdev format structure
1469 * return -EINVAL or zero on success
1470 */
1471static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1472 struct v4l2_subdev_format *fmt)
1473{
1474 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1475 struct v4l2_mbus_framefmt *format;
1476
1477 format = __resizer_get_format(res, fh, fmt->pad, fmt->which);
1478 if (format == NULL)
1479 return -EINVAL;
1480
1481 fmt->format = *format;
1482 return 0;
1483}
1484
1485/*
1486 * resizer_set_format - Handle set format by pads subdev method
1487 * @sd : pointer to v4l2 subdev structure
1488 * @fh : V4L2 subdev file handle
1489 * @fmt : pointer to v4l2 subdev format structure
1490 * return -EINVAL or zero on success
1491 */
1492static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1493 struct v4l2_subdev_format *fmt)
1494{
1495 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1496 struct v4l2_mbus_framefmt *format;
1497 struct v4l2_rect *crop;
1498
1499 format = __resizer_get_format(res, fh, fmt->pad, fmt->which);
1500 if (format == NULL)
1501 return -EINVAL;
1502
1503 resizer_try_format(res, fh, fmt->pad, &fmt->format, fmt->which);
1504 *format = fmt->format;
1505
1506 if (fmt->pad == RESZ_PAD_SINK) {
1507 /* reset crop rectangle */
1508 crop = __resizer_get_crop(res, fh, fmt->which);
1509 crop->left = 0;
1510 crop->top = 0;
1511 crop->width = fmt->format.width;
1512 crop->height = fmt->format.height;
1513
1514 /* Propagate the format from sink to source */
1515 format = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
1516 fmt->which);
1517 *format = fmt->format;
1518 resizer_try_format(res, fh, RESZ_PAD_SOURCE, format,
1519 fmt->which);
1520 }
1521
1522 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
1523 /* Compute and store the active crop rectangle and resizer
1524 * ratios. format already points to the source pad active
1525 * format.
1526 */
1527 res->crop.active = res->crop.request;
1528 resizer_calc_ratios(res, &res->crop.active, format,
1529 &res->ratio);
1530 }
1531
1532 return 0;
1533}
1534
1535/*
1536 * resizer_init_formats - Initialize formats on all pads
1537 * @sd: ISP resizer V4L2 subdevice
1538 * @fh: V4L2 subdev file handle
1539 *
1540 * Initialize all pad formats with default values. If fh is not NULL, try
1541 * formats are initialized on the file handle. Otherwise active formats are
1542 * initialized on the device.
1543 */
1544static int resizer_init_formats(struct v4l2_subdev *sd,
1545 struct v4l2_subdev_fh *fh)
1546{
1547 struct v4l2_subdev_format format;
1548
1549 memset(&format, 0, sizeof(format));
1550 format.pad = RESZ_PAD_SINK;
1551 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1552 format.format.code = V4L2_MBUS_FMT_YUYV8_1X16;
1553 format.format.width = 4096;
1554 format.format.height = 4096;
1555 resizer_set_format(sd, fh, &format);
1556
1557 return 0;
1558}
1559
1560/* subdev video operations */
1561static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = {
1562 .s_stream = resizer_set_stream,
1563};
1564
1565/* subdev pad operations */
1566static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = {
1567 .enum_mbus_code = resizer_enum_mbus_code,
1568 .enum_frame_size = resizer_enum_frame_size,
1569 .get_fmt = resizer_get_format,
1570 .set_fmt = resizer_set_format,
1571 .get_selection = resizer_get_selection,
1572 .set_selection = resizer_set_selection,
1573};
1574
1575/* subdev operations */
1576static const struct v4l2_subdev_ops resizer_v4l2_ops = {
1577 .video = &resizer_v4l2_video_ops,
1578 .pad = &resizer_v4l2_pad_ops,
1579};
1580
1581/* subdev internal operations */
1582static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = {
1583 .open = resizer_init_formats,
1584};
1585
1586/* -----------------------------------------------------------------------------
1587 * Media entity operations
1588 */
1589
1590/*
1591 * resizer_link_setup - Setup resizer connections.
1592 * @entity : Pointer to media entity structure
1593 * @local : Pointer to local pad array
1594 * @remote : Pointer to remote pad array
1595 * @flags : Link flags
1596 * return -EINVAL or zero on success
1597 */
1598static int resizer_link_setup(struct media_entity *entity,
1599 const struct media_pad *local,
1600 const struct media_pad *remote, u32 flags)
1601{
1602 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1603 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1604
1605 switch (local->index | media_entity_type(remote->entity)) {
1606 case RESZ_PAD_SINK | MEDIA_ENT_T_DEVNODE:
1607 /* read from memory */
1608 if (flags & MEDIA_LNK_FL_ENABLED) {
1609 if (res->input == RESIZER_INPUT_VP)
1610 return -EBUSY;
1611 res->input = RESIZER_INPUT_MEMORY;
1612 } else {
1613 if (res->input == RESIZER_INPUT_MEMORY)
1614 res->input = RESIZER_INPUT_NONE;
1615 }
1616 break;
1617
1618 case RESZ_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
1619 /* read from ccdc or previewer */
1620 if (flags & MEDIA_LNK_FL_ENABLED) {
1621 if (res->input == RESIZER_INPUT_MEMORY)
1622 return -EBUSY;
1623 res->input = RESIZER_INPUT_VP;
1624 } else {
1625 if (res->input == RESIZER_INPUT_VP)
1626 res->input = RESIZER_INPUT_NONE;
1627 }
1628 break;
1629
1630 case RESZ_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
1631 /* resizer always write to memory */
1632 break;
1633
1634 default:
1635 return -EINVAL;
1636 }
1637
1638 return 0;
1639}
1640
1641/* media operations */
1642static const struct media_entity_operations resizer_media_ops = {
1643 .link_setup = resizer_link_setup,
1644 .link_validate = v4l2_subdev_link_validate,
1645};
1646
1647void omap3isp_resizer_unregister_entities(struct isp_res_device *res)
1648{
1649 v4l2_device_unregister_subdev(&res->subdev);
1650 omap3isp_video_unregister(&res->video_in);
1651 omap3isp_video_unregister(&res->video_out);
1652}
1653
1654int omap3isp_resizer_register_entities(struct isp_res_device *res,
1655 struct v4l2_device *vdev)
1656{
1657 int ret;
1658
1659 /* Register the subdev and video nodes. */
1660 ret = v4l2_device_register_subdev(vdev, &res->subdev);
1661 if (ret < 0)
1662 goto error;
1663
1664 ret = omap3isp_video_register(&res->video_in, vdev);
1665 if (ret < 0)
1666 goto error;
1667
1668 ret = omap3isp_video_register(&res->video_out, vdev);
1669 if (ret < 0)
1670 goto error;
1671
1672 return 0;
1673
1674error:
1675 omap3isp_resizer_unregister_entities(res);
1676 return ret;
1677}
1678
1679/* -----------------------------------------------------------------------------
1680 * ISP resizer initialization and cleanup
1681 */
1682
1683/*
1684 * resizer_init_entities - Initialize resizer subdev and media entity.
1685 * @res : Pointer to resizer device structure
1686 * return -ENOMEM or zero on success
1687 */
1688static int resizer_init_entities(struct isp_res_device *res)
1689{
1690 struct v4l2_subdev *sd = &res->subdev;
1691 struct media_pad *pads = res->pads;
1692 struct media_entity *me = &sd->entity;
1693 int ret;
1694
1695 res->input = RESIZER_INPUT_NONE;
1696
1697 v4l2_subdev_init(sd, &resizer_v4l2_ops);
1698 sd->internal_ops = &resizer_v4l2_internal_ops;
1699 strlcpy(sd->name, "OMAP3 ISP resizer", sizeof(sd->name));
1700 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
1701 v4l2_set_subdevdata(sd, res);
1702 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1703
1704 pads[RESZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1705 pads[RESZ_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1706
1707 me->ops = &resizer_media_ops;
1708 ret = media_entity_init(me, RESZ_PADS_NUM, pads, 0);
1709 if (ret < 0)
1710 return ret;
1711
1712 resizer_init_formats(sd, NULL);
1713
1714 res->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1715 res->video_in.ops = &resizer_video_ops;
1716 res->video_in.isp = to_isp_device(res);
1717 res->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
1718 res->video_in.bpl_alignment = 32;
1719 res->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1720 res->video_out.ops = &resizer_video_ops;
1721 res->video_out.isp = to_isp_device(res);
1722 res->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
1723 res->video_out.bpl_alignment = 32;
1724
1725 ret = omap3isp_video_init(&res->video_in, "resizer");
1726 if (ret < 0)
1727 goto error_video_in;
1728
1729 ret = omap3isp_video_init(&res->video_out, "resizer");
1730 if (ret < 0)
1731 goto error_video_out;
1732
1733 res->video_out.video.entity.flags |= MEDIA_ENT_FL_DEFAULT;
1734
1735 /* Connect the video nodes to the resizer subdev. */
1736 ret = media_entity_create_link(&res->video_in.video.entity, 0,
1737 &res->subdev.entity, RESZ_PAD_SINK, 0);
1738 if (ret < 0)
1739 goto error_link;
1740
1741 ret = media_entity_create_link(&res->subdev.entity, RESZ_PAD_SOURCE,
1742 &res->video_out.video.entity, 0, 0);
1743 if (ret < 0)
1744 goto error_link;
1745
1746 return 0;
1747
1748error_link:
1749 omap3isp_video_cleanup(&res->video_out);
1750error_video_out:
1751 omap3isp_video_cleanup(&res->video_in);
1752error_video_in:
1753 media_entity_cleanup(&res->subdev.entity);
1754 return ret;
1755}
1756
1757/*
1758 * isp_resizer_init - Resizer initialization.
1759 * @isp : Pointer to ISP device
1760 * return -ENOMEM or zero on success
1761 */
1762int omap3isp_resizer_init(struct isp_device *isp)
1763{
1764 struct isp_res_device *res = &isp->isp_res;
1765
1766 init_waitqueue_head(&res->wait);
1767 atomic_set(&res->stopping, 0);
1768 return resizer_init_entities(res);
1769}
1770
1771void omap3isp_resizer_cleanup(struct isp_device *isp)
1772{
1773 struct isp_res_device *res = &isp->isp_res;
1774
1775 omap3isp_video_cleanup(&res->video_in);
1776 omap3isp_video_cleanup(&res->video_out);
1777 media_entity_cleanup(&res->subdev.entity);
1778}
diff --git a/drivers/media/platform/omap3isp/ispresizer.h b/drivers/media/platform/omap3isp/ispresizer.h
new file mode 100644
index 000000000000..70c1c0e1bbdf
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispresizer.h
@@ -0,0 +1,146 @@
1/*
2 * ispresizer.h
3 *
4 * TI OMAP3 ISP - Resizer module
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#ifndef OMAP3_ISP_RESIZER_H
28#define OMAP3_ISP_RESIZER_H
29
30#include <linux/types.h>
31
32/*
33 * Constants for filter coefficents count
34 */
35#define COEFF_CNT 32
36
37/*
38 * struct isprsz_coef - Structure for resizer filter coeffcients.
39 * @h_filter_coef_4tap: Horizontal filter coefficients for 8-phase/4-tap
40 * mode (.5x-4x)
41 * @v_filter_coef_4tap: Vertical filter coefficients for 8-phase/4-tap
42 * mode (.5x-4x)
43 * @h_filter_coef_7tap: Horizontal filter coefficients for 4-phase/7-tap
44 * mode (.25x-.5x)
45 * @v_filter_coef_7tap: Vertical filter coefficients for 4-phase/7-tap
46 * mode (.25x-.5x)
47 */
48struct isprsz_coef {
49 u16 h_filter_coef_4tap[32];
50 u16 v_filter_coef_4tap[32];
51 /* Every 8th value is a dummy value in the following arrays: */
52 u16 h_filter_coef_7tap[32];
53 u16 v_filter_coef_7tap[32];
54};
55
56/* Chrominance horizontal algorithm */
57enum resizer_chroma_algo {
58 RSZ_THE_SAME = 0, /* Chrominance the same as Luminance */
59 RSZ_BILINEAR = 1, /* Chrominance uses bilinear interpolation */
60};
61
62/* Resizer input type select */
63enum resizer_colors_type {
64 RSZ_YUV422 = 0, /* YUV422 color is interleaved */
65 RSZ_COLOR8 = 1, /* Color separate data on 8 bits */
66};
67
68/*
69 * Structure for horizontal and vertical resizing value
70 */
71struct resizer_ratio {
72 u32 horz;
73 u32 vert;
74};
75
76/*
77 * Structure for luminance enhancer parameters.
78 */
79struct resizer_luma_yenh {
80 u8 algo; /* algorithm select. */
81 u8 gain; /* maximum gain. */
82 u8 slope; /* slope. */
83 u8 core; /* core offset. */
84};
85
86enum resizer_input_entity {
87 RESIZER_INPUT_NONE,
88 RESIZER_INPUT_VP, /* input video port - prev or ccdc */
89 RESIZER_INPUT_MEMORY,
90};
91
92/* Sink and source resizer pads */
93#define RESZ_PAD_SINK 0
94#define RESZ_PAD_SOURCE 1
95#define RESZ_PADS_NUM 2
96
97/*
98 * struct isp_res_device - OMAP3 ISP resizer module
99 * @crop.request: Crop rectangle requested by the user
100 * @crop.active: Active crop rectangle (based on hardware requirements)
101 */
102struct isp_res_device {
103 struct v4l2_subdev subdev;
104 struct media_pad pads[RESZ_PADS_NUM];
105 struct v4l2_mbus_framefmt formats[RESZ_PADS_NUM];
106
107 enum resizer_input_entity input;
108 struct isp_video video_in;
109 struct isp_video video_out;
110
111 u32 addr_base; /* stored source buffer address in memory mode */
112 u32 crop_offset; /* additional offset for crop in memory mode */
113 struct resizer_ratio ratio;
114 int pm_state;
115 unsigned int applycrop:1;
116 enum isp_pipeline_stream_state state;
117 wait_queue_head_t wait;
118 atomic_t stopping;
119
120 struct {
121 struct v4l2_rect request;
122 struct v4l2_rect active;
123 } crop;
124};
125
126struct isp_device;
127
128int omap3isp_resizer_init(struct isp_device *isp);
129void omap3isp_resizer_cleanup(struct isp_device *isp);
130
131int omap3isp_resizer_register_entities(struct isp_res_device *res,
132 struct v4l2_device *vdev);
133void omap3isp_resizer_unregister_entities(struct isp_res_device *res);
134void omap3isp_resizer_isr_frame_sync(struct isp_res_device *res);
135void omap3isp_resizer_isr(struct isp_res_device *isp_res);
136
137void omap3isp_resizer_max_rate(struct isp_res_device *res,
138 unsigned int *max_rate);
139
140void omap3isp_resizer_suspend(struct isp_res_device *isp_res);
141
142void omap3isp_resizer_resume(struct isp_res_device *isp_res);
143
144int omap3isp_resizer_busy(struct isp_res_device *isp_res);
145
146#endif /* OMAP3_ISP_RESIZER_H */
diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
new file mode 100644
index 000000000000..d7ac76b5c2ae
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -0,0 +1,1102 @@
1/*
2 * ispstat.c
3 *
4 * TI OMAP3 ISP - Statistics core
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc
8 *
9 * Contacts: David Cohen <dacohen@gmail.com>
10 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11 * Sakari Ailus <sakari.ailus@iki.fi>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 * 02110-1301 USA
26 */
27
28#include <linux/dma-mapping.h>
29#include <linux/slab.h>
30#include <linux/uaccess.h>
31
32#include "isp.h"
33
34#define IS_COHERENT_BUF(stat) ((stat)->dma_ch >= 0)
35
36/*
37 * MAGIC_SIZE must always be the greatest common divisor of
38 * AEWB_PACKET_SIZE and AF_PAXEL_SIZE.
39 */
40#define MAGIC_SIZE 16
41#define MAGIC_NUM 0x55
42
43/* HACK: AF module seems to be writing one more paxel data than it should. */
44#define AF_EXTRA_DATA OMAP3ISP_AF_PAXEL_SIZE
45
46/*
47 * HACK: H3A modules go to an invalid state after have a SBL overflow. It makes
48 * the next buffer to start to be written in the same point where the overflow
49 * occurred instead of the configured address. The only known way to make it to
50 * go back to a valid state is having a valid buffer processing. Of course it
51 * requires at least a doubled buffer size to avoid an access to invalid memory
52 * region. But it does not fix everything. It may happen more than one
53 * consecutive SBL overflows. In that case, it might be unpredictable how many
54 * buffers the allocated memory should fit. For that case, a recover
55 * configuration was created. It produces the minimum buffer size for each H3A
56 * module and decrease the change for more SBL overflows. This recover state
57 * will be enabled every time a SBL overflow occur. As the output buffer size
58 * isn't big, it's possible to have an extra size able to fit many recover
59 * buffers making it extreamily unlikely to have an access to invalid memory
60 * region.
61 */
62#define NUM_H3A_RECOVER_BUFS 10
63
64/*
65 * HACK: Because of HW issues the generic layer sometimes need to have
66 * different behaviour for different statistic modules.
67 */
68#define IS_H3A_AF(stat) ((stat) == &(stat)->isp->isp_af)
69#define IS_H3A_AEWB(stat) ((stat) == &(stat)->isp->isp_aewb)
70#define IS_H3A(stat) (IS_H3A_AF(stat) || IS_H3A_AEWB(stat))
71
72static void __isp_stat_buf_sync_magic(struct ispstat *stat,
73 struct ispstat_buffer *buf,
74 u32 buf_size, enum dma_data_direction dir,
75 void (*dma_sync)(struct device *,
76 dma_addr_t, unsigned long, size_t,
77 enum dma_data_direction))
78{
79 struct device *dev = stat->isp->dev;
80 struct page *pg;
81 dma_addr_t dma_addr;
82 u32 offset;
83
84 /* Initial magic words */
85 pg = vmalloc_to_page(buf->virt_addr);
86 dma_addr = pfn_to_dma(dev, page_to_pfn(pg));
87 dma_sync(dev, dma_addr, 0, MAGIC_SIZE, dir);
88
89 /* Final magic words */
90 pg = vmalloc_to_page(buf->virt_addr + buf_size);
91 dma_addr = pfn_to_dma(dev, page_to_pfn(pg));
92 offset = ((u32)buf->virt_addr + buf_size) & ~PAGE_MASK;
93 dma_sync(dev, dma_addr, offset, MAGIC_SIZE, dir);
94}
95
96static void isp_stat_buf_sync_magic_for_device(struct ispstat *stat,
97 struct ispstat_buffer *buf,
98 u32 buf_size,
99 enum dma_data_direction dir)
100{
101 if (IS_COHERENT_BUF(stat))
102 return;
103
104 __isp_stat_buf_sync_magic(stat, buf, buf_size, dir,
105 dma_sync_single_range_for_device);
106}
107
108static void isp_stat_buf_sync_magic_for_cpu(struct ispstat *stat,
109 struct ispstat_buffer *buf,
110 u32 buf_size,
111 enum dma_data_direction dir)
112{
113 if (IS_COHERENT_BUF(stat))
114 return;
115
116 __isp_stat_buf_sync_magic(stat, buf, buf_size, dir,
117 dma_sync_single_range_for_cpu);
118}
119
120static int isp_stat_buf_check_magic(struct ispstat *stat,
121 struct ispstat_buffer *buf)
122{
123 const u32 buf_size = IS_H3A_AF(stat) ?
124 buf->buf_size + AF_EXTRA_DATA : buf->buf_size;
125 u8 *w;
126 u8 *end;
127 int ret = -EINVAL;
128
129 isp_stat_buf_sync_magic_for_cpu(stat, buf, buf_size, DMA_FROM_DEVICE);
130
131 /* Checking initial magic numbers. They shouldn't be here anymore. */
132 for (w = buf->virt_addr, end = w + MAGIC_SIZE; w < end; w++)
133 if (likely(*w != MAGIC_NUM))
134 ret = 0;
135
136 if (ret) {
137 dev_dbg(stat->isp->dev, "%s: beginning magic check does not "
138 "match.\n", stat->subdev.name);
139 return ret;
140 }
141
142 /* Checking magic numbers at the end. They must be still here. */
143 for (w = buf->virt_addr + buf_size, end = w + MAGIC_SIZE;
144 w < end; w++) {
145 if (unlikely(*w != MAGIC_NUM)) {
146 dev_dbg(stat->isp->dev, "%s: endding magic check does "
147 "not match.\n", stat->subdev.name);
148 return -EINVAL;
149 }
150 }
151
152 isp_stat_buf_sync_magic_for_device(stat, buf, buf_size,
153 DMA_FROM_DEVICE);
154
155 return 0;
156}
157
158static void isp_stat_buf_insert_magic(struct ispstat *stat,
159 struct ispstat_buffer *buf)
160{
161 const u32 buf_size = IS_H3A_AF(stat) ?
162 stat->buf_size + AF_EXTRA_DATA : stat->buf_size;
163
164 isp_stat_buf_sync_magic_for_cpu(stat, buf, buf_size, DMA_FROM_DEVICE);
165
166 /*
167 * Inserting MAGIC_NUM at the beginning and end of the buffer.
168 * buf->buf_size is set only after the buffer is queued. For now the
169 * right buf_size for the current configuration is pointed by
170 * stat->buf_size.
171 */
172 memset(buf->virt_addr, MAGIC_NUM, MAGIC_SIZE);
173 memset(buf->virt_addr + buf_size, MAGIC_NUM, MAGIC_SIZE);
174
175 isp_stat_buf_sync_magic_for_device(stat, buf, buf_size,
176 DMA_BIDIRECTIONAL);
177}
178
179static void isp_stat_buf_sync_for_device(struct ispstat *stat,
180 struct ispstat_buffer *buf)
181{
182 if (IS_COHERENT_BUF(stat))
183 return;
184
185 dma_sync_sg_for_device(stat->isp->dev, buf->iovm->sgt->sgl,
186 buf->iovm->sgt->nents, DMA_FROM_DEVICE);
187}
188
189static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
190 struct ispstat_buffer *buf)
191{
192 if (IS_COHERENT_BUF(stat))
193 return;
194
195 dma_sync_sg_for_cpu(stat->isp->dev, buf->iovm->sgt->sgl,
196 buf->iovm->sgt->nents, DMA_FROM_DEVICE);
197}
198
199static void isp_stat_buf_clear(struct ispstat *stat)
200{
201 int i;
202
203 for (i = 0; i < STAT_MAX_BUFS; i++)
204 stat->buf[i].empty = 1;
205}
206
207static struct ispstat_buffer *
208__isp_stat_buf_find(struct ispstat *stat, int look_empty)
209{
210 struct ispstat_buffer *found = NULL;
211 int i;
212
213 for (i = 0; i < STAT_MAX_BUFS; i++) {
214 struct ispstat_buffer *curr = &stat->buf[i];
215
216 /*
217 * Don't select the buffer which is being copied to
218 * userspace or used by the module.
219 */
220 if (curr == stat->locked_buf || curr == stat->active_buf)
221 continue;
222
223 /* Don't select uninitialised buffers if it's not required */
224 if (!look_empty && curr->empty)
225 continue;
226
227 /* Pick uninitialised buffer over anything else if look_empty */
228 if (curr->empty) {
229 found = curr;
230 break;
231 }
232
233 /* Choose the oldest buffer */
234 if (!found ||
235 (s32)curr->frame_number - (s32)found->frame_number < 0)
236 found = curr;
237 }
238
239 return found;
240}
241
242static inline struct ispstat_buffer *
243isp_stat_buf_find_oldest(struct ispstat *stat)
244{
245 return __isp_stat_buf_find(stat, 0);
246}
247
248static inline struct ispstat_buffer *
249isp_stat_buf_find_oldest_or_empty(struct ispstat *stat)
250{
251 return __isp_stat_buf_find(stat, 1);
252}
253
254static int isp_stat_buf_queue(struct ispstat *stat)
255{
256 if (!stat->active_buf)
257 return STAT_NO_BUF;
258
259 do_gettimeofday(&stat->active_buf->ts);
260
261 stat->active_buf->buf_size = stat->buf_size;
262 if (isp_stat_buf_check_magic(stat, stat->active_buf)) {
263 dev_dbg(stat->isp->dev, "%s: data wasn't properly written.\n",
264 stat->subdev.name);
265 return STAT_NO_BUF;
266 }
267 stat->active_buf->config_counter = stat->config_counter;
268 stat->active_buf->frame_number = stat->frame_number;
269 stat->active_buf->empty = 0;
270 stat->active_buf = NULL;
271
272 return STAT_BUF_DONE;
273}
274
275/* Get next free buffer to write the statistics to and mark it active. */
276static void isp_stat_buf_next(struct ispstat *stat)
277{
278 if (unlikely(stat->active_buf))
279 /* Overwriting unused active buffer */
280 dev_dbg(stat->isp->dev, "%s: new buffer requested without "
281 "queuing active one.\n",
282 stat->subdev.name);
283 else
284 stat->active_buf = isp_stat_buf_find_oldest_or_empty(stat);
285}
286
287static void isp_stat_buf_release(struct ispstat *stat)
288{
289 unsigned long flags;
290
291 isp_stat_buf_sync_for_device(stat, stat->locked_buf);
292 spin_lock_irqsave(&stat->isp->stat_lock, flags);
293 stat->locked_buf = NULL;
294 spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
295}
296
297/* Get buffer to userspace. */
298static struct ispstat_buffer *isp_stat_buf_get(struct ispstat *stat,
299 struct omap3isp_stat_data *data)
300{
301 int rval = 0;
302 unsigned long flags;
303 struct ispstat_buffer *buf;
304
305 spin_lock_irqsave(&stat->isp->stat_lock, flags);
306
307 while (1) {
308 buf = isp_stat_buf_find_oldest(stat);
309 if (!buf) {
310 spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
311 dev_dbg(stat->isp->dev, "%s: cannot find a buffer.\n",
312 stat->subdev.name);
313 return ERR_PTR(-EBUSY);
314 }
315 if (isp_stat_buf_check_magic(stat, buf)) {
316 dev_dbg(stat->isp->dev, "%s: current buffer has "
317 "corrupted data\n.", stat->subdev.name);
318 /* Mark empty because it doesn't have valid data. */
319 buf->empty = 1;
320 } else {
321 /* Buffer isn't corrupted. */
322 break;
323 }
324 }
325
326 stat->locked_buf = buf;
327
328 spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
329
330 if (buf->buf_size > data->buf_size) {
331 dev_warn(stat->isp->dev, "%s: userspace's buffer size is "
332 "not enough.\n", stat->subdev.name);
333 isp_stat_buf_release(stat);
334 return ERR_PTR(-EINVAL);
335 }
336
337 isp_stat_buf_sync_for_cpu(stat, buf);
338
339 rval = copy_to_user(data->buf,
340 buf->virt_addr,
341 buf->buf_size);
342
343 if (rval) {
344 dev_info(stat->isp->dev,
345 "%s: failed copying %d bytes of stat data\n",
346 stat->subdev.name, rval);
347 buf = ERR_PTR(-EFAULT);
348 isp_stat_buf_release(stat);
349 }
350
351 return buf;
352}
353
354static void isp_stat_bufs_free(struct ispstat *stat)
355{
356 struct isp_device *isp = stat->isp;
357 int i;
358
359 for (i = 0; i < STAT_MAX_BUFS; i++) {
360 struct ispstat_buffer *buf = &stat->buf[i];
361
362 if (!IS_COHERENT_BUF(stat)) {
363 if (IS_ERR_OR_NULL((void *)buf->iommu_addr))
364 continue;
365 if (buf->iovm)
366 dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
367 buf->iovm->sgt->nents,
368 DMA_FROM_DEVICE);
369 omap_iommu_vfree(isp->domain, isp->dev,
370 buf->iommu_addr);
371 } else {
372 if (!buf->virt_addr)
373 continue;
374 dma_free_coherent(stat->isp->dev, stat->buf_alloc_size,
375 buf->virt_addr, buf->dma_addr);
376 }
377 buf->iommu_addr = 0;
378 buf->iovm = NULL;
379 buf->dma_addr = 0;
380 buf->virt_addr = NULL;
381 buf->empty = 1;
382 }
383
384 dev_dbg(stat->isp->dev, "%s: all buffers were freed.\n",
385 stat->subdev.name);
386
387 stat->buf_alloc_size = 0;
388 stat->active_buf = NULL;
389}
390
391static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
392{
393 struct isp_device *isp = stat->isp;
394 int i;
395
396 stat->buf_alloc_size = size;
397
398 for (i = 0; i < STAT_MAX_BUFS; i++) {
399 struct ispstat_buffer *buf = &stat->buf[i];
400 struct iovm_struct *iovm;
401
402 WARN_ON(buf->dma_addr);
403 buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
404 size, IOMMU_FLAG);
405 if (IS_ERR((void *)buf->iommu_addr)) {
406 dev_err(stat->isp->dev,
407 "%s: Can't acquire memory for "
408 "buffer %d\n", stat->subdev.name, i);
409 isp_stat_bufs_free(stat);
410 return -ENOMEM;
411 }
412
413 iovm = omap_find_iovm_area(isp->dev, buf->iommu_addr);
414 if (!iovm ||
415 !dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
416 DMA_FROM_DEVICE)) {
417 isp_stat_bufs_free(stat);
418 return -ENOMEM;
419 }
420 buf->iovm = iovm;
421
422 buf->virt_addr = omap_da_to_va(stat->isp->dev,
423 (u32)buf->iommu_addr);
424 buf->empty = 1;
425 dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
426 "iommu_addr=0x%08lx virt_addr=0x%08lx",
427 stat->subdev.name, i, buf->iommu_addr,
428 (unsigned long)buf->virt_addr);
429 }
430
431 return 0;
432}
433
434static int isp_stat_bufs_alloc_dma(struct ispstat *stat, unsigned int size)
435{
436 int i;
437
438 stat->buf_alloc_size = size;
439
440 for (i = 0; i < STAT_MAX_BUFS; i++) {
441 struct ispstat_buffer *buf = &stat->buf[i];
442
443 WARN_ON(buf->iommu_addr);
444 buf->virt_addr = dma_alloc_coherent(stat->isp->dev, size,
445 &buf->dma_addr, GFP_KERNEL | GFP_DMA);
446
447 if (!buf->virt_addr || !buf->dma_addr) {
448 dev_info(stat->isp->dev,
449 "%s: Can't acquire memory for "
450 "DMA buffer %d\n", stat->subdev.name, i);
451 isp_stat_bufs_free(stat);
452 return -ENOMEM;
453 }
454 buf->empty = 1;
455
456 dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
457 "dma_addr=0x%08lx virt_addr=0x%08lx\n",
458 stat->subdev.name, i, (unsigned long)buf->dma_addr,
459 (unsigned long)buf->virt_addr);
460 }
461
462 return 0;
463}
464
465static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
466{
467 unsigned long flags;
468
469 spin_lock_irqsave(&stat->isp->stat_lock, flags);
470
471 BUG_ON(stat->locked_buf != NULL);
472
473 /* Are the old buffers big enough? */
474 if (stat->buf_alloc_size >= size) {
475 spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
476 return 0;
477 }
478
479 if (stat->state != ISPSTAT_DISABLED || stat->buf_processing) {
480 dev_info(stat->isp->dev,
481 "%s: trying to allocate memory when busy\n",
482 stat->subdev.name);
483 spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
484 return -EBUSY;
485 }
486
487 spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
488
489 isp_stat_bufs_free(stat);
490
491 if (IS_COHERENT_BUF(stat))
492 return isp_stat_bufs_alloc_dma(stat, size);
493 else
494 return isp_stat_bufs_alloc_iommu(stat, size);
495}
496
497static void isp_stat_queue_event(struct ispstat *stat, int err)
498{
499 struct video_device *vdev = stat->subdev.devnode;
500 struct v4l2_event event;
501 struct omap3isp_stat_event_status *status = (void *)event.u.data;
502
503 memset(&event, 0, sizeof(event));
504 if (!err) {
505 status->frame_number = stat->frame_number;
506 status->config_counter = stat->config_counter;
507 } else {
508 status->buf_err = 1;
509 }
510 event.type = stat->event_type;
511 v4l2_event_queue(vdev, &event);
512}
513
514
515/*
516 * omap3isp_stat_request_statistics - Request statistics.
517 * @data: Pointer to return statistics data.
518 *
519 * Returns 0 if successful.
520 */
521int omap3isp_stat_request_statistics(struct ispstat *stat,
522 struct omap3isp_stat_data *data)
523{
524 struct ispstat_buffer *buf;
525
526 if (stat->state != ISPSTAT_ENABLED) {
527 dev_dbg(stat->isp->dev, "%s: engine not enabled.\n",
528 stat->subdev.name);
529 return -EINVAL;
530 }
531
532 mutex_lock(&stat->ioctl_lock);
533 buf = isp_stat_buf_get(stat, data);
534 if (IS_ERR(buf)) {
535 mutex_unlock(&stat->ioctl_lock);
536 return PTR_ERR(buf);
537 }
538
539 data->ts = buf->ts;
540 data->config_counter = buf->config_counter;
541 data->frame_number = buf->frame_number;
542 data->buf_size = buf->buf_size;
543
544 buf->empty = 1;
545 isp_stat_buf_release(stat);
546 mutex_unlock(&stat->ioctl_lock);
547
548 return 0;
549}
550
551/*
552 * omap3isp_stat_config - Receives new statistic engine configuration.
553 * @new_conf: Pointer to config structure.
554 *
555 * Returns 0 if successful, -EINVAL if new_conf pointer is NULL, -ENOMEM if
556 * was unable to allocate memory for the buffer, or other errors if parameters
557 * are invalid.
558 */
559int omap3isp_stat_config(struct ispstat *stat, void *new_conf)
560{
561 int ret;
562 unsigned long irqflags;
563 struct ispstat_generic_config *user_cfg = new_conf;
564 u32 buf_size = user_cfg->buf_size;
565
566 if (!new_conf) {
567 dev_dbg(stat->isp->dev, "%s: configuration is NULL\n",
568 stat->subdev.name);
569 return -EINVAL;
570 }
571
572 mutex_lock(&stat->ioctl_lock);
573
574 dev_dbg(stat->isp->dev, "%s: configuring module with buffer "
575 "size=0x%08lx\n", stat->subdev.name, (unsigned long)buf_size);
576
577 ret = stat->ops->validate_params(stat, new_conf);
578 if (ret) {
579 mutex_unlock(&stat->ioctl_lock);
580 dev_dbg(stat->isp->dev, "%s: configuration values are "
581 "invalid.\n", stat->subdev.name);
582 return ret;
583 }
584
585 if (buf_size != user_cfg->buf_size)
586 dev_dbg(stat->isp->dev, "%s: driver has corrected buffer size "
587 "request to 0x%08lx\n", stat->subdev.name,
588 (unsigned long)user_cfg->buf_size);
589
590 /*
591 * Hack: H3A modules may need a doubled buffer size to avoid access
592 * to a invalid memory address after a SBL overflow.
593 * The buffer size is always PAGE_ALIGNED.
594 * Hack 2: MAGIC_SIZE is added to buf_size so a magic word can be
595 * inserted at the end to data integrity check purpose.
596 * Hack 3: AF module writes one paxel data more than it should, so
597 * the buffer allocation must consider it to avoid invalid memory
598 * access.
599 * Hack 4: H3A need to allocate extra space for the recover state.
600 */
601 if (IS_H3A(stat)) {
602 buf_size = user_cfg->buf_size * 2 + MAGIC_SIZE;
603 if (IS_H3A_AF(stat))
604 /*
605 * Adding one extra paxel data size for each recover
606 * buffer + 2 regular ones.
607 */
608 buf_size += AF_EXTRA_DATA * (NUM_H3A_RECOVER_BUFS + 2);
609 if (stat->recover_priv) {
610 struct ispstat_generic_config *recover_cfg =
611 stat->recover_priv;
612 buf_size += recover_cfg->buf_size *
613 NUM_H3A_RECOVER_BUFS;
614 }
615 buf_size = PAGE_ALIGN(buf_size);
616 } else { /* Histogram */
617 buf_size = PAGE_ALIGN(user_cfg->buf_size + MAGIC_SIZE);
618 }
619
620 ret = isp_stat_bufs_alloc(stat, buf_size);
621 if (ret) {
622 mutex_unlock(&stat->ioctl_lock);
623 return ret;
624 }
625
626 spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
627 stat->ops->set_params(stat, new_conf);
628 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
629
630 /*
631 * Returning the right future config_counter for this setup, so
632 * userspace can *know* when it has been applied.
633 */
634 user_cfg->config_counter = stat->config_counter + stat->inc_config;
635
636 /* Module has a valid configuration. */
637 stat->configured = 1;
638 dev_dbg(stat->isp->dev, "%s: module has been successfully "
639 "configured.\n", stat->subdev.name);
640
641 mutex_unlock(&stat->ioctl_lock);
642
643 return 0;
644}
645
646/*
647 * isp_stat_buf_process - Process statistic buffers.
648 * @buf_state: points out if buffer is ready to be processed. It's necessary
649 * because histogram needs to copy the data from internal memory
650 * before be able to process the buffer.
651 */
652static int isp_stat_buf_process(struct ispstat *stat, int buf_state)
653{
654 int ret = STAT_NO_BUF;
655
656 if (!atomic_add_unless(&stat->buf_err, -1, 0) &&
657 buf_state == STAT_BUF_DONE && stat->state == ISPSTAT_ENABLED) {
658 ret = isp_stat_buf_queue(stat);
659 isp_stat_buf_next(stat);
660 }
661
662 return ret;
663}
664
665int omap3isp_stat_pcr_busy(struct ispstat *stat)
666{
667 return stat->ops->busy(stat);
668}
669
670int omap3isp_stat_busy(struct ispstat *stat)
671{
672 return omap3isp_stat_pcr_busy(stat) | stat->buf_processing |
673 (stat->state != ISPSTAT_DISABLED);
674}
675
676/*
677 * isp_stat_pcr_enable - Disables/Enables statistic engines.
678 * @pcr_enable: 0/1 - Disables/Enables the engine.
679 *
680 * Must be called from ISP driver when the module is idle and synchronized
681 * with CCDC.
682 */
683static void isp_stat_pcr_enable(struct ispstat *stat, u8 pcr_enable)
684{
685 if ((stat->state != ISPSTAT_ENABLING &&
686 stat->state != ISPSTAT_ENABLED) && pcr_enable)
687 /* Userspace has disabled the module. Aborting. */
688 return;
689
690 stat->ops->enable(stat, pcr_enable);
691 if (stat->state == ISPSTAT_DISABLING && !pcr_enable)
692 stat->state = ISPSTAT_DISABLED;
693 else if (stat->state == ISPSTAT_ENABLING && pcr_enable)
694 stat->state = ISPSTAT_ENABLED;
695}
696
697void omap3isp_stat_suspend(struct ispstat *stat)
698{
699 unsigned long flags;
700
701 spin_lock_irqsave(&stat->isp->stat_lock, flags);
702
703 if (stat->state != ISPSTAT_DISABLED)
704 stat->ops->enable(stat, 0);
705 if (stat->state == ISPSTAT_ENABLED)
706 stat->state = ISPSTAT_SUSPENDED;
707
708 spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
709}
710
711void omap3isp_stat_resume(struct ispstat *stat)
712{
713 /* Module will be re-enabled with its pipeline */
714 if (stat->state == ISPSTAT_SUSPENDED)
715 stat->state = ISPSTAT_ENABLING;
716}
717
718static void isp_stat_try_enable(struct ispstat *stat)
719{
720 unsigned long irqflags;
721
722 if (stat->priv == NULL)
723 /* driver wasn't initialised */
724 return;
725
726 spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
727 if (stat->state == ISPSTAT_ENABLING && !stat->buf_processing &&
728 stat->buf_alloc_size) {
729 /*
730 * Userspace's requested to enable the engine but it wasn't yet.
731 * Let's do that now.
732 */
733 stat->update = 1;
734 isp_stat_buf_next(stat);
735 stat->ops->setup_regs(stat, stat->priv);
736 isp_stat_buf_insert_magic(stat, stat->active_buf);
737
738 /*
739 * H3A module has some hw issues which forces the driver to
740 * ignore next buffers even if it was disabled in the meantime.
741 * On the other hand, Histogram shouldn't ignore buffers anymore
742 * if it's being enabled.
743 */
744 if (!IS_H3A(stat))
745 atomic_set(&stat->buf_err, 0);
746
747 isp_stat_pcr_enable(stat, 1);
748 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
749 dev_dbg(stat->isp->dev, "%s: module is enabled.\n",
750 stat->subdev.name);
751 } else {
752 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
753 }
754}
755
756void omap3isp_stat_isr_frame_sync(struct ispstat *stat)
757{
758 isp_stat_try_enable(stat);
759}
760
761void omap3isp_stat_sbl_overflow(struct ispstat *stat)
762{
763 unsigned long irqflags;
764
765 spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
766 /*
767 * Due to a H3A hw issue which prevents the next buffer to start from
768 * the correct memory address, 2 buffers must be ignored.
769 */
770 atomic_set(&stat->buf_err, 2);
771
772 /*
773 * If more than one SBL overflow happen in a row, H3A module may access
774 * invalid memory region.
775 * stat->sbl_ovl_recover is set to tell to the driver to temporarily use
776 * a soft configuration which helps to avoid consecutive overflows.
777 */
778 if (stat->recover_priv)
779 stat->sbl_ovl_recover = 1;
780 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
781}
782
783/*
784 * omap3isp_stat_enable - Disable/Enable statistic engine as soon as possible
785 * @enable: 0/1 - Disables/Enables the engine.
786 *
787 * Client should configure all the module registers before this.
788 * This function can be called from a userspace request.
789 */
790int omap3isp_stat_enable(struct ispstat *stat, u8 enable)
791{
792 unsigned long irqflags;
793
794 dev_dbg(stat->isp->dev, "%s: user wants to %s module.\n",
795 stat->subdev.name, enable ? "enable" : "disable");
796
797 /* Prevent enabling while configuring */
798 mutex_lock(&stat->ioctl_lock);
799
800 spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
801
802 if (!stat->configured && enable) {
803 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
804 mutex_unlock(&stat->ioctl_lock);
805 dev_dbg(stat->isp->dev, "%s: cannot enable module as it's "
806 "never been successfully configured so far.\n",
807 stat->subdev.name);
808 return -EINVAL;
809 }
810
811 if (enable) {
812 if (stat->state == ISPSTAT_DISABLING)
813 /* Previous disabling request wasn't done yet */
814 stat->state = ISPSTAT_ENABLED;
815 else if (stat->state == ISPSTAT_DISABLED)
816 /* Module is now being enabled */
817 stat->state = ISPSTAT_ENABLING;
818 } else {
819 if (stat->state == ISPSTAT_ENABLING) {
820 /* Previous enabling request wasn't done yet */
821 stat->state = ISPSTAT_DISABLED;
822 } else if (stat->state == ISPSTAT_ENABLED) {
823 /* Module is now being disabled */
824 stat->state = ISPSTAT_DISABLING;
825 isp_stat_buf_clear(stat);
826 }
827 }
828
829 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
830 mutex_unlock(&stat->ioctl_lock);
831
832 return 0;
833}
834
835int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable)
836{
837 struct ispstat *stat = v4l2_get_subdevdata(subdev);
838
839 if (enable) {
840 /*
841 * Only set enable PCR bit if the module was previously
842 * enabled through ioct.
843 */
844 isp_stat_try_enable(stat);
845 } else {
846 unsigned long flags;
847 /* Disable PCR bit and config enable field */
848 omap3isp_stat_enable(stat, 0);
849 spin_lock_irqsave(&stat->isp->stat_lock, flags);
850 stat->ops->enable(stat, 0);
851 spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
852
853 /*
854 * If module isn't busy, a new interrupt may come or not to
855 * set the state to DISABLED. As Histogram needs to read its
856 * internal memory to clear it, let interrupt handler
857 * responsible of changing state to DISABLED. If the last
858 * interrupt is coming, it's still safe as the handler will
859 * ignore the second time when state is already set to DISABLED.
860 * It's necessary to synchronize Histogram with streamoff, once
861 * the module may be considered idle before last SDMA transfer
862 * starts if we return here.
863 */
864 if (!omap3isp_stat_pcr_busy(stat))
865 omap3isp_stat_isr(stat);
866
867 dev_dbg(stat->isp->dev, "%s: module is being disabled\n",
868 stat->subdev.name);
869 }
870
871 return 0;
872}
873
874/*
875 * __stat_isr - Interrupt handler for statistic drivers
876 */
877static void __stat_isr(struct ispstat *stat, int from_dma)
878{
879 int ret = STAT_BUF_DONE;
880 int buf_processing;
881 unsigned long irqflags;
882 struct isp_pipeline *pipe;
883
884 /*
885 * stat->buf_processing must be set before disable module. It's
886 * necessary to not inform too early the buffers aren't busy in case
887 * of SDMA is going to be used.
888 */
889 spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
890 if (stat->state == ISPSTAT_DISABLED) {
891 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
892 return;
893 }
894 buf_processing = stat->buf_processing;
895 stat->buf_processing = 1;
896 stat->ops->enable(stat, 0);
897
898 if (buf_processing && !from_dma) {
899 if (stat->state == ISPSTAT_ENABLED) {
900 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
901 dev_err(stat->isp->dev,
902 "%s: interrupt occurred when module was still "
903 "processing a buffer.\n", stat->subdev.name);
904 ret = STAT_NO_BUF;
905 goto out;
906 } else {
907 /*
908 * Interrupt handler was called from streamoff when
909 * the module wasn't busy anymore to ensure it is being
910 * disabled after process last buffer. If such buffer
911 * processing has already started, no need to do
912 * anything else.
913 */
914 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
915 return;
916 }
917 }
918 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
919
920 /* If it's busy we can't process this buffer anymore */
921 if (!omap3isp_stat_pcr_busy(stat)) {
922 if (!from_dma && stat->ops->buf_process)
923 /* Module still need to copy data to buffer. */
924 ret = stat->ops->buf_process(stat);
925 if (ret == STAT_BUF_WAITING_DMA)
926 /* Buffer is not ready yet */
927 return;
928
929 spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
930
931 /*
932 * Histogram needs to read its internal memory to clear it
933 * before be disabled. For that reason, common statistic layer
934 * can return only after call stat's buf_process() operator.
935 */
936 if (stat->state == ISPSTAT_DISABLING) {
937 stat->state = ISPSTAT_DISABLED;
938 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
939 stat->buf_processing = 0;
940 return;
941 }
942 pipe = to_isp_pipeline(&stat->subdev.entity);
943 stat->frame_number = atomic_read(&pipe->frame_number);
944
945 /*
946 * Before this point, 'ret' stores the buffer's status if it's
947 * ready to be processed. Afterwards, it holds the status if
948 * it was processed successfully.
949 */
950 ret = isp_stat_buf_process(stat, ret);
951
952 if (likely(!stat->sbl_ovl_recover)) {
953 stat->ops->setup_regs(stat, stat->priv);
954 } else {
955 /*
956 * Using recover config to increase the chance to have
957 * a good buffer processing and make the H3A module to
958 * go back to a valid state.
959 */
960 stat->update = 1;
961 stat->ops->setup_regs(stat, stat->recover_priv);
962 stat->sbl_ovl_recover = 0;
963
964 /*
965 * Set 'update' in case of the module needs to use
966 * regular configuration after next buffer.
967 */
968 stat->update = 1;
969 }
970
971 isp_stat_buf_insert_magic(stat, stat->active_buf);
972
973 /*
974 * Hack: H3A modules may access invalid memory address or send
975 * corrupted data to userspace if more than 1 SBL overflow
976 * happens in a row without re-writing its buffer's start memory
977 * address in the meantime. Such situation is avoided if the
978 * module is not immediately re-enabled when the ISR misses the
979 * timing to process the buffer and to setup the registers.
980 * Because of that, pcr_enable(1) was moved to inside this 'if'
981 * block. But the next interruption will still happen as during
982 * pcr_enable(0) the module was busy.
983 */
984 isp_stat_pcr_enable(stat, 1);
985 spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
986 } else {
987 /*
988 * If a SBL overflow occurs and the H3A driver misses the timing
989 * to process the buffer, stat->buf_err is set and won't be
990 * cleared now. So the next buffer will be correctly ignored.
991 * It's necessary due to a hw issue which makes the next H3A
992 * buffer to start from the memory address where the previous
993 * one stopped, instead of start where it was configured to.
994 * Do not "stat->buf_err = 0" here.
995 */
996
997 if (stat->ops->buf_process)
998 /*
999 * Driver may need to erase current data prior to
1000 * process a new buffer. If it misses the timing, the
1001 * next buffer might be wrong. So should be ignored.
1002 * It happens only for Histogram.
1003 */
1004 atomic_set(&stat->buf_err, 1);
1005
1006 ret = STAT_NO_BUF;
1007 dev_dbg(stat->isp->dev, "%s: cannot process buffer, "
1008 "device is busy.\n", stat->subdev.name);
1009 }
1010
1011out:
1012 stat->buf_processing = 0;
1013 isp_stat_queue_event(stat, ret != STAT_BUF_DONE);
1014}
1015
1016void omap3isp_stat_isr(struct ispstat *stat)
1017{
1018 __stat_isr(stat, 0);
1019}
1020
1021void omap3isp_stat_dma_isr(struct ispstat *stat)
1022{
1023 __stat_isr(stat, 1);
1024}
1025
1026int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
1027 struct v4l2_fh *fh,
1028 const struct v4l2_event_subscription *sub)
1029{
1030 struct ispstat *stat = v4l2_get_subdevdata(subdev);
1031
1032 if (sub->type != stat->event_type)
1033 return -EINVAL;
1034
1035 return v4l2_event_subscribe(fh, sub, STAT_NEVENTS, NULL);
1036}
1037
1038int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
1039 struct v4l2_fh *fh,
1040 const struct v4l2_event_subscription *sub)
1041{
1042 return v4l2_event_unsubscribe(fh, sub);
1043}
1044
1045void omap3isp_stat_unregister_entities(struct ispstat *stat)
1046{
1047 v4l2_device_unregister_subdev(&stat->subdev);
1048}
1049
1050int omap3isp_stat_register_entities(struct ispstat *stat,
1051 struct v4l2_device *vdev)
1052{
1053 return v4l2_device_register_subdev(vdev, &stat->subdev);
1054}
1055
1056static int isp_stat_init_entities(struct ispstat *stat, const char *name,
1057 const struct v4l2_subdev_ops *sd_ops)
1058{
1059 struct v4l2_subdev *subdev = &stat->subdev;
1060 struct media_entity *me = &subdev->entity;
1061
1062 v4l2_subdev_init(subdev, sd_ops);
1063 snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name);
1064 subdev->grp_id = 1 << 16; /* group ID for isp subdevs */
1065 subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1066 v4l2_set_subdevdata(subdev, stat);
1067
1068 stat->pad.flags = MEDIA_PAD_FL_SINK;
1069 me->ops = NULL;
1070
1071 return media_entity_init(me, 1, &stat->pad, 0);
1072}
1073
1074int omap3isp_stat_init(struct ispstat *stat, const char *name,
1075 const struct v4l2_subdev_ops *sd_ops)
1076{
1077 int ret;
1078
1079 stat->buf = kcalloc(STAT_MAX_BUFS, sizeof(*stat->buf), GFP_KERNEL);
1080 if (!stat->buf)
1081 return -ENOMEM;
1082
1083 isp_stat_buf_clear(stat);
1084 mutex_init(&stat->ioctl_lock);
1085 atomic_set(&stat->buf_err, 0);
1086
1087 ret = isp_stat_init_entities(stat, name, sd_ops);
1088 if (ret < 0) {
1089 mutex_destroy(&stat->ioctl_lock);
1090 kfree(stat->buf);
1091 }
1092
1093 return ret;
1094}
1095
1096void omap3isp_stat_cleanup(struct ispstat *stat)
1097{
1098 media_entity_cleanup(&stat->subdev.entity);
1099 mutex_destroy(&stat->ioctl_lock);
1100 isp_stat_bufs_free(stat);
1101 kfree(stat->buf);
1102}
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
new file mode 100644
index 000000000000..a6fe653eb237
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -0,0 +1,169 @@
1/*
2 * ispstat.h
3 *
4 * TI OMAP3 ISP - Statistics core
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc
8 *
9 * Contacts: David Cohen <dacohen@gmail.com>
10 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11 * Sakari Ailus <sakari.ailus@iki.fi>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 * 02110-1301 USA
26 */
27
28#ifndef OMAP3_ISP_STAT_H
29#define OMAP3_ISP_STAT_H
30
31#include <linux/types.h>
32#include <linux/omap3isp.h>
33#include <plat/dma.h>
34#include <media/v4l2-event.h>
35
36#include "isp.h"
37#include "ispvideo.h"
38
39#define STAT_MAX_BUFS 5
40#define STAT_NEVENTS 8
41
42#define STAT_BUF_DONE 0 /* Buffer is ready */
43#define STAT_NO_BUF 1 /* An error has occurred */
44#define STAT_BUF_WAITING_DMA 2 /* Histogram only: DMA is running */
45
46struct ispstat;
47
48struct ispstat_buffer {
49 unsigned long iommu_addr;
50 struct iovm_struct *iovm;
51 void *virt_addr;
52 dma_addr_t dma_addr;
53 struct timeval ts;
54 u32 buf_size;
55 u32 frame_number;
56 u16 config_counter;
57 u8 empty;
58};
59
60struct ispstat_ops {
61 /*
62 * Validate new params configuration.
63 * new_conf->buf_size value must be changed to the exact buffer size
64 * necessary for the new configuration if it's smaller.
65 */
66 int (*validate_params)(struct ispstat *stat, void *new_conf);
67
68 /*
69 * Save new params configuration.
70 * stat->priv->buf_size value must be set to the exact buffer size for
71 * the new configuration.
72 * stat->update is set to 1 if new configuration is different than
73 * current one.
74 */
75 void (*set_params)(struct ispstat *stat, void *new_conf);
76
77 /* Apply stored configuration. */
78 void (*setup_regs)(struct ispstat *stat, void *priv);
79
80 /* Enable/Disable module. */
81 void (*enable)(struct ispstat *stat, int enable);
82
83 /* Verify is module is busy. */
84 int (*busy)(struct ispstat *stat);
85
86 /* Used for specific operations during generic buf process task. */
87 int (*buf_process)(struct ispstat *stat);
88};
89
90enum ispstat_state_t {
91 ISPSTAT_DISABLED = 0,
92 ISPSTAT_DISABLING,
93 ISPSTAT_ENABLED,
94 ISPSTAT_ENABLING,
95 ISPSTAT_SUSPENDED,
96};
97
98struct ispstat {
99 struct v4l2_subdev subdev;
100 struct media_pad pad; /* sink pad */
101
102 /* Control */
103 unsigned configured:1;
104 unsigned update:1;
105 unsigned buf_processing:1;
106 unsigned sbl_ovl_recover:1;
107 u8 inc_config;
108 atomic_t buf_err;
109 enum ispstat_state_t state; /* enabling/disabling state */
110 struct omap_dma_channel_params dma_config;
111 struct isp_device *isp;
112 void *priv; /* pointer to priv config struct */
113 void *recover_priv; /* pointer to recover priv configuration */
114 struct mutex ioctl_lock; /* serialize private ioctl */
115
116 const struct ispstat_ops *ops;
117
118 /* Buffer */
119 u8 wait_acc_frames;
120 u16 config_counter;
121 u32 frame_number;
122 u32 buf_size;
123 u32 buf_alloc_size;
124 int dma_ch;
125 unsigned long event_type;
126 struct ispstat_buffer *buf;
127 struct ispstat_buffer *active_buf;
128 struct ispstat_buffer *locked_buf;
129};
130
131struct ispstat_generic_config {
132 /*
133 * Fields must be in the same order as in:
134 * - omap3isp_h3a_aewb_config
135 * - omap3isp_h3a_af_config
136 * - omap3isp_hist_config
137 */
138 u32 buf_size;
139 u16 config_counter;
140};
141
142int omap3isp_stat_config(struct ispstat *stat, void *new_conf);
143int omap3isp_stat_request_statistics(struct ispstat *stat,
144 struct omap3isp_stat_data *data);
145int omap3isp_stat_init(struct ispstat *stat, const char *name,
146 const struct v4l2_subdev_ops *sd_ops);
147void omap3isp_stat_cleanup(struct ispstat *stat);
148int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
149 struct v4l2_fh *fh,
150 const struct v4l2_event_subscription *sub);
151int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
152 struct v4l2_fh *fh,
153 const struct v4l2_event_subscription *sub);
154int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable);
155
156int omap3isp_stat_busy(struct ispstat *stat);
157int omap3isp_stat_pcr_busy(struct ispstat *stat);
158void omap3isp_stat_suspend(struct ispstat *stat);
159void omap3isp_stat_resume(struct ispstat *stat);
160int omap3isp_stat_enable(struct ispstat *stat, u8 enable);
161void omap3isp_stat_sbl_overflow(struct ispstat *stat);
162void omap3isp_stat_isr(struct ispstat *stat);
163void omap3isp_stat_isr_frame_sync(struct ispstat *stat);
164void omap3isp_stat_dma_isr(struct ispstat *stat);
165int omap3isp_stat_register_entities(struct ispstat *stat,
166 struct v4l2_device *vdev);
167void omap3isp_stat_unregister_entities(struct ispstat *stat);
168
169#endif /* OMAP3_ISP_STAT_H */
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
new file mode 100644
index 000000000000..a0b737fecf13
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -0,0 +1,1404 @@
1/*
2 * ispvideo.c
3 *
4 * TI OMAP3 ISP - Generic video node
5 *
6 * Copyright (C) 2009-2010 Nokia Corporation
7 *
8 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9 * Sakari Ailus <sakari.ailus@iki.fi>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA
24 */
25
26#include <asm/cacheflush.h>
27#include <linux/clk.h>
28#include <linux/mm.h>
29#include <linux/module.h>
30#include <linux/pagemap.h>
31#include <linux/scatterlist.h>
32#include <linux/sched.h>
33#include <linux/slab.h>
34#include <linux/vmalloc.h>
35#include <media/v4l2-dev.h>
36#include <media/v4l2-ioctl.h>
37#include <plat/iommu.h>
38#include <plat/iovmm.h>
39#include <plat/omap-pm.h>
40
41#include "ispvideo.h"
42#include "isp.h"
43
44
45/* -----------------------------------------------------------------------------
46 * Helper functions
47 */
48
49/*
50 * NOTE: When adding new media bus codes, always remember to add
51 * corresponding in-memory formats to the table below!!!
52 */
53static struct isp_format_info formats[] = {
54 { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
55 V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
56 V4L2_PIX_FMT_GREY, 8, 1, },
57 { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
58 V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
59 V4L2_PIX_FMT_Y10, 10, 2, },
60 { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
61 V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
62 V4L2_PIX_FMT_Y12, 12, 2, },
63 { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
64 V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
65 V4L2_PIX_FMT_SBGGR8, 8, 1, },
66 { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
67 V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
68 V4L2_PIX_FMT_SGBRG8, 8, 1, },
69 { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
70 V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
71 V4L2_PIX_FMT_SGRBG8, 8, 1, },
72 { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
73 V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
74 V4L2_PIX_FMT_SRGGB8, 8, 1, },
75 { V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
76 V4L2_MBUS_FMT_SBGGR10_1X10, 0,
77 V4L2_PIX_FMT_SBGGR10DPCM8, 8, 1, },
78 { V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
79 V4L2_MBUS_FMT_SGBRG10_1X10, 0,
80 V4L2_PIX_FMT_SGBRG10DPCM8, 8, 1, },
81 { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
82 V4L2_MBUS_FMT_SGRBG10_1X10, 0,
83 V4L2_PIX_FMT_SGRBG10DPCM8, 8, 1, },
84 { V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
85 V4L2_MBUS_FMT_SRGGB10_1X10, 0,
86 V4L2_PIX_FMT_SRGGB10DPCM8, 8, 1, },
87 { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
88 V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
89 V4L2_PIX_FMT_SBGGR10, 10, 2, },
90 { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
91 V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
92 V4L2_PIX_FMT_SGBRG10, 10, 2, },
93 { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
94 V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
95 V4L2_PIX_FMT_SGRBG10, 10, 2, },
96 { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
97 V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
98 V4L2_PIX_FMT_SRGGB10, 10, 2, },
99 { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
100 V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
101 V4L2_PIX_FMT_SBGGR12, 12, 2, },
102 { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
103 V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
104 V4L2_PIX_FMT_SGBRG12, 12, 2, },
105 { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
106 V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
107 V4L2_PIX_FMT_SGRBG12, 12, 2, },
108 { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
109 V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
110 V4L2_PIX_FMT_SRGGB12, 12, 2, },
111 { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
112 V4L2_MBUS_FMT_UYVY8_1X16, 0,
113 V4L2_PIX_FMT_UYVY, 16, 2, },
114 { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
115 V4L2_MBUS_FMT_YUYV8_1X16, 0,
116 V4L2_PIX_FMT_YUYV, 16, 2, },
117 { V4L2_MBUS_FMT_UYVY8_2X8, V4L2_MBUS_FMT_UYVY8_2X8,
118 V4L2_MBUS_FMT_UYVY8_2X8, 0,
119 V4L2_PIX_FMT_UYVY, 8, 2, },
120 { V4L2_MBUS_FMT_YUYV8_2X8, V4L2_MBUS_FMT_YUYV8_2X8,
121 V4L2_MBUS_FMT_YUYV8_2X8, 0,
122 V4L2_PIX_FMT_YUYV, 8, 2, },
123 /* Empty entry to catch the unsupported pixel code (0) used by the CCDC
124 * module and avoid NULL pointer dereferences.
125 */
126 { 0, }
127};
128
129const struct isp_format_info *
130omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
131{
132 unsigned int i;
133
134 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
135 if (formats[i].code == code)
136 return &formats[i];
137 }
138
139 return NULL;
140}
141
142/*
143 * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
144 * @video: ISP video instance
145 * @mbus: v4l2_mbus_framefmt format (input)
146 * @pix: v4l2_pix_format format (output)
147 *
148 * Fill the output pix structure with information from the input mbus format.
149 * The bytesperline and sizeimage fields are computed from the requested bytes
150 * per line value in the pix format and information from the video instance.
151 *
152 * Return the number of padding bytes at end of line.
153 */
154static unsigned int isp_video_mbus_to_pix(const struct isp_video *video,
155 const struct v4l2_mbus_framefmt *mbus,
156 struct v4l2_pix_format *pix)
157{
158 unsigned int bpl = pix->bytesperline;
159 unsigned int min_bpl;
160 unsigned int i;
161
162 memset(pix, 0, sizeof(*pix));
163 pix->width = mbus->width;
164 pix->height = mbus->height;
165
166 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
167 if (formats[i].code == mbus->code)
168 break;
169 }
170
171 if (WARN_ON(i == ARRAY_SIZE(formats)))
172 return 0;
173
174 min_bpl = pix->width * formats[i].bpp;
175
176 /* Clamp the requested bytes per line value. If the maximum bytes per
177 * line value is zero, the module doesn't support user configurable line
178 * sizes. Override the requested value with the minimum in that case.
179 */
180 if (video->bpl_max)
181 bpl = clamp(bpl, min_bpl, video->bpl_max);
182 else
183 bpl = min_bpl;
184
185 if (!video->bpl_zero_padding || bpl != min_bpl)
186 bpl = ALIGN(bpl, video->bpl_alignment);
187
188 pix->pixelformat = formats[i].pixelformat;
189 pix->bytesperline = bpl;
190 pix->sizeimage = pix->bytesperline * pix->height;
191 pix->colorspace = mbus->colorspace;
192 pix->field = mbus->field;
193
194 return bpl - min_bpl;
195}
196
197static void isp_video_pix_to_mbus(const struct v4l2_pix_format *pix,
198 struct v4l2_mbus_framefmt *mbus)
199{
200 unsigned int i;
201
202 memset(mbus, 0, sizeof(*mbus));
203 mbus->width = pix->width;
204 mbus->height = pix->height;
205
206 /* Skip the last format in the loop so that it will be selected if no
207 * match is found.
208 */
209 for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) {
210 if (formats[i].pixelformat == pix->pixelformat)
211 break;
212 }
213
214 mbus->code = formats[i].code;
215 mbus->colorspace = pix->colorspace;
216 mbus->field = pix->field;
217}
218
219static struct v4l2_subdev *
220isp_video_remote_subdev(struct isp_video *video, u32 *pad)
221{
222 struct media_pad *remote;
223
224 remote = media_entity_remote_source(&video->pad);
225
226 if (remote == NULL ||
227 media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
228 return NULL;
229
230 if (pad)
231 *pad = remote->index;
232
233 return media_entity_to_v4l2_subdev(remote->entity);
234}
235
236/* Return a pointer to the ISP video instance at the far end of the pipeline. */
237static int isp_video_get_graph_data(struct isp_video *video,
238 struct isp_pipeline *pipe)
239{
240 struct media_entity_graph graph;
241 struct media_entity *entity = &video->video.entity;
242 struct media_device *mdev = entity->parent;
243 struct isp_video *far_end = NULL;
244
245 mutex_lock(&mdev->graph_mutex);
246 media_entity_graph_walk_start(&graph, entity);
247
248 while ((entity = media_entity_graph_walk_next(&graph))) {
249 struct isp_video *__video;
250
251 pipe->entities |= 1 << entity->id;
252
253 if (far_end != NULL)
254 continue;
255
256 if (entity == &video->video.entity)
257 continue;
258
259 if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
260 continue;
261
262 __video = to_isp_video(media_entity_to_video_device(entity));
263 if (__video->type != video->type)
264 far_end = __video;
265 }
266
267 mutex_unlock(&mdev->graph_mutex);
268
269 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
270 pipe->input = far_end;
271 pipe->output = video;
272 } else {
273 if (far_end == NULL)
274 return -EPIPE;
275
276 pipe->input = video;
277 pipe->output = far_end;
278 }
279
280 return 0;
281}
282
283/*
284 * Validate a pipeline by checking both ends of all links for format
285 * discrepancies.
286 *
287 * Compute the minimum time per frame value as the maximum of time per frame
288 * limits reported by every block in the pipeline.
289 *
290 * Return 0 if all formats match, or -EPIPE if at least one link is found with
291 * different formats on its two ends or if the pipeline doesn't start with a
292 * video source (either a subdev with no input pad, or a non-subdev entity).
293 */
294static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
295{
296 struct isp_device *isp = pipe->output->isp;
297 struct media_pad *pad;
298 struct v4l2_subdev *subdev;
299
300 subdev = isp_video_remote_subdev(pipe->output, NULL);
301 if (subdev == NULL)
302 return -EPIPE;
303
304 while (1) {
305 /* Retrieve the sink format */
306 pad = &subdev->entity.pads[0];
307 if (!(pad->flags & MEDIA_PAD_FL_SINK))
308 break;
309
310 /* Update the maximum frame rate */
311 if (subdev == &isp->isp_res.subdev)
312 omap3isp_resizer_max_rate(&isp->isp_res,
313 &pipe->max_rate);
314
315 /* Retrieve the source format. Return an error if no source
316 * entity can be found, and stop checking the pipeline if the
317 * source entity isn't a subdev.
318 */
319 pad = media_entity_remote_source(pad);
320 if (pad == NULL)
321 return -EPIPE;
322
323 if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
324 break;
325
326 subdev = media_entity_to_v4l2_subdev(pad->entity);
327 }
328
329 return 0;
330}
331
332static int
333__isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
334{
335 struct v4l2_subdev_format fmt;
336 struct v4l2_subdev *subdev;
337 u32 pad;
338 int ret;
339
340 subdev = isp_video_remote_subdev(video, &pad);
341 if (subdev == NULL)
342 return -EINVAL;
343
344 mutex_lock(&video->mutex);
345
346 fmt.pad = pad;
347 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
348 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
349 if (ret == -ENOIOCTLCMD)
350 ret = -EINVAL;
351
352 mutex_unlock(&video->mutex);
353
354 if (ret)
355 return ret;
356
357 format->type = video->type;
358 return isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
359}
360
361static int
362isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
363{
364 struct v4l2_format format;
365 int ret;
366
367 memcpy(&format, &vfh->format, sizeof(format));
368 ret = __isp_video_get_format(video, &format);
369 if (ret < 0)
370 return ret;
371
372 if (vfh->format.fmt.pix.pixelformat != format.fmt.pix.pixelformat ||
373 vfh->format.fmt.pix.height != format.fmt.pix.height ||
374 vfh->format.fmt.pix.width != format.fmt.pix.width ||
375 vfh->format.fmt.pix.bytesperline != format.fmt.pix.bytesperline ||
376 vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage)
377 return -EINVAL;
378
379 return ret;
380}
381
382/* -----------------------------------------------------------------------------
383 * IOMMU management
384 */
385
386#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
387
388/*
389 * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list
390 * @dev: Device pointer specific to the OMAP3 ISP.
391 * @sglist: Pointer to source Scatter gather list to allocate.
392 * @sglen: Number of elements of the scatter-gatter list.
393 *
394 * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
395 * we ran out of memory.
396 */
397static dma_addr_t
398ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
399{
400 struct sg_table *sgt;
401 u32 da;
402
403 sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
404 if (sgt == NULL)
405 return -ENOMEM;
406
407 sgt->sgl = (struct scatterlist *)sglist;
408 sgt->nents = sglen;
409 sgt->orig_nents = sglen;
410
411 da = omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
412 if (IS_ERR_VALUE(da))
413 kfree(sgt);
414
415 return da;
416}
417
418/*
419 * ispmmu_vunmap - Unmap a device address from the ISP MMU
420 * @dev: Device pointer specific to the OMAP3 ISP.
421 * @da: Device address generated from a ispmmu_vmap call.
422 */
423static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
424{
425 struct sg_table *sgt;
426
427 sgt = omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
428 kfree(sgt);
429}
430
431/* -----------------------------------------------------------------------------
432 * Video queue operations
433 */
434
435static void isp_video_queue_prepare(struct isp_video_queue *queue,
436 unsigned int *nbuffers, unsigned int *size)
437{
438 struct isp_video_fh *vfh =
439 container_of(queue, struct isp_video_fh, queue);
440 struct isp_video *video = vfh->video;
441
442 *size = vfh->format.fmt.pix.sizeimage;
443 if (*size == 0)
444 return;
445
446 *nbuffers = min(*nbuffers, video->capture_mem / PAGE_ALIGN(*size));
447}
448
449static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
450{
451 struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
452 struct isp_buffer *buffer = to_isp_buffer(buf);
453 struct isp_video *video = vfh->video;
454
455 if (buffer->isp_addr) {
456 ispmmu_vunmap(video->isp, buffer->isp_addr);
457 buffer->isp_addr = 0;
458 }
459}
460
461static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
462{
463 struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
464 struct isp_buffer *buffer = to_isp_buffer(buf);
465 struct isp_video *video = vfh->video;
466 unsigned long addr;
467
468 addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen);
469 if (IS_ERR_VALUE(addr))
470 return -EIO;
471
472 if (!IS_ALIGNED(addr, 32)) {
473 dev_dbg(video->isp->dev, "Buffer address must be "
474 "aligned to 32 bytes boundary.\n");
475 ispmmu_vunmap(video->isp, buffer->isp_addr);
476 return -EINVAL;
477 }
478
479 buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
480 buffer->isp_addr = addr;
481 return 0;
482}
483
484/*
485 * isp_video_buffer_queue - Add buffer to streaming queue
486 * @buf: Video buffer
487 *
488 * In memory-to-memory mode, start streaming on the pipeline if buffers are
489 * queued on both the input and the output, if the pipeline isn't already busy.
490 * If the pipeline is busy, it will be restarted in the output module interrupt
491 * handler.
492 */
493static void isp_video_buffer_queue(struct isp_video_buffer *buf)
494{
495 struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
496 struct isp_buffer *buffer = to_isp_buffer(buf);
497 struct isp_video *video = vfh->video;
498 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
499 enum isp_pipeline_state state;
500 unsigned long flags;
501 unsigned int empty;
502 unsigned int start;
503
504 empty = list_empty(&video->dmaqueue);
505 list_add_tail(&buffer->buffer.irqlist, &video->dmaqueue);
506
507 if (empty) {
508 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
509 state = ISP_PIPELINE_QUEUE_OUTPUT;
510 else
511 state = ISP_PIPELINE_QUEUE_INPUT;
512
513 spin_lock_irqsave(&pipe->lock, flags);
514 pipe->state |= state;
515 video->ops->queue(video, buffer);
516 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
517
518 start = isp_pipeline_ready(pipe);
519 if (start)
520 pipe->state |= ISP_PIPELINE_STREAM;
521 spin_unlock_irqrestore(&pipe->lock, flags);
522
523 if (start)
524 omap3isp_pipeline_set_stream(pipe,
525 ISP_PIPELINE_STREAM_SINGLESHOT);
526 }
527}
528
529static const struct isp_video_queue_operations isp_video_queue_ops = {
530 .queue_prepare = &isp_video_queue_prepare,
531 .buffer_prepare = &isp_video_buffer_prepare,
532 .buffer_queue = &isp_video_buffer_queue,
533 .buffer_cleanup = &isp_video_buffer_cleanup,
534};
535
536/*
537 * omap3isp_video_buffer_next - Complete the current buffer and return the next
538 * @video: ISP video object
539 *
540 * Remove the current video buffer from the DMA queue and fill its timestamp,
541 * field count and state fields before waking up its completion handler.
542 *
543 * For capture video nodes the buffer state is set to ISP_BUF_STATE_DONE if no
544 * error has been flagged in the pipeline, or to ISP_BUF_STATE_ERROR otherwise.
545 * For video output nodes the buffer state is always set to ISP_BUF_STATE_DONE.
546 *
547 * The DMA queue is expected to contain at least one buffer.
548 *
549 * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is
550 * empty.
551 */
552struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
553{
554 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
555 struct isp_video_queue *queue = video->queue;
556 enum isp_pipeline_state state;
557 struct isp_video_buffer *buf;
558 unsigned long flags;
559 struct timespec ts;
560
561 spin_lock_irqsave(&queue->irqlock, flags);
562 if (WARN_ON(list_empty(&video->dmaqueue))) {
563 spin_unlock_irqrestore(&queue->irqlock, flags);
564 return NULL;
565 }
566
567 buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
568 irqlist);
569 list_del(&buf->irqlist);
570 spin_unlock_irqrestore(&queue->irqlock, flags);
571
572 ktime_get_ts(&ts);
573 buf->vbuf.timestamp.tv_sec = ts.tv_sec;
574 buf->vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
575
576 /* Do frame number propagation only if this is the output video node.
577 * Frame number either comes from the CSI receivers or it gets
578 * incremented here if H3A is not active.
579 * Note: There is no guarantee that the output buffer will finish
580 * first, so the input number might lag behind by 1 in some cases.
581 */
582 if (video == pipe->output && !pipe->do_propagation)
583 buf->vbuf.sequence = atomic_inc_return(&pipe->frame_number);
584 else
585 buf->vbuf.sequence = atomic_read(&pipe->frame_number);
586
587 /* Report pipeline errors to userspace on the capture device side. */
588 if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
589 buf->state = ISP_BUF_STATE_ERROR;
590 pipe->error = false;
591 } else {
592 buf->state = ISP_BUF_STATE_DONE;
593 }
594
595 wake_up(&buf->wait);
596
597 if (list_empty(&video->dmaqueue)) {
598 if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
599 state = ISP_PIPELINE_QUEUE_OUTPUT
600 | ISP_PIPELINE_STREAM;
601 else
602 state = ISP_PIPELINE_QUEUE_INPUT
603 | ISP_PIPELINE_STREAM;
604
605 spin_lock_irqsave(&pipe->lock, flags);
606 pipe->state &= ~state;
607 if (video->pipe.stream_state == ISP_PIPELINE_STREAM_CONTINUOUS)
608 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
609 spin_unlock_irqrestore(&pipe->lock, flags);
610 return NULL;
611 }
612
613 if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) {
614 spin_lock_irqsave(&pipe->lock, flags);
615 pipe->state &= ~ISP_PIPELINE_STREAM;
616 spin_unlock_irqrestore(&pipe->lock, flags);
617 }
618
619 buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
620 irqlist);
621 buf->state = ISP_BUF_STATE_ACTIVE;
622 return to_isp_buffer(buf);
623}
624
625/*
626 * omap3isp_video_resume - Perform resume operation on the buffers
627 * @video: ISP video object
628 * @continuous: Pipeline is in single shot mode if 0 or continuous mode otherwise
629 *
630 * This function is intended to be used on suspend/resume scenario. It
631 * requests video queue layer to discard buffers marked as DONE if it's in
632 * continuous mode and requests ISP modules to queue again the ACTIVE buffer
633 * if there's any.
634 */
635void omap3isp_video_resume(struct isp_video *video, int continuous)
636{
637 struct isp_buffer *buf = NULL;
638
639 if (continuous && video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
640 omap3isp_video_queue_discard_done(video->queue);
641
642 if (!list_empty(&video->dmaqueue)) {
643 buf = list_first_entry(&video->dmaqueue,
644 struct isp_buffer, buffer.irqlist);
645 video->ops->queue(video, buf);
646 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
647 } else {
648 if (continuous)
649 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
650 }
651}
652
653/* -----------------------------------------------------------------------------
654 * V4L2 ioctls
655 */
656
657static int
658isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
659{
660 struct isp_video *video = video_drvdata(file);
661
662 strlcpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver));
663 strlcpy(cap->card, video->video.name, sizeof(cap->card));
664 strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
665
666 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
667 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
668 else
669 cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
670
671 return 0;
672}
673
674static int
675isp_video_get_format(struct file *file, void *fh, struct v4l2_format *format)
676{
677 struct isp_video_fh *vfh = to_isp_video_fh(fh);
678 struct isp_video *video = video_drvdata(file);
679
680 if (format->type != video->type)
681 return -EINVAL;
682
683 mutex_lock(&video->mutex);
684 *format = vfh->format;
685 mutex_unlock(&video->mutex);
686
687 return 0;
688}
689
690static int
691isp_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
692{
693 struct isp_video_fh *vfh = to_isp_video_fh(fh);
694 struct isp_video *video = video_drvdata(file);
695 struct v4l2_mbus_framefmt fmt;
696
697 if (format->type != video->type)
698 return -EINVAL;
699
700 mutex_lock(&video->mutex);
701
702 /* Fill the bytesperline and sizeimage fields by converting to media bus
703 * format and back to pixel format.
704 */
705 isp_video_pix_to_mbus(&format->fmt.pix, &fmt);
706 isp_video_mbus_to_pix(video, &fmt, &format->fmt.pix);
707
708 vfh->format = *format;
709
710 mutex_unlock(&video->mutex);
711 return 0;
712}
713
714static int
715isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
716{
717 struct isp_video *video = video_drvdata(file);
718 struct v4l2_subdev_format fmt;
719 struct v4l2_subdev *subdev;
720 u32 pad;
721 int ret;
722
723 if (format->type != video->type)
724 return -EINVAL;
725
726 subdev = isp_video_remote_subdev(video, &pad);
727 if (subdev == NULL)
728 return -EINVAL;
729
730 isp_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
731
732 fmt.pad = pad;
733 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
734 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
735 if (ret)
736 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
737
738 isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
739 return 0;
740}
741
742static int
743isp_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
744{
745 struct isp_video *video = video_drvdata(file);
746 struct v4l2_subdev *subdev;
747 int ret;
748
749 subdev = isp_video_remote_subdev(video, NULL);
750 if (subdev == NULL)
751 return -EINVAL;
752
753 mutex_lock(&video->mutex);
754 ret = v4l2_subdev_call(subdev, video, cropcap, cropcap);
755 mutex_unlock(&video->mutex);
756
757 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
758}
759
760static int
761isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
762{
763 struct isp_video *video = video_drvdata(file);
764 struct v4l2_subdev_format format;
765 struct v4l2_subdev *subdev;
766 u32 pad;
767 int ret;
768
769 subdev = isp_video_remote_subdev(video, &pad);
770 if (subdev == NULL)
771 return -EINVAL;
772
773 /* Try the get crop operation first and fallback to get format if not
774 * implemented.
775 */
776 ret = v4l2_subdev_call(subdev, video, g_crop, crop);
777 if (ret != -ENOIOCTLCMD)
778 return ret;
779
780 format.pad = pad;
781 format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
782 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
783 if (ret < 0)
784 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
785
786 crop->c.left = 0;
787 crop->c.top = 0;
788 crop->c.width = format.format.width;
789 crop->c.height = format.format.height;
790
791 return 0;
792}
793
794static int
795isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop)
796{
797 struct isp_video *video = video_drvdata(file);
798 struct v4l2_subdev *subdev;
799 int ret;
800
801 subdev = isp_video_remote_subdev(video, NULL);
802 if (subdev == NULL)
803 return -EINVAL;
804
805 mutex_lock(&video->mutex);
806 ret = v4l2_subdev_call(subdev, video, s_crop, crop);
807 mutex_unlock(&video->mutex);
808
809 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
810}
811
812static int
813isp_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a)
814{
815 struct isp_video_fh *vfh = to_isp_video_fh(fh);
816 struct isp_video *video = video_drvdata(file);
817
818 if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
819 video->type != a->type)
820 return -EINVAL;
821
822 memset(a, 0, sizeof(*a));
823 a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
824 a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
825 a->parm.output.timeperframe = vfh->timeperframe;
826
827 return 0;
828}
829
830static int
831isp_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a)
832{
833 struct isp_video_fh *vfh = to_isp_video_fh(fh);
834 struct isp_video *video = video_drvdata(file);
835
836 if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
837 video->type != a->type)
838 return -EINVAL;
839
840 if (a->parm.output.timeperframe.denominator == 0)
841 a->parm.output.timeperframe.denominator = 1;
842
843 vfh->timeperframe = a->parm.output.timeperframe;
844
845 return 0;
846}
847
848static int
849isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
850{
851 struct isp_video_fh *vfh = to_isp_video_fh(fh);
852
853 return omap3isp_video_queue_reqbufs(&vfh->queue, rb);
854}
855
856static int
857isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
858{
859 struct isp_video_fh *vfh = to_isp_video_fh(fh);
860
861 return omap3isp_video_queue_querybuf(&vfh->queue, b);
862}
863
864static int
865isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
866{
867 struct isp_video_fh *vfh = to_isp_video_fh(fh);
868
869 return omap3isp_video_queue_qbuf(&vfh->queue, b);
870}
871
872static int
873isp_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
874{
875 struct isp_video_fh *vfh = to_isp_video_fh(fh);
876
877 return omap3isp_video_queue_dqbuf(&vfh->queue, b,
878 file->f_flags & O_NONBLOCK);
879}
880
881static int isp_video_check_external_subdevs(struct isp_video *video,
882 struct isp_pipeline *pipe)
883{
884 struct isp_device *isp = video->isp;
885 struct media_entity *ents[] = {
886 &isp->isp_csi2a.subdev.entity,
887 &isp->isp_csi2c.subdev.entity,
888 &isp->isp_ccp2.subdev.entity,
889 &isp->isp_ccdc.subdev.entity
890 };
891 struct media_pad *source_pad;
892 struct media_entity *source = NULL;
893 struct media_entity *sink;
894 struct v4l2_subdev_format fmt;
895 struct v4l2_ext_controls ctrls;
896 struct v4l2_ext_control ctrl;
897 unsigned int i;
898 int ret = 0;
899
900 for (i = 0; i < ARRAY_SIZE(ents); i++) {
901 /* Is the entity part of the pipeline? */
902 if (!(pipe->entities & (1 << ents[i]->id)))
903 continue;
904
905 /* ISP entities have always sink pad == 0. Find source. */
906 source_pad = media_entity_remote_source(&ents[i]->pads[0]);
907 if (source_pad == NULL)
908 continue;
909
910 source = source_pad->entity;
911 sink = ents[i];
912 break;
913 }
914
915 if (!source) {
916 dev_warn(isp->dev, "can't find source, failing now\n");
917 return ret;
918 }
919
920 if (media_entity_type(source) != MEDIA_ENT_T_V4L2_SUBDEV)
921 return 0;
922
923 pipe->external = media_entity_to_v4l2_subdev(source);
924
925 fmt.pad = source_pad->index;
926 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
927 ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(sink),
928 pad, get_fmt, NULL, &fmt);
929 if (unlikely(ret < 0)) {
930 dev_warn(isp->dev, "get_fmt returned null!\n");
931 return ret;
932 }
933
934 pipe->external_width =
935 omap3isp_video_format_info(fmt.format.code)->width;
936
937 memset(&ctrls, 0, sizeof(ctrls));
938 memset(&ctrl, 0, sizeof(ctrl));
939
940 ctrl.id = V4L2_CID_PIXEL_RATE;
941
942 ctrls.count = 1;
943 ctrls.controls = &ctrl;
944
945 ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, &ctrls);
946 if (ret < 0) {
947 dev_warn(isp->dev, "no pixel rate control in subdev %s\n",
948 pipe->external->name);
949 return ret;
950 }
951
952 pipe->external_rate = ctrl.value64;
953
954 if (pipe->entities & (1 << isp->isp_ccdc.subdev.entity.id)) {
955 unsigned int rate = UINT_MAX;
956 /*
957 * Check that maximum allowed CCDC pixel rate isn't
958 * exceeded by the pixel rate.
959 */
960 omap3isp_ccdc_max_rate(&isp->isp_ccdc, &rate);
961 if (pipe->external_rate > rate)
962 return -ENOSPC;
963 }
964
965 return 0;
966}
967
968/*
969 * Stream management
970 *
971 * Every ISP pipeline has a single input and a single output. The input can be
972 * either a sensor or a video node. The output is always a video node.
973 *
974 * As every pipeline has an output video node, the ISP video objects at the
975 * pipeline output stores the pipeline state. It tracks the streaming state of
976 * both the input and output, as well as the availability of buffers.
977 *
978 * In sensor-to-memory mode, frames are always available at the pipeline input.
979 * Starting the sensor usually requires I2C transfers and must be done in
980 * interruptible context. The pipeline is started and stopped synchronously
981 * to the stream on/off commands. All modules in the pipeline will get their
982 * subdev set stream handler called. The module at the end of the pipeline must
983 * delay starting the hardware until buffers are available at its output.
984 *
985 * In memory-to-memory mode, starting/stopping the stream requires
986 * synchronization between the input and output. ISP modules can't be stopped
987 * in the middle of a frame, and at least some of the modules seem to become
988 * busy as soon as they're started, even if they don't receive a frame start
989 * event. For that reason frames need to be processed in single-shot mode. The
990 * driver needs to wait until a frame is completely processed and written to
991 * memory before restarting the pipeline for the next frame. Pipelined
992 * processing might be possible but requires more testing.
993 *
994 * Stream start must be delayed until buffers are available at both the input
995 * and output. The pipeline must be started in the videobuf queue callback with
996 * the buffers queue spinlock held. The modules subdev set stream operation must
997 * not sleep.
998 */
999static int
1000isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
1001{
1002 struct isp_video_fh *vfh = to_isp_video_fh(fh);
1003 struct isp_video *video = video_drvdata(file);
1004 enum isp_pipeline_state state;
1005 struct isp_pipeline *pipe;
1006 unsigned long flags;
1007 int ret;
1008
1009 if (type != video->type)
1010 return -EINVAL;
1011
1012 mutex_lock(&video->stream_lock);
1013
1014 if (video->streaming) {
1015 mutex_unlock(&video->stream_lock);
1016 return -EBUSY;
1017 }
1018
1019 /* Start streaming on the pipeline. No link touching an entity in the
1020 * pipeline can be activated or deactivated once streaming is started.
1021 */
1022 pipe = video->video.entity.pipe
1023 ? to_isp_pipeline(&video->video.entity) : &video->pipe;
1024
1025 pipe->entities = 0;
1026
1027 if (video->isp->pdata->set_constraints)
1028 video->isp->pdata->set_constraints(video->isp, true);
1029 pipe->l3_ick = clk_get_rate(video->isp->clock[ISP_CLK_L3_ICK]);
1030 pipe->max_rate = pipe->l3_ick;
1031
1032 ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe);
1033 if (ret < 0)
1034 goto err_pipeline_start;
1035
1036 /* Verify that the currently configured format matches the output of
1037 * the connected subdev.
1038 */
1039 ret = isp_video_check_format(video, vfh);
1040 if (ret < 0)
1041 goto err_check_format;
1042
1043 video->bpl_padding = ret;
1044 video->bpl_value = vfh->format.fmt.pix.bytesperline;
1045
1046 ret = isp_video_get_graph_data(video, pipe);
1047 if (ret < 0)
1048 goto err_check_format;
1049
1050 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1051 state = ISP_PIPELINE_STREAM_OUTPUT | ISP_PIPELINE_IDLE_OUTPUT;
1052 else
1053 state = ISP_PIPELINE_STREAM_INPUT | ISP_PIPELINE_IDLE_INPUT;
1054
1055 ret = isp_video_check_external_subdevs(video, pipe);
1056 if (ret < 0)
1057 goto err_check_format;
1058
1059 /* Validate the pipeline and update its state. */
1060 ret = isp_video_validate_pipeline(pipe);
1061 if (ret < 0)
1062 goto err_check_format;
1063
1064 pipe->error = false;
1065
1066 spin_lock_irqsave(&pipe->lock, flags);
1067 pipe->state &= ~ISP_PIPELINE_STREAM;
1068 pipe->state |= state;
1069 spin_unlock_irqrestore(&pipe->lock, flags);
1070
1071 /* Set the maximum time per frame as the value requested by userspace.
1072 * This is a soft limit that can be overridden if the hardware doesn't
1073 * support the request limit.
1074 */
1075 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1076 pipe->max_timeperframe = vfh->timeperframe;
1077
1078 video->queue = &vfh->queue;
1079 INIT_LIST_HEAD(&video->dmaqueue);
1080 atomic_set(&pipe->frame_number, -1);
1081
1082 ret = omap3isp_video_queue_streamon(&vfh->queue);
1083 if (ret < 0)
1084 goto err_check_format;
1085
1086 /* In sensor-to-memory mode, the stream can be started synchronously
1087 * to the stream on command. In memory-to-memory mode, it will be
1088 * started when buffers are queued on both the input and output.
1089 */
1090 if (pipe->input == NULL) {
1091 ret = omap3isp_pipeline_set_stream(pipe,
1092 ISP_PIPELINE_STREAM_CONTINUOUS);
1093 if (ret < 0)
1094 goto err_set_stream;
1095 spin_lock_irqsave(&video->queue->irqlock, flags);
1096 if (list_empty(&video->dmaqueue))
1097 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
1098 spin_unlock_irqrestore(&video->queue->irqlock, flags);
1099 }
1100
1101 video->streaming = 1;
1102
1103 mutex_unlock(&video->stream_lock);
1104 return 0;
1105
1106err_set_stream:
1107 omap3isp_video_queue_streamoff(&vfh->queue);
1108err_check_format:
1109 media_entity_pipeline_stop(&video->video.entity);
1110err_pipeline_start:
1111 if (video->isp->pdata->set_constraints)
1112 video->isp->pdata->set_constraints(video->isp, false);
1113 /* The DMA queue must be emptied here, otherwise CCDC interrupts that
1114 * will get triggered the next time the CCDC is powered up will try to
1115 * access buffers that might have been freed but still present in the
1116 * DMA queue. This can easily get triggered if the above
1117 * omap3isp_pipeline_set_stream() call fails on a system with a
1118 * free-running sensor.
1119 */
1120 INIT_LIST_HEAD(&video->dmaqueue);
1121 video->queue = NULL;
1122
1123 mutex_unlock(&video->stream_lock);
1124 return ret;
1125}
1126
1127static int
1128isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
1129{
1130 struct isp_video_fh *vfh = to_isp_video_fh(fh);
1131 struct isp_video *video = video_drvdata(file);
1132 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
1133 enum isp_pipeline_state state;
1134 unsigned int streaming;
1135 unsigned long flags;
1136
1137 if (type != video->type)
1138 return -EINVAL;
1139
1140 mutex_lock(&video->stream_lock);
1141
1142 /* Make sure we're not streaming yet. */
1143 mutex_lock(&vfh->queue.lock);
1144 streaming = vfh->queue.streaming;
1145 mutex_unlock(&vfh->queue.lock);
1146
1147 if (!streaming)
1148 goto done;
1149
1150 /* Update the pipeline state. */
1151 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1152 state = ISP_PIPELINE_STREAM_OUTPUT
1153 | ISP_PIPELINE_QUEUE_OUTPUT;
1154 else
1155 state = ISP_PIPELINE_STREAM_INPUT
1156 | ISP_PIPELINE_QUEUE_INPUT;
1157
1158 spin_lock_irqsave(&pipe->lock, flags);
1159 pipe->state &= ~state;
1160 spin_unlock_irqrestore(&pipe->lock, flags);
1161
1162 /* Stop the stream. */
1163 omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_STOPPED);
1164 omap3isp_video_queue_streamoff(&vfh->queue);
1165 video->queue = NULL;
1166 video->streaming = 0;
1167
1168 if (video->isp->pdata->set_constraints)
1169 video->isp->pdata->set_constraints(video->isp, false);
1170 media_entity_pipeline_stop(&video->video.entity);
1171
1172done:
1173 mutex_unlock(&video->stream_lock);
1174 return 0;
1175}
1176
1177static int
1178isp_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
1179{
1180 if (input->index > 0)
1181 return -EINVAL;
1182
1183 strlcpy(input->name, "camera", sizeof(input->name));
1184 input->type = V4L2_INPUT_TYPE_CAMERA;
1185
1186 return 0;
1187}
1188
1189static int
1190isp_video_g_input(struct file *file, void *fh, unsigned int *input)
1191{
1192 *input = 0;
1193
1194 return 0;
1195}
1196
1197static int
1198isp_video_s_input(struct file *file, void *fh, unsigned int input)
1199{
1200 return input == 0 ? 0 : -EINVAL;
1201}
1202
1203static const struct v4l2_ioctl_ops isp_video_ioctl_ops = {
1204 .vidioc_querycap = isp_video_querycap,
1205 .vidioc_g_fmt_vid_cap = isp_video_get_format,
1206 .vidioc_s_fmt_vid_cap = isp_video_set_format,
1207 .vidioc_try_fmt_vid_cap = isp_video_try_format,
1208 .vidioc_g_fmt_vid_out = isp_video_get_format,
1209 .vidioc_s_fmt_vid_out = isp_video_set_format,
1210 .vidioc_try_fmt_vid_out = isp_video_try_format,
1211 .vidioc_cropcap = isp_video_cropcap,
1212 .vidioc_g_crop = isp_video_get_crop,
1213 .vidioc_s_crop = isp_video_set_crop,
1214 .vidioc_g_parm = isp_video_get_param,
1215 .vidioc_s_parm = isp_video_set_param,
1216 .vidioc_reqbufs = isp_video_reqbufs,
1217 .vidioc_querybuf = isp_video_querybuf,
1218 .vidioc_qbuf = isp_video_qbuf,
1219 .vidioc_dqbuf = isp_video_dqbuf,
1220 .vidioc_streamon = isp_video_streamon,
1221 .vidioc_streamoff = isp_video_streamoff,
1222 .vidioc_enum_input = isp_video_enum_input,
1223 .vidioc_g_input = isp_video_g_input,
1224 .vidioc_s_input = isp_video_s_input,
1225};
1226
1227/* -----------------------------------------------------------------------------
1228 * V4L2 file operations
1229 */
1230
1231static int isp_video_open(struct file *file)
1232{
1233 struct isp_video *video = video_drvdata(file);
1234 struct isp_video_fh *handle;
1235 int ret = 0;
1236
1237 handle = kzalloc(sizeof(*handle), GFP_KERNEL);
1238 if (handle == NULL)
1239 return -ENOMEM;
1240
1241 v4l2_fh_init(&handle->vfh, &video->video);
1242 v4l2_fh_add(&handle->vfh);
1243
1244 /* If this is the first user, initialise the pipeline. */
1245 if (omap3isp_get(video->isp) == NULL) {
1246 ret = -EBUSY;
1247 goto done;
1248 }
1249
1250 ret = omap3isp_pipeline_pm_use(&video->video.entity, 1);
1251 if (ret < 0) {
1252 omap3isp_put(video->isp);
1253 goto done;
1254 }
1255
1256 omap3isp_video_queue_init(&handle->queue, video->type,
1257 &isp_video_queue_ops, video->isp->dev,
1258 sizeof(struct isp_buffer));
1259
1260 memset(&handle->format, 0, sizeof(handle->format));
1261 handle->format.type = video->type;
1262 handle->timeperframe.denominator = 1;
1263
1264 handle->video = video;
1265 file->private_data = &handle->vfh;
1266
1267done:
1268 if (ret < 0) {
1269 v4l2_fh_del(&handle->vfh);
1270 kfree(handle);
1271 }
1272
1273 return ret;
1274}
1275
1276static int isp_video_release(struct file *file)
1277{
1278 struct isp_video *video = video_drvdata(file);
1279 struct v4l2_fh *vfh = file->private_data;
1280 struct isp_video_fh *handle = to_isp_video_fh(vfh);
1281
1282 /* Disable streaming and free the buffers queue resources. */
1283 isp_video_streamoff(file, vfh, video->type);
1284
1285 mutex_lock(&handle->queue.lock);
1286 omap3isp_video_queue_cleanup(&handle->queue);
1287 mutex_unlock(&handle->queue.lock);
1288
1289 omap3isp_pipeline_pm_use(&video->video.entity, 0);
1290
1291 /* Release the file handle. */
1292 v4l2_fh_del(vfh);
1293 kfree(handle);
1294 file->private_data = NULL;
1295
1296 omap3isp_put(video->isp);
1297
1298 return 0;
1299}
1300
1301static unsigned int isp_video_poll(struct file *file, poll_table *wait)
1302{
1303 struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
1304 struct isp_video_queue *queue = &vfh->queue;
1305
1306 return omap3isp_video_queue_poll(queue, file, wait);
1307}
1308
1309static int isp_video_mmap(struct file *file, struct vm_area_struct *vma)
1310{
1311 struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
1312
1313 return omap3isp_video_queue_mmap(&vfh->queue, vma);
1314}
1315
1316static struct v4l2_file_operations isp_video_fops = {
1317 .owner = THIS_MODULE,
1318 .unlocked_ioctl = video_ioctl2,
1319 .open = isp_video_open,
1320 .release = isp_video_release,
1321 .poll = isp_video_poll,
1322 .mmap = isp_video_mmap,
1323};
1324
1325/* -----------------------------------------------------------------------------
1326 * ISP video core
1327 */
1328
1329static const struct isp_video_operations isp_video_dummy_ops = {
1330};
1331
1332int omap3isp_video_init(struct isp_video *video, const char *name)
1333{
1334 const char *direction;
1335 int ret;
1336
1337 switch (video->type) {
1338 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1339 direction = "output";
1340 video->pad.flags = MEDIA_PAD_FL_SINK;
1341 break;
1342 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1343 direction = "input";
1344 video->pad.flags = MEDIA_PAD_FL_SOURCE;
1345 video->video.vfl_dir = VFL_DIR_TX;
1346 break;
1347
1348 default:
1349 return -EINVAL;
1350 }
1351
1352 ret = media_entity_init(&video->video.entity, 1, &video->pad, 0);
1353 if (ret < 0)
1354 return ret;
1355
1356 mutex_init(&video->mutex);
1357 atomic_set(&video->active, 0);
1358
1359 spin_lock_init(&video->pipe.lock);
1360 mutex_init(&video->stream_lock);
1361
1362 /* Initialize the video device. */
1363 if (video->ops == NULL)
1364 video->ops = &isp_video_dummy_ops;
1365
1366 video->video.fops = &isp_video_fops;
1367 snprintf(video->video.name, sizeof(video->video.name),
1368 "OMAP3 ISP %s %s", name, direction);
1369 video->video.vfl_type = VFL_TYPE_GRABBER;
1370 video->video.release = video_device_release_empty;
1371 video->video.ioctl_ops = &isp_video_ioctl_ops;
1372 video->pipe.stream_state = ISP_PIPELINE_STREAM_STOPPED;
1373
1374 video_set_drvdata(&video->video, video);
1375
1376 return 0;
1377}
1378
1379void omap3isp_video_cleanup(struct isp_video *video)
1380{
1381 media_entity_cleanup(&video->video.entity);
1382 mutex_destroy(&video->stream_lock);
1383 mutex_destroy(&video->mutex);
1384}
1385
1386int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
1387{
1388 int ret;
1389
1390 video->video.v4l2_dev = vdev;
1391
1392 ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
1393 if (ret < 0)
1394 printk(KERN_ERR "%s: could not register video device (%d)\n",
1395 __func__, ret);
1396
1397 return ret;
1398}
1399
1400void omap3isp_video_unregister(struct isp_video *video)
1401{
1402 if (video_is_registered(&video->video))
1403 video_unregister_device(&video->video);
1404}
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
new file mode 100644
index 000000000000..1ad470ec2b9d
--- /dev/null
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -0,0 +1,216 @@
1/*
2 * ispvideo.h
3 *
4 * TI OMAP3 ISP - Generic video node
5 *
6 * Copyright (C) 2009-2010 Nokia Corporation
7 *
8 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9 * Sakari Ailus <sakari.ailus@iki.fi>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA
24 */
25
26#ifndef OMAP3_ISP_VIDEO_H
27#define OMAP3_ISP_VIDEO_H
28
29#include <linux/v4l2-mediabus.h>
30#include <media/media-entity.h>
31#include <media/v4l2-dev.h>
32#include <media/v4l2-fh.h>
33
34#include "ispqueue.h"
35
36#define ISP_VIDEO_DRIVER_NAME "ispvideo"
37#define ISP_VIDEO_DRIVER_VERSION "0.0.2"
38
39struct isp_device;
40struct isp_video;
41struct v4l2_mbus_framefmt;
42struct v4l2_pix_format;
43
44/*
45 * struct isp_format_info - ISP media bus format information
46 * @code: V4L2 media bus format code
47 * @truncated: V4L2 media bus format code for the same format truncated to 10
48 * bits. Identical to @code if the format is 10 bits wide or less.
49 * @uncompressed: V4L2 media bus format code for the corresponding uncompressed
50 * format. Identical to @code if the format is not DPCM compressed.
51 * @flavor: V4L2 media bus format code for the same pixel layout but
52 * shifted to be 8 bits per pixel. =0 if format is not shiftable.
53 * @pixelformat: V4L2 pixel format FCC identifier
54 * @width: Bits per pixel (when transferred over a bus)
55 * @bpp: Bytes per pixel (when stored in memory)
56 */
57struct isp_format_info {
58 enum v4l2_mbus_pixelcode code;
59 enum v4l2_mbus_pixelcode truncated;
60 enum v4l2_mbus_pixelcode uncompressed;
61 enum v4l2_mbus_pixelcode flavor;
62 u32 pixelformat;
63 unsigned int width;
64 unsigned int bpp;
65};
66
67enum isp_pipeline_stream_state {
68 ISP_PIPELINE_STREAM_STOPPED = 0,
69 ISP_PIPELINE_STREAM_CONTINUOUS = 1,
70 ISP_PIPELINE_STREAM_SINGLESHOT = 2,
71};
72
73enum isp_pipeline_state {
74 /* The stream has been started on the input video node. */
75 ISP_PIPELINE_STREAM_INPUT = 1,
76 /* The stream has been started on the output video node. */
77 ISP_PIPELINE_STREAM_OUTPUT = 2,
78 /* At least one buffer is queued on the input video node. */
79 ISP_PIPELINE_QUEUE_INPUT = 4,
80 /* At least one buffer is queued on the output video node. */
81 ISP_PIPELINE_QUEUE_OUTPUT = 8,
82 /* The input entity is idle, ready to be started. */
83 ISP_PIPELINE_IDLE_INPUT = 16,
84 /* The output entity is idle, ready to be started. */
85 ISP_PIPELINE_IDLE_OUTPUT = 32,
86 /* The pipeline is currently streaming. */
87 ISP_PIPELINE_STREAM = 64,
88};
89
90/*
91 * struct isp_pipeline - An ISP hardware pipeline
92 * @error: A hardware error occurred during capture
93 * @entities: Bitmask of entities in the pipeline (indexed by entity ID)
94 */
95struct isp_pipeline {
96 struct media_pipeline pipe;
97 spinlock_t lock; /* Pipeline state and queue flags */
98 unsigned int state;
99 enum isp_pipeline_stream_state stream_state;
100 struct isp_video *input;
101 struct isp_video *output;
102 u32 entities;
103 unsigned long l3_ick;
104 unsigned int max_rate;
105 atomic_t frame_number;
106 bool do_propagation; /* of frame number */
107 bool error;
108 struct v4l2_fract max_timeperframe;
109 struct v4l2_subdev *external;
110 unsigned int external_rate;
111 unsigned int external_width;
112};
113
114#define to_isp_pipeline(__e) \
115 container_of((__e)->pipe, struct isp_pipeline, pipe)
116
117static inline int isp_pipeline_ready(struct isp_pipeline *pipe)
118{
119 return pipe->state == (ISP_PIPELINE_STREAM_INPUT |
120 ISP_PIPELINE_STREAM_OUTPUT |
121 ISP_PIPELINE_QUEUE_INPUT |
122 ISP_PIPELINE_QUEUE_OUTPUT |
123 ISP_PIPELINE_IDLE_INPUT |
124 ISP_PIPELINE_IDLE_OUTPUT);
125}
126
127/*
128 * struct isp_buffer - ISP buffer
129 * @buffer: ISP video buffer
130 * @isp_addr: MMU mapped address (a.k.a. device address) of the buffer.
131 */
132struct isp_buffer {
133 struct isp_video_buffer buffer;
134 dma_addr_t isp_addr;
135};
136
137#define to_isp_buffer(buf) container_of(buf, struct isp_buffer, buffer)
138
139enum isp_video_dmaqueue_flags {
140 /* Set if DMA queue becomes empty when ISP_PIPELINE_STREAM_CONTINUOUS */
141 ISP_VIDEO_DMAQUEUE_UNDERRUN = (1 << 0),
142 /* Set when queuing buffer to an empty DMA queue */
143 ISP_VIDEO_DMAQUEUE_QUEUED = (1 << 1),
144};
145
146#define isp_video_dmaqueue_flags_clr(video) \
147 ({ (video)->dmaqueue_flags = 0; })
148
149/*
150 * struct isp_video_operations - ISP video operations
151 * @queue: Resume streaming when a buffer is queued. Called on VIDIOC_QBUF
152 * if there was no buffer previously queued.
153 */
154struct isp_video_operations {
155 int(*queue)(struct isp_video *video, struct isp_buffer *buffer);
156};
157
158struct isp_video {
159 struct video_device video;
160 enum v4l2_buf_type type;
161 struct media_pad pad;
162
163 struct mutex mutex; /* format and crop settings */
164 atomic_t active;
165
166 struct isp_device *isp;
167
168 unsigned int capture_mem;
169 unsigned int bpl_alignment; /* alignment value */
170 unsigned int bpl_zero_padding; /* whether the alignment is optional */
171 unsigned int bpl_max; /* maximum bytes per line value */
172 unsigned int bpl_value; /* bytes per line value */
173 unsigned int bpl_padding; /* padding at end of line */
174
175 /* Entity video node streaming */
176 unsigned int streaming:1;
177
178 /* Pipeline state */
179 struct isp_pipeline pipe;
180 struct mutex stream_lock; /* pipeline and stream states */
181
182 /* Video buffers queue */
183 struct isp_video_queue *queue;
184 struct list_head dmaqueue;
185 enum isp_video_dmaqueue_flags dmaqueue_flags;
186
187 const struct isp_video_operations *ops;
188};
189
190#define to_isp_video(vdev) container_of(vdev, struct isp_video, video)
191
192struct isp_video_fh {
193 struct v4l2_fh vfh;
194 struct isp_video *video;
195 struct isp_video_queue queue;
196 struct v4l2_format format;
197 struct v4l2_fract timeperframe;
198};
199
200#define to_isp_video_fh(fh) container_of(fh, struct isp_video_fh, vfh)
201#define isp_video_queue_to_isp_video_fh(q) \
202 container_of(q, struct isp_video_fh, queue)
203
204int omap3isp_video_init(struct isp_video *video, const char *name);
205void omap3isp_video_cleanup(struct isp_video *video);
206int omap3isp_video_register(struct isp_video *video,
207 struct v4l2_device *vdev);
208void omap3isp_video_unregister(struct isp_video *video);
209struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video);
210void omap3isp_video_resume(struct isp_video *video, int continuous);
211struct media_pad *omap3isp_video_remote_pad(struct isp_video *video);
212
213const struct isp_format_info *
214omap3isp_video_format_info(enum v4l2_mbus_pixelcode code);
215
216#endif /* OMAP3_ISP_VIDEO_H */
diff --git a/drivers/media/platform/omap3isp/luma_enhance_table.h b/drivers/media/platform/omap3isp/luma_enhance_table.h
new file mode 100644
index 000000000000..098b45e2280f
--- /dev/null
+++ b/drivers/media/platform/omap3isp/luma_enhance_table.h
@@ -0,0 +1,42 @@
1/*
2 * luma_enhance_table.h
3 *
4 * TI OMAP3 ISP - Luminance enhancement table
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
271047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552,
281047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552,
291047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552,
301047552, 1047552, 1047552, 1047552, 1048575, 1047551, 1046527, 1045503,
311044479, 1043455, 1042431, 1041407, 1040383, 1039359, 1038335, 1037311,
321036287, 1035263, 1034239, 1033215, 1032191, 1031167, 1030143, 1028096,
331028096, 1028096, 1028096, 1028096, 1028096, 1028096, 1028096, 1028096,
341028096, 1028100, 1032196, 1036292, 1040388, 1044484, 0, 0,
35 0, 5, 5125, 10245, 15365, 20485, 25605, 30720,
36 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720,
37 30720, 30720, 31743, 30719, 29695, 28671, 27647, 26623,
38 25599, 24575, 23551, 22527, 21503, 20479, 19455, 18431,
39 17407, 16383, 15359, 14335, 13311, 12287, 11263, 10239,
40 9215, 8191, 7167, 6143, 5119, 4095, 3071, 1024,
41 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
42 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024
diff --git a/drivers/media/platform/omap3isp/noise_filter_table.h b/drivers/media/platform/omap3isp/noise_filter_table.h
new file mode 100644
index 000000000000..d50451a4a242
--- /dev/null
+++ b/drivers/media/platform/omap3isp/noise_filter_table.h
@@ -0,0 +1,30 @@
1/*
2 * noise_filter_table.h
3 *
4 * TI OMAP3 ISP - Noise filter table
5 *
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
8 *
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
2716, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2816, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2931, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
3031, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31