aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/omap3isp
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/video/omap3isp
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/media/video/omap3isp')
-rw-r--r--drivers/media/video/omap3isp/Makefile13
-rw-r--r--drivers/media/video/omap3isp/cfa_coef_table.h61
-rw-r--r--drivers/media/video/omap3isp/gamma_table.h90
-rw-r--r--drivers/media/video/omap3isp/isp.c2244
-rw-r--r--drivers/media/video/omap3isp/isp.h438
-rw-r--r--drivers/media/video/omap3isp/ispccdc.c2315
-rw-r--r--drivers/media/video/omap3isp/ispccdc.h219
-rw-r--r--drivers/media/video/omap3isp/ispccp2.c1196
-rw-r--r--drivers/media/video/omap3isp/ispccp2.h99
-rw-r--r--drivers/media/video/omap3isp/ispcsi2.c1317
-rw-r--r--drivers/media/video/omap3isp/ispcsi2.h166
-rw-r--r--drivers/media/video/omap3isp/ispcsiphy.c247
-rw-r--r--drivers/media/video/omap3isp/ispcsiphy.h74
-rw-r--r--drivers/media/video/omap3isp/isph3a.h117
-rw-r--r--drivers/media/video/omap3isp/isph3a_aewb.c374
-rw-r--r--drivers/media/video/omap3isp/isph3a_af.c429
-rw-r--r--drivers/media/video/omap3isp/isphist.c520
-rw-r--r--drivers/media/video/omap3isp/isphist.h40
-rw-r--r--drivers/media/video/omap3isp/isppreview.c2113
-rw-r--r--drivers/media/video/omap3isp/isppreview.h214
-rw-r--r--drivers/media/video/omap3isp/ispqueue.c1153
-rw-r--r--drivers/media/video/omap3isp/ispqueue.h187
-rw-r--r--drivers/media/video/omap3isp/ispreg.h1589
-rw-r--r--drivers/media/video/omap3isp/ispresizer.c1738
-rw-r--r--drivers/media/video/omap3isp/ispresizer.h147
-rw-r--r--drivers/media/video/omap3isp/ispstat.c1092
-rw-r--r--drivers/media/video/omap3isp/ispstat.h169
-rw-r--r--drivers/media/video/omap3isp/ispvideo.c1334
-rw-r--r--drivers/media/video/omap3isp/ispvideo.h204
-rw-r--r--drivers/media/video/omap3isp/luma_enhance_table.h42
-rw-r--r--drivers/media/video/omap3isp/noise_filter_table.h30
31 files changed, 19971 insertions, 0 deletions
diff --git a/drivers/media/video/omap3isp/Makefile b/drivers/media/video/omap3isp/Makefile
new file mode 100644
index 00000000000..b1b344774ae
--- /dev/null
+++ b/drivers/media/video/omap3isp/Makefile
@@ -0,0 +1,13 @@
1# Makefile for OMAP3 ISP driver
2
3ifdef CONFIG_VIDEO_OMAP3_DEBUG
4EXTRA_CFLAGS += -DDEBUG
5endif
6
7omap3-isp-objs += \
8 isp.o ispqueue.o ispvideo.o \
9 ispcsiphy.o ispccp2.o ispcsi2.o \
10 ispccdc.o isppreview.o ispresizer.o \
11 ispstat.o isph3a_aewb.o isph3a_af.o isphist.o
12
13obj-$(CONFIG_VIDEO_OMAP3) += omap3-isp.o
diff --git a/drivers/media/video/omap3isp/cfa_coef_table.h b/drivers/media/video/omap3isp/cfa_coef_table.h
new file mode 100644
index 00000000000..c60df0ed075
--- /dev/null
+++ b/drivers/media/video/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
26244, 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,
53244, 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/video/omap3isp/gamma_table.h b/drivers/media/video/omap3isp/gamma_table.h
new file mode 100644
index 00000000000..78deebf7d96
--- /dev/null
+++ b/drivers/media/video/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/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c
new file mode 100644
index 00000000000..abc26854e29
--- /dev/null
+++ b/drivers/media/video/omap3isp/isp.c
@@ -0,0 +1,2244 @@
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 "isp.h"
74#include "ispreg.h"
75#include "ispccdc.h"
76#include "isppreview.h"
77#include "ispresizer.h"
78#include "ispcsi2.h"
79#include "ispccp2.h"
80#include "isph3a.h"
81#include "isphist.h"
82
83static unsigned int autoidle;
84module_param(autoidle, int, 0444);
85MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support");
86
87static void isp_save_ctx(struct isp_device *isp);
88
89static void isp_restore_ctx(struct isp_device *isp);
90
91static const struct isp_res_mapping isp_res_maps[] = {
92 {
93 .isp_rev = ISP_REVISION_2_0,
94 .map = 1 << OMAP3_ISP_IOMEM_MAIN |
95 1 << OMAP3_ISP_IOMEM_CCP2 |
96 1 << OMAP3_ISP_IOMEM_CCDC |
97 1 << OMAP3_ISP_IOMEM_HIST |
98 1 << OMAP3_ISP_IOMEM_H3A |
99 1 << OMAP3_ISP_IOMEM_PREV |
100 1 << OMAP3_ISP_IOMEM_RESZ |
101 1 << OMAP3_ISP_IOMEM_SBL |
102 1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
103 1 << OMAP3_ISP_IOMEM_CSIPHY2,
104 },
105 {
106 .isp_rev = ISP_REVISION_15_0,
107 .map = 1 << OMAP3_ISP_IOMEM_MAIN |
108 1 << OMAP3_ISP_IOMEM_CCP2 |
109 1 << OMAP3_ISP_IOMEM_CCDC |
110 1 << OMAP3_ISP_IOMEM_HIST |
111 1 << OMAP3_ISP_IOMEM_H3A |
112 1 << OMAP3_ISP_IOMEM_PREV |
113 1 << OMAP3_ISP_IOMEM_RESZ |
114 1 << OMAP3_ISP_IOMEM_SBL |
115 1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
116 1 << OMAP3_ISP_IOMEM_CSIPHY2 |
117 1 << OMAP3_ISP_IOMEM_CSI2A_REGS2 |
118 1 << OMAP3_ISP_IOMEM_CSI2C_REGS1 |
119 1 << OMAP3_ISP_IOMEM_CSIPHY1 |
120 1 << OMAP3_ISP_IOMEM_CSI2C_REGS2,
121 },
122};
123
124/* Structure for saving/restoring ISP module registers */
125static struct isp_reg isp_reg_list[] = {
126 {OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG, 0},
127 {OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, 0},
128 {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL, 0},
129 {0, ISP_TOK_TERM, 0}
130};
131
132/*
133 * omap3isp_flush - Post pending L3 bus writes by doing a register readback
134 * @isp: OMAP3 ISP device
135 *
136 * In order to force posting of pending writes, we need to write and
137 * readback the same register, in this case the revision register.
138 *
139 * See this link for reference:
140 * http://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html
141 */
142void omap3isp_flush(struct isp_device *isp)
143{
144 isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
145 isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
146}
147
148/*
149 * isp_enable_interrupts - Enable ISP interrupts.
150 * @isp: OMAP3 ISP device
151 */
152static void isp_enable_interrupts(struct isp_device *isp)
153{
154 static const u32 irq = IRQ0ENABLE_CSIA_IRQ
155 | IRQ0ENABLE_CSIB_IRQ
156 | IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ
157 | IRQ0ENABLE_CCDC_LSC_DONE_IRQ
158 | IRQ0ENABLE_CCDC_VD0_IRQ
159 | IRQ0ENABLE_CCDC_VD1_IRQ
160 | IRQ0ENABLE_HS_VS_IRQ
161 | IRQ0ENABLE_HIST_DONE_IRQ
162 | IRQ0ENABLE_H3A_AWB_DONE_IRQ
163 | IRQ0ENABLE_H3A_AF_DONE_IRQ
164 | IRQ0ENABLE_PRV_DONE_IRQ
165 | IRQ0ENABLE_RSZ_DONE_IRQ;
166
167 isp_reg_writel(isp, irq, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
168 isp_reg_writel(isp, irq, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE);
169}
170
171/*
172 * isp_disable_interrupts - Disable ISP interrupts.
173 * @isp: OMAP3 ISP device
174 */
175static void isp_disable_interrupts(struct isp_device *isp)
176{
177 isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE);
178}
179
180/**
181 * isp_set_xclk - Configures the specified cam_xclk to the desired frequency.
182 * @isp: OMAP3 ISP device
183 * @xclk: Desired frequency of the clock in Hz. 0 = stable low, 1 is stable high
184 * @xclksel: XCLK to configure (0 = A, 1 = B).
185 *
186 * Configures the specified MCLK divisor in the ISP timing control register
187 * (TCTRL_CTRL) to generate the desired xclk clock value.
188 *
189 * Divisor = cam_mclk_hz / xclk
190 *
191 * Returns the final frequency that is actually being generated
192 **/
193static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
194{
195 u32 divisor;
196 u32 currentxclk;
197 unsigned long mclk_hz;
198
199 if (!omap3isp_get(isp))
200 return 0;
201
202 mclk_hz = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
203
204 if (xclk >= mclk_hz) {
205 divisor = ISPTCTRL_CTRL_DIV_BYPASS;
206 currentxclk = mclk_hz;
207 } else if (xclk >= 2) {
208 divisor = mclk_hz / xclk;
209 if (divisor >= ISPTCTRL_CTRL_DIV_BYPASS)
210 divisor = ISPTCTRL_CTRL_DIV_BYPASS - 1;
211 currentxclk = mclk_hz / divisor;
212 } else {
213 divisor = xclk;
214 currentxclk = 0;
215 }
216
217 switch (xclksel) {
218 case ISP_XCLK_A:
219 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
220 ISPTCTRL_CTRL_DIVA_MASK,
221 divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
222 dev_dbg(isp->dev, "isp_set_xclk(): cam_xclka set to %d Hz\n",
223 currentxclk);
224 break;
225 case ISP_XCLK_B:
226 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
227 ISPTCTRL_CTRL_DIVB_MASK,
228 divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
229 dev_dbg(isp->dev, "isp_set_xclk(): cam_xclkb set to %d Hz\n",
230 currentxclk);
231 break;
232 case ISP_XCLK_NONE:
233 default:
234 omap3isp_put(isp);
235 dev_dbg(isp->dev, "ISP_ERR: isp_set_xclk(): Invalid requested "
236 "xclk. Must be 0 (A) or 1 (B).\n");
237 return -EINVAL;
238 }
239
240 /* Do we go from stable whatever to clock? */
241 if (divisor >= 2 && isp->xclk_divisor[xclksel - 1] < 2)
242 omap3isp_get(isp);
243 /* Stopping the clock. */
244 else if (divisor < 2 && isp->xclk_divisor[xclksel - 1] >= 2)
245 omap3isp_put(isp);
246
247 isp->xclk_divisor[xclksel - 1] = divisor;
248
249 omap3isp_put(isp);
250
251 return currentxclk;
252}
253
254/*
255 * isp_power_settings - Sysconfig settings, for Power Management.
256 * @isp: OMAP3 ISP device
257 * @idle: Consider idle state.
258 *
259 * Sets the power settings for the ISP, and SBL bus.
260 */
261static void isp_power_settings(struct isp_device *isp, int idle)
262{
263 isp_reg_writel(isp,
264 ((idle ? ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY :
265 ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY) <<
266 ISP_SYSCONFIG_MIDLEMODE_SHIFT) |
267 ((isp->revision == ISP_REVISION_15_0) ?
268 ISP_SYSCONFIG_AUTOIDLE : 0),
269 OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
270
271 if (isp->autoidle)
272 isp_reg_writel(isp, ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
273 ISP_CTRL);
274}
275
276/*
277 * Configure the bridge and lane shifter. Valid inputs are
278 *
279 * CCDC_INPUT_PARALLEL: Parallel interface
280 * CCDC_INPUT_CSI2A: CSI2a receiver
281 * CCDC_INPUT_CCP2B: CCP2b receiver
282 * CCDC_INPUT_CSI2C: CSI2c receiver
283 *
284 * The bridge and lane shifter are configured according to the selected input
285 * and the ISP platform data.
286 */
287void omap3isp_configure_bridge(struct isp_device *isp,
288 enum ccdc_input_entity input,
289 const struct isp_parallel_platform_data *pdata,
290 unsigned int shift)
291{
292 u32 ispctrl_val;
293
294 ispctrl_val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
295 ispctrl_val &= ~ISPCTRL_SHIFT_MASK;
296 ispctrl_val &= ~ISPCTRL_PAR_CLK_POL_INV;
297 ispctrl_val &= ~ISPCTRL_PAR_SER_CLK_SEL_MASK;
298 ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_MASK;
299
300 switch (input) {
301 case CCDC_INPUT_PARALLEL:
302 ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
303 ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
304 ispctrl_val |= pdata->bridge << ISPCTRL_PAR_BRIDGE_SHIFT;
305 shift += pdata->data_lane_shift * 2;
306 break;
307
308 case CCDC_INPUT_CSI2A:
309 ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIA;
310 break;
311
312 case CCDC_INPUT_CCP2B:
313 ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIB;
314 break;
315
316 case CCDC_INPUT_CSI2C:
317 ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIC;
318 break;
319
320 default:
321 return;
322 }
323
324 ispctrl_val |= ((shift/2) << ISPCTRL_SHIFT_SHIFT) & ISPCTRL_SHIFT_MASK;
325
326 ispctrl_val &= ~ISPCTRL_SYNC_DETECT_MASK;
327 ispctrl_val |= ISPCTRL_SYNC_DETECT_VSRISE;
328
329 isp_reg_writel(isp, ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
330}
331
332/**
333 * isp_set_pixel_clock - Configures the ISP pixel clock
334 * @isp: OMAP3 ISP device
335 * @pixelclk: Average pixel clock in Hz
336 *
337 * Set the average pixel clock required by the sensor. The ISP will use the
338 * lowest possible memory bandwidth settings compatible with the clock.
339 **/
340static void isp_set_pixel_clock(struct isp_device *isp, unsigned int pixelclk)
341{
342 isp->isp_ccdc.vpcfg.pixelclk = pixelclk;
343}
344
345void omap3isp_hist_dma_done(struct isp_device *isp)
346{
347 if (omap3isp_ccdc_busy(&isp->isp_ccdc) ||
348 omap3isp_stat_pcr_busy(&isp->isp_hist)) {
349 /* Histogram cannot be enabled in this frame anymore */
350 atomic_set(&isp->isp_hist.buf_err, 1);
351 dev_dbg(isp->dev, "hist: Out of synchronization with "
352 "CCDC. Ignoring next buffer.\n");
353 }
354}
355
356static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus)
357{
358 static const char *name[] = {
359 "CSIA_IRQ",
360 "res1",
361 "res2",
362 "CSIB_LCM_IRQ",
363 "CSIB_IRQ",
364 "res5",
365 "res6",
366 "res7",
367 "CCDC_VD0_IRQ",
368 "CCDC_VD1_IRQ",
369 "CCDC_VD2_IRQ",
370 "CCDC_ERR_IRQ",
371 "H3A_AF_DONE_IRQ",
372 "H3A_AWB_DONE_IRQ",
373 "res14",
374 "res15",
375 "HIST_DONE_IRQ",
376 "CCDC_LSC_DONE",
377 "CCDC_LSC_PREFETCH_COMPLETED",
378 "CCDC_LSC_PREFETCH_ERROR",
379 "PRV_DONE_IRQ",
380 "CBUFF_IRQ",
381 "res22",
382 "res23",
383 "RSZ_DONE_IRQ",
384 "OVF_IRQ",
385 "res26",
386 "res27",
387 "MMU_ERR_IRQ",
388 "OCP_ERR_IRQ",
389 "SEC_ERR_IRQ",
390 "HS_VS_IRQ",
391 };
392 int i;
393
394 dev_dbg(isp->dev, "ISP IRQ: ");
395
396 for (i = 0; i < ARRAY_SIZE(name); i++) {
397 if ((1 << i) & irqstatus)
398 printk(KERN_CONT "%s ", name[i]);
399 }
400 printk(KERN_CONT "\n");
401}
402
403static void isp_isr_sbl(struct isp_device *isp)
404{
405 struct device *dev = isp->dev;
406 u32 sbl_pcr;
407
408 /*
409 * Handle shared buffer logic overflows for video buffers.
410 * ISPSBL_PCR_CCDCPRV_2_RSZ_OVF can be safely ignored.
411 */
412 sbl_pcr = isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_PCR);
413 isp_reg_writel(isp, sbl_pcr, OMAP3_ISP_IOMEM_SBL, ISPSBL_PCR);
414 sbl_pcr &= ~ISPSBL_PCR_CCDCPRV_2_RSZ_OVF;
415
416 if (sbl_pcr)
417 dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr);
418
419 if (sbl_pcr & (ISPSBL_PCR_CCDC_WBL_OVF | ISPSBL_PCR_CSIA_WBL_OVF
420 | ISPSBL_PCR_CSIB_WBL_OVF)) {
421 isp->isp_ccdc.error = 1;
422 if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
423 isp->isp_prev.error = 1;
424 if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)
425 isp->isp_res.error = 1;
426 }
427
428 if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) {
429 isp->isp_prev.error = 1;
430 if (isp->isp_res.input == RESIZER_INPUT_VP &&
431 !(isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER))
432 isp->isp_res.error = 1;
433 }
434
435 if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF
436 | ISPSBL_PCR_RSZ2_WBL_OVF
437 | ISPSBL_PCR_RSZ3_WBL_OVF
438 | ISPSBL_PCR_RSZ4_WBL_OVF))
439 isp->isp_res.error = 1;
440
441 if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF)
442 omap3isp_stat_sbl_overflow(&isp->isp_af);
443
444 if (sbl_pcr & ISPSBL_PCR_H3A_AEAWB_WBL_OVF)
445 omap3isp_stat_sbl_overflow(&isp->isp_aewb);
446}
447
448/*
449 * isp_isr - Interrupt Service Routine for Camera ISP module.
450 * @irq: Not used currently.
451 * @_isp: Pointer to the OMAP3 ISP device
452 *
453 * Handles the corresponding callback if plugged in.
454 *
455 * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
456 * IRQ wasn't handled.
457 */
458static irqreturn_t isp_isr(int irq, void *_isp)
459{
460 static const u32 ccdc_events = IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ |
461 IRQ0STATUS_CCDC_LSC_DONE_IRQ |
462 IRQ0STATUS_CCDC_VD0_IRQ |
463 IRQ0STATUS_CCDC_VD1_IRQ |
464 IRQ0STATUS_HS_VS_IRQ;
465 struct isp_device *isp = _isp;
466 u32 irqstatus;
467 int ret;
468
469 irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
470 isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
471
472 isp_isr_sbl(isp);
473
474 if (irqstatus & IRQ0STATUS_CSIA_IRQ) {
475 ret = omap3isp_csi2_isr(&isp->isp_csi2a);
476 if (ret)
477 isp->isp_ccdc.error = 1;
478 }
479
480 if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
481 ret = omap3isp_ccp2_isr(&isp->isp_ccp2);
482 if (ret)
483 isp->isp_ccdc.error = 1;
484 }
485
486 if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) {
487 if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
488 omap3isp_preview_isr_frame_sync(&isp->isp_prev);
489 if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)
490 omap3isp_resizer_isr_frame_sync(&isp->isp_res);
491 omap3isp_stat_isr_frame_sync(&isp->isp_aewb);
492 omap3isp_stat_isr_frame_sync(&isp->isp_af);
493 omap3isp_stat_isr_frame_sync(&isp->isp_hist);
494 }
495
496 if (irqstatus & ccdc_events)
497 omap3isp_ccdc_isr(&isp->isp_ccdc, irqstatus & ccdc_events);
498
499 if (irqstatus & IRQ0STATUS_PRV_DONE_IRQ) {
500 if (isp->isp_prev.output & PREVIEW_OUTPUT_RESIZER)
501 omap3isp_resizer_isr_frame_sync(&isp->isp_res);
502 omap3isp_preview_isr(&isp->isp_prev);
503 }
504
505 if (irqstatus & IRQ0STATUS_RSZ_DONE_IRQ)
506 omap3isp_resizer_isr(&isp->isp_res);
507
508 if (irqstatus & IRQ0STATUS_H3A_AWB_DONE_IRQ)
509 omap3isp_stat_isr(&isp->isp_aewb);
510
511 if (irqstatus & IRQ0STATUS_H3A_AF_DONE_IRQ)
512 omap3isp_stat_isr(&isp->isp_af);
513
514 if (irqstatus & IRQ0STATUS_HIST_DONE_IRQ)
515 omap3isp_stat_isr(&isp->isp_hist);
516
517 omap3isp_flush(isp);
518
519#if defined(DEBUG) && defined(ISP_ISR_DEBUG)
520 isp_isr_dbg(isp, irqstatus);
521#endif
522
523 return IRQ_HANDLED;
524}
525
526/* -----------------------------------------------------------------------------
527 * Pipeline power management
528 *
529 * Entities must be powered up when part of a pipeline that contains at least
530 * one open video device node.
531 *
532 * To achieve this use the entity use_count field to track the number of users.
533 * For entities corresponding to video device nodes the use_count field stores
534 * the users count of the node. For entities corresponding to subdevs the
535 * use_count field stores the total number of users of all video device nodes
536 * in the pipeline.
537 *
538 * The omap3isp_pipeline_pm_use() function must be called in the open() and
539 * close() handlers of video device nodes. It increments or decrements the use
540 * count of all subdev entities in the pipeline.
541 *
542 * To react to link management on powered pipelines, the link setup notification
543 * callback updates the use count of all entities in the source and sink sides
544 * of the link.
545 */
546
547/*
548 * isp_pipeline_pm_use_count - Count the number of users of a pipeline
549 * @entity: The entity
550 *
551 * Return the total number of users of all video device nodes in the pipeline.
552 */
553static int isp_pipeline_pm_use_count(struct media_entity *entity)
554{
555 struct media_entity_graph graph;
556 int use = 0;
557
558 media_entity_graph_walk_start(&graph, entity);
559
560 while ((entity = media_entity_graph_walk_next(&graph))) {
561 if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
562 use += entity->use_count;
563 }
564
565 return use;
566}
567
568/*
569 * isp_pipeline_pm_power_one - Apply power change to an entity
570 * @entity: The entity
571 * @change: Use count change
572 *
573 * Change the entity use count by @change. If the entity is a subdev update its
574 * power state by calling the core::s_power operation when the use count goes
575 * from 0 to != 0 or from != 0 to 0.
576 *
577 * Return 0 on success or a negative error code on failure.
578 */
579static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
580{
581 struct v4l2_subdev *subdev;
582 int ret;
583
584 subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
585 ? media_entity_to_v4l2_subdev(entity) : NULL;
586
587 if (entity->use_count == 0 && change > 0 && subdev != NULL) {
588 ret = v4l2_subdev_call(subdev, core, s_power, 1);
589 if (ret < 0 && ret != -ENOIOCTLCMD)
590 return ret;
591 }
592
593 entity->use_count += change;
594 WARN_ON(entity->use_count < 0);
595
596 if (entity->use_count == 0 && change < 0 && subdev != NULL)
597 v4l2_subdev_call(subdev, core, s_power, 0);
598
599 return 0;
600}
601
602/*
603 * isp_pipeline_pm_power - Apply power change to all entities in a pipeline
604 * @entity: The entity
605 * @change: Use count change
606 *
607 * Walk the pipeline to update the use count and the power state of all non-node
608 * entities.
609 *
610 * Return 0 on success or a negative error code on failure.
611 */
612static int isp_pipeline_pm_power(struct media_entity *entity, int change)
613{
614 struct media_entity_graph graph;
615 struct media_entity *first = entity;
616 int ret = 0;
617
618 if (!change)
619 return 0;
620
621 media_entity_graph_walk_start(&graph, entity);
622
623 while (!ret && (entity = media_entity_graph_walk_next(&graph)))
624 if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
625 ret = isp_pipeline_pm_power_one(entity, change);
626
627 if (!ret)
628 return 0;
629
630 media_entity_graph_walk_start(&graph, first);
631
632 while ((first = media_entity_graph_walk_next(&graph))
633 && first != entity)
634 if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
635 isp_pipeline_pm_power_one(first, -change);
636
637 return ret;
638}
639
640/*
641 * omap3isp_pipeline_pm_use - Update the use count of an entity
642 * @entity: The entity
643 * @use: Use (1) or stop using (0) the entity
644 *
645 * Update the use count of all entities in the pipeline and power entities on or
646 * off accordingly.
647 *
648 * Return 0 on success or a negative error code on failure. Powering entities
649 * off is assumed to never fail. No failure can occur when the use parameter is
650 * set to 0.
651 */
652int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
653{
654 int change = use ? 1 : -1;
655 int ret;
656
657 mutex_lock(&entity->parent->graph_mutex);
658
659 /* Apply use count to node. */
660 entity->use_count += change;
661 WARN_ON(entity->use_count < 0);
662
663 /* Apply power change to connected non-nodes. */
664 ret = isp_pipeline_pm_power(entity, change);
665 if (ret < 0)
666 entity->use_count -= change;
667
668 mutex_unlock(&entity->parent->graph_mutex);
669
670 return ret;
671}
672
673/*
674 * isp_pipeline_link_notify - Link management notification callback
675 * @source: Pad at the start of the link
676 * @sink: Pad at the end of the link
677 * @flags: New link flags that will be applied
678 *
679 * React to link management on powered pipelines by updating the use count of
680 * all entities in the source and sink sides of the link. Entities are powered
681 * on or off accordingly.
682 *
683 * Return 0 on success or a negative error code on failure. Powering entities
684 * off is assumed to never fail. This function will not fail for disconnection
685 * events.
686 */
687static int isp_pipeline_link_notify(struct media_pad *source,
688 struct media_pad *sink, u32 flags)
689{
690 int source_use = isp_pipeline_pm_use_count(source->entity);
691 int sink_use = isp_pipeline_pm_use_count(sink->entity);
692 int ret;
693
694 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
695 /* Powering off entities is assumed to never fail. */
696 isp_pipeline_pm_power(source->entity, -sink_use);
697 isp_pipeline_pm_power(sink->entity, -source_use);
698 return 0;
699 }
700
701 ret = isp_pipeline_pm_power(source->entity, sink_use);
702 if (ret < 0)
703 return ret;
704
705 ret = isp_pipeline_pm_power(sink->entity, source_use);
706 if (ret < 0)
707 isp_pipeline_pm_power(source->entity, -sink_use);
708
709 return ret;
710}
711
712/* -----------------------------------------------------------------------------
713 * Pipeline stream management
714 */
715
716/*
717 * isp_pipeline_enable - Enable streaming on a pipeline
718 * @pipe: ISP pipeline
719 * @mode: Stream mode (single shot or continuous)
720 *
721 * Walk the entities chain starting at the pipeline output video node and start
722 * all modules in the chain in the given mode.
723 *
724 * Return 0 if successful, or the return value of the failed video::s_stream
725 * operation otherwise.
726 */
727static int isp_pipeline_enable(struct isp_pipeline *pipe,
728 enum isp_pipeline_stream_state mode)
729{
730 struct isp_device *isp = pipe->output->isp;
731 struct media_entity *entity;
732 struct media_pad *pad;
733 struct v4l2_subdev *subdev;
734 unsigned long flags;
735 int ret = 0;
736
737 spin_lock_irqsave(&pipe->lock, flags);
738 pipe->state &= ~(ISP_PIPELINE_IDLE_INPUT | ISP_PIPELINE_IDLE_OUTPUT);
739 spin_unlock_irqrestore(&pipe->lock, flags);
740
741 pipe->do_propagation = false;
742
743 entity = &pipe->output->video.entity;
744 while (1) {
745 pad = &entity->pads[0];
746 if (!(pad->flags & MEDIA_PAD_FL_SINK))
747 break;
748
749 pad = media_entity_remote_source(pad);
750 if (pad == NULL ||
751 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
752 break;
753
754 entity = pad->entity;
755 subdev = media_entity_to_v4l2_subdev(entity);
756
757 ret = v4l2_subdev_call(subdev, video, s_stream, mode);
758 if (ret < 0 && ret != -ENOIOCTLCMD)
759 break;
760
761 if (subdev == &isp->isp_ccdc.subdev) {
762 v4l2_subdev_call(&isp->isp_aewb.subdev, video,
763 s_stream, mode);
764 v4l2_subdev_call(&isp->isp_af.subdev, video,
765 s_stream, mode);
766 v4l2_subdev_call(&isp->isp_hist.subdev, video,
767 s_stream, mode);
768 pipe->do_propagation = true;
769 }
770 }
771
772 /* Frame number propagation. In continuous streaming mode the number
773 * is incremented in the frame start ISR. In mem-to-mem mode
774 * singleshot is used and frame start IRQs are not available.
775 * Thus we have to increment the number here.
776 */
777 if (pipe->do_propagation && mode == ISP_PIPELINE_STREAM_SINGLESHOT)
778 atomic_inc(&pipe->frame_number);
779
780 return ret;
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 failure = -ETIMEDOUT;
878 }
879 }
880
881 if (failure < 0)
882 isp->needs_reset = true;
883
884 return failure;
885}
886
887/*
888 * omap3isp_pipeline_set_stream - Enable/disable streaming on a pipeline
889 * @pipe: ISP pipeline
890 * @state: Stream state (stopped, single shot or continuous)
891 *
892 * Set the pipeline to the given stream state. Pipelines can be started in
893 * single-shot or continuous mode.
894 *
895 * Return 0 if successful, or the return value of the failed video::s_stream
896 * operation otherwise. The pipeline state is not updated when the operation
897 * fails, except when stopping the pipeline.
898 */
899int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
900 enum isp_pipeline_stream_state state)
901{
902 int ret;
903
904 if (state == ISP_PIPELINE_STREAM_STOPPED)
905 ret = isp_pipeline_disable(pipe);
906 else
907 ret = isp_pipeline_enable(pipe, state);
908
909 if (ret == 0 || state == ISP_PIPELINE_STREAM_STOPPED)
910 pipe->stream_state = state;
911
912 return ret;
913}
914
915/*
916 * isp_pipeline_resume - Resume streaming on a pipeline
917 * @pipe: ISP pipeline
918 *
919 * Resume video output and input and re-enable pipeline.
920 */
921static void isp_pipeline_resume(struct isp_pipeline *pipe)
922{
923 int singleshot = pipe->stream_state == ISP_PIPELINE_STREAM_SINGLESHOT;
924
925 omap3isp_video_resume(pipe->output, !singleshot);
926 if (singleshot)
927 omap3isp_video_resume(pipe->input, 0);
928 isp_pipeline_enable(pipe, pipe->stream_state);
929}
930
931/*
932 * isp_pipeline_suspend - Suspend streaming on a pipeline
933 * @pipe: ISP pipeline
934 *
935 * Suspend pipeline.
936 */
937static void isp_pipeline_suspend(struct isp_pipeline *pipe)
938{
939 isp_pipeline_disable(pipe);
940}
941
942/*
943 * isp_pipeline_is_last - Verify if entity has an enabled link to the output
944 * video node
945 * @me: ISP module's media entity
946 *
947 * Returns 1 if the entity has an enabled link to the output video node or 0
948 * otherwise. It's true only while pipeline can have no more than one output
949 * node.
950 */
951static int isp_pipeline_is_last(struct media_entity *me)
952{
953 struct isp_pipeline *pipe;
954 struct media_pad *pad;
955
956 if (!me->pipe)
957 return 0;
958 pipe = to_isp_pipeline(me);
959 if (pipe->stream_state == ISP_PIPELINE_STREAM_STOPPED)
960 return 0;
961 pad = media_entity_remote_source(&pipe->output->pad);
962 return pad->entity == me;
963}
964
965/*
966 * isp_suspend_module_pipeline - Suspend pipeline to which belongs the module
967 * @me: ISP module's media entity
968 *
969 * Suspend the whole pipeline if module's entity has an enabled link to the
970 * output video node. It works only while pipeline can have no more than one
971 * output node.
972 */
973static void isp_suspend_module_pipeline(struct media_entity *me)
974{
975 if (isp_pipeline_is_last(me))
976 isp_pipeline_suspend(to_isp_pipeline(me));
977}
978
979/*
980 * isp_resume_module_pipeline - Resume pipeline to which belongs the module
981 * @me: ISP module's media entity
982 *
983 * Resume the whole pipeline if module's entity has an enabled link to the
984 * output video node. It works only while pipeline can have no more than one
985 * output node.
986 */
987static void isp_resume_module_pipeline(struct media_entity *me)
988{
989 if (isp_pipeline_is_last(me))
990 isp_pipeline_resume(to_isp_pipeline(me));
991}
992
993/*
994 * isp_suspend_modules - Suspend ISP submodules.
995 * @isp: OMAP3 ISP device
996 *
997 * Returns 0 if suspend left in idle state all the submodules properly,
998 * or returns 1 if a general Reset is required to suspend the submodules.
999 */
1000static int isp_suspend_modules(struct isp_device *isp)
1001{
1002 unsigned long timeout;
1003
1004 omap3isp_stat_suspend(&isp->isp_aewb);
1005 omap3isp_stat_suspend(&isp->isp_af);
1006 omap3isp_stat_suspend(&isp->isp_hist);
1007 isp_suspend_module_pipeline(&isp->isp_res.subdev.entity);
1008 isp_suspend_module_pipeline(&isp->isp_prev.subdev.entity);
1009 isp_suspend_module_pipeline(&isp->isp_ccdc.subdev.entity);
1010 isp_suspend_module_pipeline(&isp->isp_csi2a.subdev.entity);
1011 isp_suspend_module_pipeline(&isp->isp_ccp2.subdev.entity);
1012
1013 timeout = jiffies + ISP_STOP_TIMEOUT;
1014 while (omap3isp_stat_busy(&isp->isp_af)
1015 || omap3isp_stat_busy(&isp->isp_aewb)
1016 || omap3isp_stat_busy(&isp->isp_hist)
1017 || omap3isp_preview_busy(&isp->isp_prev)
1018 || omap3isp_resizer_busy(&isp->isp_res)
1019 || omap3isp_ccdc_busy(&isp->isp_ccdc)) {
1020 if (time_after(jiffies, timeout)) {
1021 dev_info(isp->dev, "can't stop modules.\n");
1022 return 1;
1023 }
1024 msleep(1);
1025 }
1026
1027 return 0;
1028}
1029
1030/*
1031 * isp_resume_modules - Resume ISP submodules.
1032 * @isp: OMAP3 ISP device
1033 */
1034static void isp_resume_modules(struct isp_device *isp)
1035{
1036 omap3isp_stat_resume(&isp->isp_aewb);
1037 omap3isp_stat_resume(&isp->isp_af);
1038 omap3isp_stat_resume(&isp->isp_hist);
1039 isp_resume_module_pipeline(&isp->isp_res.subdev.entity);
1040 isp_resume_module_pipeline(&isp->isp_prev.subdev.entity);
1041 isp_resume_module_pipeline(&isp->isp_ccdc.subdev.entity);
1042 isp_resume_module_pipeline(&isp->isp_csi2a.subdev.entity);
1043 isp_resume_module_pipeline(&isp->isp_ccp2.subdev.entity);
1044}
1045
1046/*
1047 * isp_reset - Reset ISP with a timeout wait for idle.
1048 * @isp: OMAP3 ISP device
1049 */
1050static int isp_reset(struct isp_device *isp)
1051{
1052 unsigned long timeout = 0;
1053
1054 isp_reg_writel(isp,
1055 isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG)
1056 | ISP_SYSCONFIG_SOFTRESET,
1057 OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
1058 while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN,
1059 ISP_SYSSTATUS) & 0x1)) {
1060 if (timeout++ > 10000) {
1061 dev_alert(isp->dev, "cannot reset ISP\n");
1062 return -ETIMEDOUT;
1063 }
1064 udelay(1);
1065 }
1066
1067 return 0;
1068}
1069
1070/*
1071 * isp_save_context - Saves the values of the ISP module registers.
1072 * @isp: OMAP3 ISP device
1073 * @reg_list: Structure containing pairs of register address and value to
1074 * modify on OMAP.
1075 */
1076static void
1077isp_save_context(struct isp_device *isp, struct isp_reg *reg_list)
1078{
1079 struct isp_reg *next = reg_list;
1080
1081 for (; next->reg != ISP_TOK_TERM; next++)
1082 next->val = isp_reg_readl(isp, next->mmio_range, next->reg);
1083}
1084
1085/*
1086 * isp_restore_context - Restores the values of the ISP module registers.
1087 * @isp: OMAP3 ISP device
1088 * @reg_list: Structure containing pairs of register address and value to
1089 * modify on OMAP.
1090 */
1091static void
1092isp_restore_context(struct isp_device *isp, struct isp_reg *reg_list)
1093{
1094 struct isp_reg *next = reg_list;
1095
1096 for (; next->reg != ISP_TOK_TERM; next++)
1097 isp_reg_writel(isp, next->val, next->mmio_range, next->reg);
1098}
1099
1100/*
1101 * isp_save_ctx - Saves ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
1102 * @isp: OMAP3 ISP device
1103 *
1104 * Routine for saving the context of each module in the ISP.
1105 * CCDC, HIST, H3A, PREV, RESZ and MMU.
1106 */
1107static void isp_save_ctx(struct isp_device *isp)
1108{
1109 isp_save_context(isp, isp_reg_list);
1110 omap_iommu_save_ctx(isp->dev);
1111}
1112
1113/*
1114 * isp_restore_ctx - Restores ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
1115 * @isp: OMAP3 ISP device
1116 *
1117 * Routine for restoring the context of each module in the ISP.
1118 * CCDC, HIST, H3A, PREV, RESZ and MMU.
1119 */
1120static void isp_restore_ctx(struct isp_device *isp)
1121{
1122 isp_restore_context(isp, isp_reg_list);
1123 omap_iommu_restore_ctx(isp->dev);
1124 omap3isp_ccdc_restore_context(isp);
1125 omap3isp_preview_restore_context(isp);
1126}
1127
1128/* -----------------------------------------------------------------------------
1129 * SBL resources management
1130 */
1131#define OMAP3_ISP_SBL_READ (OMAP3_ISP_SBL_CSI1_READ | \
1132 OMAP3_ISP_SBL_CCDC_LSC_READ | \
1133 OMAP3_ISP_SBL_PREVIEW_READ | \
1134 OMAP3_ISP_SBL_RESIZER_READ)
1135#define OMAP3_ISP_SBL_WRITE (OMAP3_ISP_SBL_CSI1_WRITE | \
1136 OMAP3_ISP_SBL_CSI2A_WRITE | \
1137 OMAP3_ISP_SBL_CSI2C_WRITE | \
1138 OMAP3_ISP_SBL_CCDC_WRITE | \
1139 OMAP3_ISP_SBL_PREVIEW_WRITE)
1140
1141void omap3isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res)
1142{
1143 u32 sbl = 0;
1144
1145 isp->sbl_resources |= res;
1146
1147 if (isp->sbl_resources & OMAP3_ISP_SBL_CSI1_READ)
1148 sbl |= ISPCTRL_SBL_SHARED_RPORTA;
1149
1150 if (isp->sbl_resources & OMAP3_ISP_SBL_CCDC_LSC_READ)
1151 sbl |= ISPCTRL_SBL_SHARED_RPORTB;
1152
1153 if (isp->sbl_resources & OMAP3_ISP_SBL_CSI2C_WRITE)
1154 sbl |= ISPCTRL_SBL_SHARED_WPORTC;
1155
1156 if (isp->sbl_resources & OMAP3_ISP_SBL_RESIZER_WRITE)
1157 sbl |= ISPCTRL_SBL_WR0_RAM_EN;
1158
1159 if (isp->sbl_resources & OMAP3_ISP_SBL_WRITE)
1160 sbl |= ISPCTRL_SBL_WR1_RAM_EN;
1161
1162 if (isp->sbl_resources & OMAP3_ISP_SBL_READ)
1163 sbl |= ISPCTRL_SBL_RD_RAM_EN;
1164
1165 isp_reg_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, sbl);
1166}
1167
1168void omap3isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res)
1169{
1170 u32 sbl = 0;
1171
1172 isp->sbl_resources &= ~res;
1173
1174 if (!(isp->sbl_resources & OMAP3_ISP_SBL_CSI1_READ))
1175 sbl |= ISPCTRL_SBL_SHARED_RPORTA;
1176
1177 if (!(isp->sbl_resources & OMAP3_ISP_SBL_CCDC_LSC_READ))
1178 sbl |= ISPCTRL_SBL_SHARED_RPORTB;
1179
1180 if (!(isp->sbl_resources & OMAP3_ISP_SBL_CSI2C_WRITE))
1181 sbl |= ISPCTRL_SBL_SHARED_WPORTC;
1182
1183 if (!(isp->sbl_resources & OMAP3_ISP_SBL_RESIZER_WRITE))
1184 sbl |= ISPCTRL_SBL_WR0_RAM_EN;
1185
1186 if (!(isp->sbl_resources & OMAP3_ISP_SBL_WRITE))
1187 sbl |= ISPCTRL_SBL_WR1_RAM_EN;
1188
1189 if (!(isp->sbl_resources & OMAP3_ISP_SBL_READ))
1190 sbl |= ISPCTRL_SBL_RD_RAM_EN;
1191
1192 isp_reg_clr(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, sbl);
1193}
1194
1195/*
1196 * isp_module_sync_idle - Helper to sync module with its idle state
1197 * @me: ISP submodule's media entity
1198 * @wait: ISP submodule's wait queue for streamoff/interrupt synchronization
1199 * @stopping: flag which tells module wants to stop
1200 *
1201 * This function checks if ISP submodule needs to wait for next interrupt. If
1202 * yes, makes the caller to sleep while waiting for such event.
1203 */
1204int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
1205 atomic_t *stopping)
1206{
1207 struct isp_pipeline *pipe = to_isp_pipeline(me);
1208
1209 if (pipe->stream_state == ISP_PIPELINE_STREAM_STOPPED ||
1210 (pipe->stream_state == ISP_PIPELINE_STREAM_SINGLESHOT &&
1211 !isp_pipeline_ready(pipe)))
1212 return 0;
1213
1214 /*
1215 * atomic_set() doesn't include memory barrier on ARM platform for SMP
1216 * scenario. We'll call it here to avoid race conditions.
1217 */
1218 atomic_set(stopping, 1);
1219 smp_mb();
1220
1221 /*
1222 * If module is the last one, it's writing to memory. In this case,
1223 * it's necessary to check if the module is already paused due to
1224 * DMA queue underrun or if it has to wait for next interrupt to be
1225 * idle.
1226 * If it isn't the last one, the function won't sleep but *stopping
1227 * will still be set to warn next submodule caller's interrupt the
1228 * module wants to be idle.
1229 */
1230 if (isp_pipeline_is_last(me)) {
1231 struct isp_video *video = pipe->output;
1232 unsigned long flags;
1233 spin_lock_irqsave(&video->queue->irqlock, flags);
1234 if (video->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
1235 spin_unlock_irqrestore(&video->queue->irqlock, flags);
1236 atomic_set(stopping, 0);
1237 smp_mb();
1238 return 0;
1239 }
1240 spin_unlock_irqrestore(&video->queue->irqlock, flags);
1241 if (!wait_event_timeout(*wait, !atomic_read(stopping),
1242 msecs_to_jiffies(1000))) {
1243 atomic_set(stopping, 0);
1244 smp_mb();
1245 return -ETIMEDOUT;
1246 }
1247 }
1248
1249 return 0;
1250}
1251
1252/*
1253 * omap3isp_module_sync_is_stopped - Helper to verify if module was stopping
1254 * @wait: ISP submodule's wait queue for streamoff/interrupt synchronization
1255 * @stopping: flag which tells module wants to stop
1256 *
1257 * This function checks if ISP submodule was stopping. In case of yes, it
1258 * notices the caller by setting stopping to 0 and waking up the wait queue.
1259 * Returns 1 if it was stopping or 0 otherwise.
1260 */
1261int omap3isp_module_sync_is_stopping(wait_queue_head_t *wait,
1262 atomic_t *stopping)
1263{
1264 if (atomic_cmpxchg(stopping, 1, 0)) {
1265 wake_up(wait);
1266 return 1;
1267 }
1268
1269 return 0;
1270}
1271
1272/* --------------------------------------------------------------------------
1273 * Clock management
1274 */
1275
1276#define ISPCTRL_CLKS_MASK (ISPCTRL_H3A_CLK_EN | \
1277 ISPCTRL_HIST_CLK_EN | \
1278 ISPCTRL_RSZ_CLK_EN | \
1279 (ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN) | \
1280 (ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN))
1281
1282static void __isp_subclk_update(struct isp_device *isp)
1283{
1284 u32 clk = 0;
1285
1286 if (isp->subclk_resources & OMAP3_ISP_SUBCLK_H3A)
1287 clk |= ISPCTRL_H3A_CLK_EN;
1288
1289 if (isp->subclk_resources & OMAP3_ISP_SUBCLK_HIST)
1290 clk |= ISPCTRL_HIST_CLK_EN;
1291
1292 if (isp->subclk_resources & OMAP3_ISP_SUBCLK_RESIZER)
1293 clk |= ISPCTRL_RSZ_CLK_EN;
1294
1295 /* NOTE: For CCDC & Preview submodules, we need to affect internal
1296 * RAM as well.
1297 */
1298 if (isp->subclk_resources & OMAP3_ISP_SUBCLK_CCDC)
1299 clk |= ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN;
1300
1301 if (isp->subclk_resources & OMAP3_ISP_SUBCLK_PREVIEW)
1302 clk |= ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN;
1303
1304 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
1305 ISPCTRL_CLKS_MASK, clk);
1306}
1307
1308void omap3isp_subclk_enable(struct isp_device *isp,
1309 enum isp_subclk_resource res)
1310{
1311 isp->subclk_resources |= res;
1312
1313 __isp_subclk_update(isp);
1314}
1315
1316void omap3isp_subclk_disable(struct isp_device *isp,
1317 enum isp_subclk_resource res)
1318{
1319 isp->subclk_resources &= ~res;
1320
1321 __isp_subclk_update(isp);
1322}
1323
1324/*
1325 * isp_enable_clocks - Enable ISP clocks
1326 * @isp: OMAP3 ISP device
1327 *
1328 * Return 0 if successful, or clk_enable return value if any of tthem fails.
1329 */
1330static int isp_enable_clocks(struct isp_device *isp)
1331{
1332 int r;
1333 unsigned long rate;
1334 int divisor;
1335
1336 /*
1337 * cam_mclk clock chain:
1338 * dpll4 -> dpll4_m5 -> dpll4_m5x2 -> cam_mclk
1339 *
1340 * In OMAP3630 dpll4_m5x2 != 2 x dpll4_m5 but both are
1341 * set to the same value. Hence the rate set for dpll4_m5
1342 * has to be twice of what is set on OMAP3430 to get
1343 * the required value for cam_mclk
1344 */
1345 if (cpu_is_omap3630())
1346 divisor = 1;
1347 else
1348 divisor = 2;
1349
1350 r = clk_enable(isp->clock[ISP_CLK_CAM_ICK]);
1351 if (r) {
1352 dev_err(isp->dev, "clk_enable cam_ick failed\n");
1353 goto out_clk_enable_ick;
1354 }
1355 r = clk_set_rate(isp->clock[ISP_CLK_DPLL4_M5_CK],
1356 CM_CAM_MCLK_HZ/divisor);
1357 if (r) {
1358 dev_err(isp->dev, "clk_set_rate for dpll4_m5_ck failed\n");
1359 goto out_clk_enable_mclk;
1360 }
1361 r = clk_enable(isp->clock[ISP_CLK_CAM_MCLK]);
1362 if (r) {
1363 dev_err(isp->dev, "clk_enable cam_mclk failed\n");
1364 goto out_clk_enable_mclk;
1365 }
1366 rate = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
1367 if (rate != CM_CAM_MCLK_HZ)
1368 dev_warn(isp->dev, "unexpected cam_mclk rate:\n"
1369 " expected : %d\n"
1370 " actual : %ld\n", CM_CAM_MCLK_HZ, rate);
1371 r = clk_enable(isp->clock[ISP_CLK_CSI2_FCK]);
1372 if (r) {
1373 dev_err(isp->dev, "clk_enable csi2_fck failed\n");
1374 goto out_clk_enable_csi2_fclk;
1375 }
1376 return 0;
1377
1378out_clk_enable_csi2_fclk:
1379 clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
1380out_clk_enable_mclk:
1381 clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
1382out_clk_enable_ick:
1383 return r;
1384}
1385
1386/*
1387 * isp_disable_clocks - Disable ISP clocks
1388 * @isp: OMAP3 ISP device
1389 */
1390static void isp_disable_clocks(struct isp_device *isp)
1391{
1392 clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
1393 clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
1394 clk_disable(isp->clock[ISP_CLK_CSI2_FCK]);
1395}
1396
1397static const char *isp_clocks[] = {
1398 "cam_ick",
1399 "cam_mclk",
1400 "dpll4_m5_ck",
1401 "csi2_96m_fck",
1402 "l3_ick",
1403};
1404
1405static void isp_put_clocks(struct isp_device *isp)
1406{
1407 unsigned int i;
1408
1409 for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
1410 if (isp->clock[i]) {
1411 clk_put(isp->clock[i]);
1412 isp->clock[i] = NULL;
1413 }
1414 }
1415}
1416
1417static int isp_get_clocks(struct isp_device *isp)
1418{
1419 struct clk *clk;
1420 unsigned int i;
1421
1422 for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
1423 clk = clk_get(isp->dev, isp_clocks[i]);
1424 if (IS_ERR(clk)) {
1425 dev_err(isp->dev, "clk_get %s failed\n", isp_clocks[i]);
1426 isp_put_clocks(isp);
1427 return PTR_ERR(clk);
1428 }
1429
1430 isp->clock[i] = clk;
1431 }
1432
1433 return 0;
1434}
1435
1436/*
1437 * omap3isp_get - Acquire the ISP resource.
1438 *
1439 * Initializes the clocks for the first acquire.
1440 *
1441 * Increment the reference count on the ISP. If the first reference is taken,
1442 * enable clocks and power-up all submodules.
1443 *
1444 * Return a pointer to the ISP device structure, or NULL if an error occurred.
1445 */
1446struct isp_device *omap3isp_get(struct isp_device *isp)
1447{
1448 struct isp_device *__isp = isp;
1449
1450 if (isp == NULL)
1451 return NULL;
1452
1453 mutex_lock(&isp->isp_mutex);
1454 if (isp->ref_count > 0)
1455 goto out;
1456
1457 if (isp_enable_clocks(isp) < 0) {
1458 __isp = NULL;
1459 goto out;
1460 }
1461
1462 /* We don't want to restore context before saving it! */
1463 if (isp->has_context)
1464 isp_restore_ctx(isp);
1465 else
1466 isp->has_context = 1;
1467
1468 isp_enable_interrupts(isp);
1469
1470out:
1471 if (__isp != NULL)
1472 isp->ref_count++;
1473 mutex_unlock(&isp->isp_mutex);
1474
1475 return __isp;
1476}
1477
1478/*
1479 * omap3isp_put - Release the ISP
1480 *
1481 * Decrement the reference count on the ISP. If the last reference is released,
1482 * power-down all submodules, disable clocks and free temporary buffers.
1483 */
1484void omap3isp_put(struct isp_device *isp)
1485{
1486 if (isp == NULL)
1487 return;
1488
1489 mutex_lock(&isp->isp_mutex);
1490 BUG_ON(isp->ref_count == 0);
1491 if (--isp->ref_count == 0) {
1492 isp_disable_interrupts(isp);
1493 isp_save_ctx(isp);
1494 if (isp->needs_reset) {
1495 isp_reset(isp);
1496 isp->needs_reset = false;
1497 }
1498 isp_disable_clocks(isp);
1499 }
1500 mutex_unlock(&isp->isp_mutex);
1501}
1502
1503/* --------------------------------------------------------------------------
1504 * Platform device driver
1505 */
1506
1507/*
1508 * omap3isp_print_status - Prints the values of the ISP Control Module registers
1509 * @isp: OMAP3 ISP device
1510 */
1511#define ISP_PRINT_REGISTER(isp, name)\
1512 dev_dbg(isp->dev, "###ISP " #name "=0x%08x\n", \
1513 isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_##name))
1514#define SBL_PRINT_REGISTER(isp, name)\
1515 dev_dbg(isp->dev, "###SBL " #name "=0x%08x\n", \
1516 isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_##name))
1517
1518void omap3isp_print_status(struct isp_device *isp)
1519{
1520 dev_dbg(isp->dev, "-------------ISP Register dump--------------\n");
1521
1522 ISP_PRINT_REGISTER(isp, SYSCONFIG);
1523 ISP_PRINT_REGISTER(isp, SYSSTATUS);
1524 ISP_PRINT_REGISTER(isp, IRQ0ENABLE);
1525 ISP_PRINT_REGISTER(isp, IRQ0STATUS);
1526 ISP_PRINT_REGISTER(isp, TCTRL_GRESET_LENGTH);
1527 ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_REPLAY);
1528 ISP_PRINT_REGISTER(isp, CTRL);
1529 ISP_PRINT_REGISTER(isp, TCTRL_CTRL);
1530 ISP_PRINT_REGISTER(isp, TCTRL_FRAME);
1531 ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_DELAY);
1532 ISP_PRINT_REGISTER(isp, TCTRL_STRB_DELAY);
1533 ISP_PRINT_REGISTER(isp, TCTRL_SHUT_DELAY);
1534 ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_LENGTH);
1535 ISP_PRINT_REGISTER(isp, TCTRL_STRB_LENGTH);
1536 ISP_PRINT_REGISTER(isp, TCTRL_SHUT_LENGTH);
1537
1538 SBL_PRINT_REGISTER(isp, PCR);
1539 SBL_PRINT_REGISTER(isp, SDR_REQ_EXP);
1540
1541 dev_dbg(isp->dev, "--------------------------------------------\n");
1542}
1543
1544#ifdef CONFIG_PM
1545
1546/*
1547 * Power management support.
1548 *
1549 * As the ISP can't properly handle an input video stream interruption on a non
1550 * frame boundary, the ISP pipelines need to be stopped before sensors get
1551 * suspended. However, as suspending the sensors can require a running clock,
1552 * which can be provided by the ISP, the ISP can't be completely suspended
1553 * before the sensor.
1554 *
1555 * To solve this problem power management support is split into prepare/complete
1556 * and suspend/resume operations. The pipelines are stopped in prepare() and the
1557 * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in
1558 * resume(), and the the pipelines are restarted in complete().
1559 *
1560 * TODO: PM dependencies between the ISP and sensors are not modeled explicitly
1561 * yet.
1562 */
1563static int isp_pm_prepare(struct device *dev)
1564{
1565 struct isp_device *isp = dev_get_drvdata(dev);
1566 int reset;
1567
1568 WARN_ON(mutex_is_locked(&isp->isp_mutex));
1569
1570 if (isp->ref_count == 0)
1571 return 0;
1572
1573 reset = isp_suspend_modules(isp);
1574 isp_disable_interrupts(isp);
1575 isp_save_ctx(isp);
1576 if (reset)
1577 isp_reset(isp);
1578
1579 return 0;
1580}
1581
1582static int isp_pm_suspend(struct device *dev)
1583{
1584 struct isp_device *isp = dev_get_drvdata(dev);
1585
1586 WARN_ON(mutex_is_locked(&isp->isp_mutex));
1587
1588 if (isp->ref_count)
1589 isp_disable_clocks(isp);
1590
1591 return 0;
1592}
1593
1594static int isp_pm_resume(struct device *dev)
1595{
1596 struct isp_device *isp = dev_get_drvdata(dev);
1597
1598 if (isp->ref_count == 0)
1599 return 0;
1600
1601 return isp_enable_clocks(isp);
1602}
1603
1604static void isp_pm_complete(struct device *dev)
1605{
1606 struct isp_device *isp = dev_get_drvdata(dev);
1607
1608 if (isp->ref_count == 0)
1609 return;
1610
1611 isp_restore_ctx(isp);
1612 isp_enable_interrupts(isp);
1613 isp_resume_modules(isp);
1614}
1615
1616#else
1617
1618#define isp_pm_prepare NULL
1619#define isp_pm_suspend NULL
1620#define isp_pm_resume NULL
1621#define isp_pm_complete NULL
1622
1623#endif /* CONFIG_PM */
1624
1625static void isp_unregister_entities(struct isp_device *isp)
1626{
1627 omap3isp_csi2_unregister_entities(&isp->isp_csi2a);
1628 omap3isp_ccp2_unregister_entities(&isp->isp_ccp2);
1629 omap3isp_ccdc_unregister_entities(&isp->isp_ccdc);
1630 omap3isp_preview_unregister_entities(&isp->isp_prev);
1631 omap3isp_resizer_unregister_entities(&isp->isp_res);
1632 omap3isp_stat_unregister_entities(&isp->isp_aewb);
1633 omap3isp_stat_unregister_entities(&isp->isp_af);
1634 omap3isp_stat_unregister_entities(&isp->isp_hist);
1635
1636 v4l2_device_unregister(&isp->v4l2_dev);
1637 media_device_unregister(&isp->media_dev);
1638}
1639
1640/*
1641 * isp_register_subdev_group - Register a group of subdevices
1642 * @isp: OMAP3 ISP device
1643 * @board_info: I2C subdevs board information array
1644 *
1645 * Register all I2C subdevices in the board_info array. The array must be
1646 * terminated by a NULL entry, and the first entry must be the sensor.
1647 *
1648 * Return a pointer to the sensor media entity if it has been successfully
1649 * registered, or NULL otherwise.
1650 */
1651static struct v4l2_subdev *
1652isp_register_subdev_group(struct isp_device *isp,
1653 struct isp_subdev_i2c_board_info *board_info)
1654{
1655 struct v4l2_subdev *sensor = NULL;
1656 unsigned int first;
1657
1658 if (board_info->board_info == NULL)
1659 return NULL;
1660
1661 for (first = 1; board_info->board_info; ++board_info, first = 0) {
1662 struct v4l2_subdev *subdev;
1663 struct i2c_adapter *adapter;
1664
1665 adapter = i2c_get_adapter(board_info->i2c_adapter_id);
1666 if (adapter == NULL) {
1667 printk(KERN_ERR "%s: Unable to get I2C adapter %d for "
1668 "device %s\n", __func__,
1669 board_info->i2c_adapter_id,
1670 board_info->board_info->type);
1671 continue;
1672 }
1673
1674 subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
1675 board_info->board_info, NULL);
1676 if (subdev == NULL) {
1677 printk(KERN_ERR "%s: Unable to register subdev %s\n",
1678 __func__, board_info->board_info->type);
1679 continue;
1680 }
1681
1682 if (first)
1683 sensor = subdev;
1684 }
1685
1686 return sensor;
1687}
1688
1689static int isp_register_entities(struct isp_device *isp)
1690{
1691 struct isp_platform_data *pdata = isp->pdata;
1692 struct isp_v4l2_subdevs_group *subdevs;
1693 int ret;
1694
1695 isp->media_dev.dev = isp->dev;
1696 strlcpy(isp->media_dev.model, "TI OMAP3 ISP",
1697 sizeof(isp->media_dev.model));
1698 isp->media_dev.link_notify = isp_pipeline_link_notify;
1699 ret = media_device_register(&isp->media_dev);
1700 if (ret < 0) {
1701 printk(KERN_ERR "%s: Media device registration failed (%d)\n",
1702 __func__, ret);
1703 return ret;
1704 }
1705
1706 isp->v4l2_dev.mdev = &isp->media_dev;
1707 ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
1708 if (ret < 0) {
1709 printk(KERN_ERR "%s: V4L2 device registration failed (%d)\n",
1710 __func__, ret);
1711 goto done;
1712 }
1713
1714 /* Register internal entities */
1715 ret = omap3isp_ccp2_register_entities(&isp->isp_ccp2, &isp->v4l2_dev);
1716 if (ret < 0)
1717 goto done;
1718
1719 ret = omap3isp_csi2_register_entities(&isp->isp_csi2a, &isp->v4l2_dev);
1720 if (ret < 0)
1721 goto done;
1722
1723 ret = omap3isp_ccdc_register_entities(&isp->isp_ccdc, &isp->v4l2_dev);
1724 if (ret < 0)
1725 goto done;
1726
1727 ret = omap3isp_preview_register_entities(&isp->isp_prev,
1728 &isp->v4l2_dev);
1729 if (ret < 0)
1730 goto done;
1731
1732 ret = omap3isp_resizer_register_entities(&isp->isp_res, &isp->v4l2_dev);
1733 if (ret < 0)
1734 goto done;
1735
1736 ret = omap3isp_stat_register_entities(&isp->isp_aewb, &isp->v4l2_dev);
1737 if (ret < 0)
1738 goto done;
1739
1740 ret = omap3isp_stat_register_entities(&isp->isp_af, &isp->v4l2_dev);
1741 if (ret < 0)
1742 goto done;
1743
1744 ret = omap3isp_stat_register_entities(&isp->isp_hist, &isp->v4l2_dev);
1745 if (ret < 0)
1746 goto done;
1747
1748 /* Register external entities */
1749 for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) {
1750 struct v4l2_subdev *sensor;
1751 struct media_entity *input;
1752 unsigned int flags;
1753 unsigned int pad;
1754
1755 sensor = isp_register_subdev_group(isp, subdevs->subdevs);
1756 if (sensor == NULL)
1757 continue;
1758
1759 sensor->host_priv = subdevs;
1760
1761 /* Connect the sensor to the correct interface module. Parallel
1762 * sensors are connected directly to the CCDC, while serial
1763 * sensors are connected to the CSI2a, CCP2b or CSI2c receiver
1764 * through CSIPHY1 or CSIPHY2.
1765 */
1766 switch (subdevs->interface) {
1767 case ISP_INTERFACE_PARALLEL:
1768 input = &isp->isp_ccdc.subdev.entity;
1769 pad = CCDC_PAD_SINK;
1770 flags = 0;
1771 break;
1772
1773 case ISP_INTERFACE_CSI2A_PHY2:
1774 input = &isp->isp_csi2a.subdev.entity;
1775 pad = CSI2_PAD_SINK;
1776 flags = MEDIA_LNK_FL_IMMUTABLE
1777 | MEDIA_LNK_FL_ENABLED;
1778 break;
1779
1780 case ISP_INTERFACE_CCP2B_PHY1:
1781 case ISP_INTERFACE_CCP2B_PHY2:
1782 input = &isp->isp_ccp2.subdev.entity;
1783 pad = CCP2_PAD_SINK;
1784 flags = 0;
1785 break;
1786
1787 case ISP_INTERFACE_CSI2C_PHY1:
1788 input = &isp->isp_csi2c.subdev.entity;
1789 pad = CSI2_PAD_SINK;
1790 flags = MEDIA_LNK_FL_IMMUTABLE
1791 | MEDIA_LNK_FL_ENABLED;
1792 break;
1793
1794 default:
1795 printk(KERN_ERR "%s: invalid interface type %u\n",
1796 __func__, subdevs->interface);
1797 ret = -EINVAL;
1798 goto done;
1799 }
1800
1801 ret = media_entity_create_link(&sensor->entity, 0, input, pad,
1802 flags);
1803 if (ret < 0)
1804 goto done;
1805 }
1806
1807 ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
1808
1809done:
1810 if (ret < 0)
1811 isp_unregister_entities(isp);
1812
1813 return ret;
1814}
1815
1816static void isp_cleanup_modules(struct isp_device *isp)
1817{
1818 omap3isp_h3a_aewb_cleanup(isp);
1819 omap3isp_h3a_af_cleanup(isp);
1820 omap3isp_hist_cleanup(isp);
1821 omap3isp_resizer_cleanup(isp);
1822 omap3isp_preview_cleanup(isp);
1823 omap3isp_ccdc_cleanup(isp);
1824 omap3isp_ccp2_cleanup(isp);
1825 omap3isp_csi2_cleanup(isp);
1826}
1827
1828static int isp_initialize_modules(struct isp_device *isp)
1829{
1830 int ret;
1831
1832 ret = omap3isp_csiphy_init(isp);
1833 if (ret < 0) {
1834 dev_err(isp->dev, "CSI PHY initialization failed\n");
1835 goto error_csiphy;
1836 }
1837
1838 ret = omap3isp_csi2_init(isp);
1839 if (ret < 0) {
1840 dev_err(isp->dev, "CSI2 initialization failed\n");
1841 goto error_csi2;
1842 }
1843
1844 ret = omap3isp_ccp2_init(isp);
1845 if (ret < 0) {
1846 dev_err(isp->dev, "CCP2 initialization failed\n");
1847 goto error_ccp2;
1848 }
1849
1850 ret = omap3isp_ccdc_init(isp);
1851 if (ret < 0) {
1852 dev_err(isp->dev, "CCDC initialization failed\n");
1853 goto error_ccdc;
1854 }
1855
1856 ret = omap3isp_preview_init(isp);
1857 if (ret < 0) {
1858 dev_err(isp->dev, "Preview initialization failed\n");
1859 goto error_preview;
1860 }
1861
1862 ret = omap3isp_resizer_init(isp);
1863 if (ret < 0) {
1864 dev_err(isp->dev, "Resizer initialization failed\n");
1865 goto error_resizer;
1866 }
1867
1868 ret = omap3isp_hist_init(isp);
1869 if (ret < 0) {
1870 dev_err(isp->dev, "Histogram initialization failed\n");
1871 goto error_hist;
1872 }
1873
1874 ret = omap3isp_h3a_aewb_init(isp);
1875 if (ret < 0) {
1876 dev_err(isp->dev, "H3A AEWB initialization failed\n");
1877 goto error_h3a_aewb;
1878 }
1879
1880 ret = omap3isp_h3a_af_init(isp);
1881 if (ret < 0) {
1882 dev_err(isp->dev, "H3A AF initialization failed\n");
1883 goto error_h3a_af;
1884 }
1885
1886 /* Connect the submodules. */
1887 ret = media_entity_create_link(
1888 &isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
1889 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
1890 if (ret < 0)
1891 goto error_link;
1892
1893 ret = media_entity_create_link(
1894 &isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
1895 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
1896 if (ret < 0)
1897 goto error_link;
1898
1899 ret = media_entity_create_link(
1900 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
1901 &isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
1902 if (ret < 0)
1903 goto error_link;
1904
1905 ret = media_entity_create_link(
1906 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
1907 &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
1908 if (ret < 0)
1909 goto error_link;
1910
1911 ret = media_entity_create_link(
1912 &isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
1913 &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
1914 if (ret < 0)
1915 goto error_link;
1916
1917 ret = media_entity_create_link(
1918 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
1919 &isp->isp_aewb.subdev.entity, 0,
1920 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
1921 if (ret < 0)
1922 goto error_link;
1923
1924 ret = media_entity_create_link(
1925 &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
1926 &isp->isp_af.subdev.entity, 0,
1927 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
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_hist.subdev.entity, 0,
1934 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
1935 if (ret < 0)
1936 goto error_link;
1937
1938 return 0;
1939
1940error_link:
1941 omap3isp_h3a_af_cleanup(isp);
1942error_h3a_af:
1943 omap3isp_h3a_aewb_cleanup(isp);
1944error_h3a_aewb:
1945 omap3isp_hist_cleanup(isp);
1946error_hist:
1947 omap3isp_resizer_cleanup(isp);
1948error_resizer:
1949 omap3isp_preview_cleanup(isp);
1950error_preview:
1951 omap3isp_ccdc_cleanup(isp);
1952error_ccdc:
1953 omap3isp_ccp2_cleanup(isp);
1954error_ccp2:
1955 omap3isp_csi2_cleanup(isp);
1956error_csi2:
1957error_csiphy:
1958 return ret;
1959}
1960
1961/*
1962 * isp_remove - Remove ISP platform device
1963 * @pdev: Pointer to ISP platform device
1964 *
1965 * Always returns 0.
1966 */
1967static int isp_remove(struct platform_device *pdev)
1968{
1969 struct isp_device *isp = platform_get_drvdata(pdev);
1970 int i;
1971
1972 isp_unregister_entities(isp);
1973 isp_cleanup_modules(isp);
1974
1975 omap3isp_get(isp);
1976 iommu_detach_device(isp->domain, &pdev->dev);
1977 iommu_domain_free(isp->domain);
1978 omap3isp_put(isp);
1979
1980 free_irq(isp->irq_num, isp);
1981 isp_put_clocks(isp);
1982
1983 for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) {
1984 if (isp->mmio_base[i]) {
1985 iounmap(isp->mmio_base[i]);
1986 isp->mmio_base[i] = NULL;
1987 }
1988
1989 if (isp->mmio_base_phys[i]) {
1990 release_mem_region(isp->mmio_base_phys[i],
1991 isp->mmio_size[i]);
1992 isp->mmio_base_phys[i] = 0;
1993 }
1994 }
1995
1996 regulator_put(isp->isp_csiphy1.vdd);
1997 regulator_put(isp->isp_csiphy2.vdd);
1998 kfree(isp);
1999
2000 return 0;
2001}
2002
2003static int isp_map_mem_resource(struct platform_device *pdev,
2004 struct isp_device *isp,
2005 enum isp_mem_resources res)
2006{
2007 struct resource *mem;
2008
2009 /* request the mem region for the camera registers */
2010
2011 mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
2012 if (!mem) {
2013 dev_err(isp->dev, "no mem resource?\n");
2014 return -ENODEV;
2015 }
2016
2017 if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
2018 dev_err(isp->dev,
2019 "cannot reserve camera register I/O region\n");
2020 return -ENODEV;
2021 }
2022 isp->mmio_base_phys[res] = mem->start;
2023 isp->mmio_size[res] = resource_size(mem);
2024
2025 /* map the region */
2026 isp->mmio_base[res] = ioremap_nocache(isp->mmio_base_phys[res],
2027 isp->mmio_size[res]);
2028 if (!isp->mmio_base[res]) {
2029 dev_err(isp->dev, "cannot map camera register I/O region\n");
2030 return -ENODEV;
2031 }
2032
2033 return 0;
2034}
2035
2036/*
2037 * isp_probe - Probe ISP platform device
2038 * @pdev: Pointer to ISP platform device
2039 *
2040 * Returns 0 if successful,
2041 * -ENOMEM if no memory available,
2042 * -ENODEV if no platform device resources found
2043 * or no space for remapping registers,
2044 * -EINVAL if couldn't install ISR,
2045 * or clk_get return error value.
2046 */
2047static int isp_probe(struct platform_device *pdev)
2048{
2049 struct isp_platform_data *pdata = pdev->dev.platform_data;
2050 struct isp_device *isp;
2051 int ret;
2052 int i, m;
2053
2054 if (pdata == NULL)
2055 return -EINVAL;
2056
2057 isp = kzalloc(sizeof(*isp), GFP_KERNEL);
2058 if (!isp) {
2059 dev_err(&pdev->dev, "could not allocate memory\n");
2060 return -ENOMEM;
2061 }
2062
2063 isp->autoidle = autoidle;
2064 isp->platform_cb.set_xclk = isp_set_xclk;
2065 isp->platform_cb.set_pixel_clock = isp_set_pixel_clock;
2066
2067 mutex_init(&isp->isp_mutex);
2068 spin_lock_init(&isp->stat_lock);
2069
2070 isp->dev = &pdev->dev;
2071 isp->pdata = pdata;
2072 isp->ref_count = 0;
2073
2074 isp->raw_dmamask = DMA_BIT_MASK(32);
2075 isp->dev->dma_mask = &isp->raw_dmamask;
2076 isp->dev->coherent_dma_mask = DMA_BIT_MASK(32);
2077
2078 platform_set_drvdata(pdev, isp);
2079
2080 /* Regulators */
2081 isp->isp_csiphy1.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY1");
2082 isp->isp_csiphy2.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY2");
2083
2084 /* Clocks */
2085 ret = isp_map_mem_resource(pdev, isp, OMAP3_ISP_IOMEM_MAIN);
2086 if (ret < 0)
2087 goto error;
2088
2089 ret = isp_get_clocks(isp);
2090 if (ret < 0)
2091 goto error;
2092
2093 if (omap3isp_get(isp) == NULL)
2094 goto error;
2095
2096 ret = isp_reset(isp);
2097 if (ret < 0)
2098 goto error_isp;
2099
2100 /* Memory resources */
2101 isp->revision = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
2102 dev_info(isp->dev, "Revision %d.%d found\n",
2103 (isp->revision & 0xf0) >> 4, isp->revision & 0x0f);
2104
2105 for (m = 0; m < ARRAY_SIZE(isp_res_maps); m++)
2106 if (isp->revision == isp_res_maps[m].isp_rev)
2107 break;
2108
2109 if (m == ARRAY_SIZE(isp_res_maps)) {
2110 dev_err(isp->dev, "No resource map found for ISP rev %d.%d\n",
2111 (isp->revision & 0xf0) >> 4, isp->revision & 0xf);
2112 ret = -ENODEV;
2113 goto error_isp;
2114 }
2115
2116 for (i = 1; i < OMAP3_ISP_IOMEM_LAST; i++) {
2117 if (isp_res_maps[m].map & 1 << i) {
2118 ret = isp_map_mem_resource(pdev, isp, i);
2119 if (ret)
2120 goto error_isp;
2121 }
2122 }
2123
2124 isp->domain = iommu_domain_alloc(pdev->dev.bus);
2125 if (!isp->domain) {
2126 dev_err(isp->dev, "can't alloc iommu domain\n");
2127 ret = -ENOMEM;
2128 goto error_isp;
2129 }
2130
2131 ret = iommu_attach_device(isp->domain, &pdev->dev);
2132 if (ret) {
2133 dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret);
2134 goto free_domain;
2135 }
2136
2137 /* Interrupt */
2138 isp->irq_num = platform_get_irq(pdev, 0);
2139 if (isp->irq_num <= 0) {
2140 dev_err(isp->dev, "No IRQ resource\n");
2141 ret = -ENODEV;
2142 goto detach_dev;
2143 }
2144
2145 if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) {
2146 dev_err(isp->dev, "Unable to request IRQ\n");
2147 ret = -EINVAL;
2148 goto detach_dev;
2149 }
2150
2151 /* Entities */
2152 ret = isp_initialize_modules(isp);
2153 if (ret < 0)
2154 goto error_irq;
2155
2156 ret = isp_register_entities(isp);
2157 if (ret < 0)
2158 goto error_modules;
2159
2160 isp_power_settings(isp, 1);
2161 omap3isp_put(isp);
2162
2163 return 0;
2164
2165error_modules:
2166 isp_cleanup_modules(isp);
2167error_irq:
2168 free_irq(isp->irq_num, isp);
2169detach_dev:
2170 iommu_detach_device(isp->domain, &pdev->dev);
2171free_domain:
2172 iommu_domain_free(isp->domain);
2173error_isp:
2174 omap3isp_put(isp);
2175error:
2176 isp_put_clocks(isp);
2177
2178 for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) {
2179 if (isp->mmio_base[i]) {
2180 iounmap(isp->mmio_base[i]);
2181 isp->mmio_base[i] = NULL;
2182 }
2183
2184 if (isp->mmio_base_phys[i]) {
2185 release_mem_region(isp->mmio_base_phys[i],
2186 isp->mmio_size[i]);
2187 isp->mmio_base_phys[i] = 0;
2188 }
2189 }
2190 regulator_put(isp->isp_csiphy2.vdd);
2191 regulator_put(isp->isp_csiphy1.vdd);
2192 platform_set_drvdata(pdev, NULL);
2193 kfree(isp);
2194
2195 return ret;
2196}
2197
2198static const struct dev_pm_ops omap3isp_pm_ops = {
2199 .prepare = isp_pm_prepare,
2200 .suspend = isp_pm_suspend,
2201 .resume = isp_pm_resume,
2202 .complete = isp_pm_complete,
2203};
2204
2205static struct platform_device_id omap3isp_id_table[] = {
2206 { "omap3isp", 0 },
2207 { },
2208};
2209MODULE_DEVICE_TABLE(platform, omap3isp_id_table);
2210
2211static struct platform_driver omap3isp_driver = {
2212 .probe = isp_probe,
2213 .remove = isp_remove,
2214 .id_table = omap3isp_id_table,
2215 .driver = {
2216 .owner = THIS_MODULE,
2217 .name = "omap3isp",
2218 .pm = &omap3isp_pm_ops,
2219 },
2220};
2221
2222/*
2223 * isp_init - ISP module initialization.
2224 */
2225static int __init isp_init(void)
2226{
2227 return platform_driver_register(&omap3isp_driver);
2228}
2229
2230/*
2231 * isp_cleanup - ISP module cleanup.
2232 */
2233static void __exit isp_cleanup(void)
2234{
2235 platform_driver_unregister(&omap3isp_driver);
2236}
2237
2238module_init(isp_init);
2239module_exit(isp_cleanup);
2240
2241MODULE_AUTHOR("Nokia Corporation");
2242MODULE_DESCRIPTION("TI OMAP3 ISP driver");
2243MODULE_LICENSE("GPL");
2244MODULE_VERSION(ISP_VIDEO_DRIVER_VERSION);
diff --git a/drivers/media/video/omap3isp/isp.h b/drivers/media/video/omap3isp/isp.h
new file mode 100644
index 00000000000..60e0e29e3ed
--- /dev/null
+++ b/drivers/media/video/omap3isp/isp.h
@@ -0,0 +1,438 @@
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/v4l2-device.h>
31#include <linux/device.h>
32#include <linux/io.h>
33#include <linux/platform_device.h>
34#include <linux/wait.h>
35#include <linux/iommu.h>
36#include <plat/iommu.h>
37#include <plat/iovmm.h>
38
39#include "ispstat.h"
40#include "ispccdc.h"
41#include "ispreg.h"
42#include "ispresizer.h"
43#include "isppreview.h"
44#include "ispcsiphy.h"
45#include "ispcsi2.h"
46#include "ispccp2.h"
47
48#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
49
50#define ISP_TOK_TERM 0xFFFFFFFF /*
51 * terminating token for ISP
52 * modules reg list
53 */
54#define to_isp_device(ptr_module) \
55 container_of(ptr_module, struct isp_device, isp_##ptr_module)
56#define to_device(ptr_module) \
57 (to_isp_device(ptr_module)->dev)
58
59enum isp_mem_resources {
60 OMAP3_ISP_IOMEM_MAIN,
61 OMAP3_ISP_IOMEM_CCP2,
62 OMAP3_ISP_IOMEM_CCDC,
63 OMAP3_ISP_IOMEM_HIST,
64 OMAP3_ISP_IOMEM_H3A,
65 OMAP3_ISP_IOMEM_PREV,
66 OMAP3_ISP_IOMEM_RESZ,
67 OMAP3_ISP_IOMEM_SBL,
68 OMAP3_ISP_IOMEM_CSI2A_REGS1,
69 OMAP3_ISP_IOMEM_CSIPHY2,
70 OMAP3_ISP_IOMEM_CSI2A_REGS2,
71 OMAP3_ISP_IOMEM_CSI2C_REGS1,
72 OMAP3_ISP_IOMEM_CSIPHY1,
73 OMAP3_ISP_IOMEM_CSI2C_REGS2,
74 OMAP3_ISP_IOMEM_LAST
75};
76
77enum isp_sbl_resource {
78 OMAP3_ISP_SBL_CSI1_READ = 0x1,
79 OMAP3_ISP_SBL_CSI1_WRITE = 0x2,
80 OMAP3_ISP_SBL_CSI2A_WRITE = 0x4,
81 OMAP3_ISP_SBL_CSI2C_WRITE = 0x8,
82 OMAP3_ISP_SBL_CCDC_LSC_READ = 0x10,
83 OMAP3_ISP_SBL_CCDC_WRITE = 0x20,
84 OMAP3_ISP_SBL_PREVIEW_READ = 0x40,
85 OMAP3_ISP_SBL_PREVIEW_WRITE = 0x80,
86 OMAP3_ISP_SBL_RESIZER_READ = 0x100,
87 OMAP3_ISP_SBL_RESIZER_WRITE = 0x200,
88};
89
90enum isp_subclk_resource {
91 OMAP3_ISP_SUBCLK_CCDC = (1 << 0),
92 OMAP3_ISP_SUBCLK_H3A = (1 << 1),
93 OMAP3_ISP_SUBCLK_HIST = (1 << 2),
94 OMAP3_ISP_SUBCLK_PREVIEW = (1 << 3),
95 OMAP3_ISP_SUBCLK_RESIZER = (1 << 4),
96};
97
98enum isp_interface_type {
99 ISP_INTERFACE_PARALLEL,
100 ISP_INTERFACE_CSI2A_PHY2,
101 ISP_INTERFACE_CCP2B_PHY1,
102 ISP_INTERFACE_CCP2B_PHY2,
103 ISP_INTERFACE_CSI2C_PHY1,
104};
105
106/* ISP: OMAP 34xx ES 1.0 */
107#define ISP_REVISION_1_0 0x10
108/* ISP2: OMAP 34xx ES 2.0, 2.1 and 3.0 */
109#define ISP_REVISION_2_0 0x20
110/* ISP2P: OMAP 36xx */
111#define ISP_REVISION_15_0 0xF0
112
113/*
114 * struct isp_res_mapping - Map ISP io resources to ISP revision.
115 * @isp_rev: ISP_REVISION_x_x
116 * @map: bitmap for enum isp_mem_resources
117 */
118struct isp_res_mapping {
119 u32 isp_rev;
120 u32 map;
121};
122
123/*
124 * struct isp_reg - Structure for ISP register values.
125 * @reg: 32-bit Register address.
126 * @val: 32-bit Register value.
127 */
128struct isp_reg {
129 enum isp_mem_resources mmio_range;
130 u32 reg;
131 u32 val;
132};
133
134/**
135 * struct isp_parallel_platform_data - Parallel interface platform data
136 * @data_lane_shift: Data lane shifter
137 * 0 - CAMEXT[13:0] -> CAM[13:0]
138 * 1 - CAMEXT[13:2] -> CAM[11:0]
139 * 2 - CAMEXT[13:4] -> CAM[9:0]
140 * 3 - CAMEXT[13:6] -> CAM[7:0]
141 * @clk_pol: Pixel clock polarity
142 * 0 - Non Inverted, 1 - Inverted
143 * @hs_pol: Horizontal synchronization polarity
144 * 0 - Active high, 1 - Active low
145 * @vs_pol: Vertical synchronization polarity
146 * 0 - Active high, 1 - Active low
147 * @bridge: CCDC Bridge input control
148 * ISPCTRL_PAR_BRIDGE_DISABLE - Disable
149 * ISPCTRL_PAR_BRIDGE_LENDIAN - Little endian
150 * ISPCTRL_PAR_BRIDGE_BENDIAN - Big endian
151 */
152struct isp_parallel_platform_data {
153 unsigned int data_lane_shift:2;
154 unsigned int clk_pol:1;
155 unsigned int hs_pol:1;
156 unsigned int vs_pol:1;
157 unsigned int bridge:4;
158};
159
160/**
161 * struct isp_ccp2_platform_data - CCP2 interface platform data
162 * @strobe_clk_pol: Strobe/clock polarity
163 * 0 - Non Inverted, 1 - Inverted
164 * @crc: Enable the cyclic redundancy check
165 * @ccp2_mode: Enable CCP2 compatibility mode
166 * 0 - MIPI-CSI1 mode, 1 - CCP2 mode
167 * @phy_layer: Physical layer selection
168 * ISPCCP2_CTRL_PHY_SEL_CLOCK - Data/clock physical layer
169 * ISPCCP2_CTRL_PHY_SEL_STROBE - Data/strobe physical layer
170 * @vpclk_div: Video port output clock control
171 */
172struct isp_ccp2_platform_data {
173 unsigned int strobe_clk_pol:1;
174 unsigned int crc:1;
175 unsigned int ccp2_mode:1;
176 unsigned int phy_layer:1;
177 unsigned int vpclk_div:2;
178};
179
180/**
181 * struct isp_csi2_platform_data - CSI2 interface platform data
182 * @crc: Enable the cyclic redundancy check
183 * @vpclk_div: Video port output clock control
184 */
185struct isp_csi2_platform_data {
186 unsigned crc:1;
187 unsigned vpclk_div:2;
188};
189
190struct isp_subdev_i2c_board_info {
191 struct i2c_board_info *board_info;
192 int i2c_adapter_id;
193};
194
195struct isp_v4l2_subdevs_group {
196 struct isp_subdev_i2c_board_info *subdevs;
197 enum isp_interface_type interface;
198 union {
199 struct isp_parallel_platform_data parallel;
200 struct isp_ccp2_platform_data ccp2;
201 struct isp_csi2_platform_data csi2;
202 } bus; /* gcc < 4.6.0 chokes on anonymous union initializers */
203};
204
205struct isp_platform_data {
206 struct isp_v4l2_subdevs_group *subdevs;
207 void (*set_constraints)(struct isp_device *isp, bool enable);
208};
209
210struct isp_platform_callback {
211 u32 (*set_xclk)(struct isp_device *isp, u32 xclk, u8 xclksel);
212 int (*csiphy_config)(struct isp_csiphy *phy,
213 struct isp_csiphy_dphy_cfg *dphy,
214 struct isp_csiphy_lanes_cfg *lanes);
215 void (*set_pixel_clock)(struct isp_device *isp, unsigned int pixelclk);
216};
217
218/*
219 * struct isp_device - ISP device structure.
220 * @dev: Device pointer specific to the OMAP3 ISP.
221 * @revision: Stores current ISP module revision.
222 * @irq_num: Currently used IRQ number.
223 * @mmio_base: Array with kernel base addresses for ioremapped ISP register
224 * regions.
225 * @mmio_base_phys: Array with physical L4 bus addresses for ISP register
226 * regions.
227 * @mmio_size: Array with ISP register regions size in bytes.
228 * @raw_dmamask: Raw DMA mask
229 * @stat_lock: Spinlock for handling statistics
230 * @isp_mutex: Mutex for serializing requests to ISP.
231 * @has_context: Context has been saved at least once and can be restored.
232 * @ref_count: Reference count for handling multiple ISP requests.
233 * @cam_ick: Pointer to camera interface clock structure.
234 * @cam_mclk: Pointer to camera functional clock structure.
235 * @dpll4_m5_ck: Pointer to DPLL4 M5 clock structure.
236 * @csi2_fck: Pointer to camera CSI2 complexIO clock structure.
237 * @l3_ick: Pointer to OMAP3 L3 bus interface clock.
238 * @irq: Currently attached ISP ISR callbacks information structure.
239 * @isp_af: Pointer to current settings for ISP AutoFocus SCM.
240 * @isp_hist: Pointer to current settings for ISP Histogram SCM.
241 * @isp_h3a: Pointer to current settings for ISP Auto Exposure and
242 * White Balance SCM.
243 * @isp_res: Pointer to current settings for ISP Resizer.
244 * @isp_prev: Pointer to current settings for ISP Preview.
245 * @isp_ccdc: Pointer to current settings for ISP CCDC.
246 * @iommu: Pointer to requested IOMMU instance for ISP.
247 * @platform_cb: ISP driver callback function pointers for platform code
248 *
249 * This structure is used to store the OMAP ISP Information.
250 */
251struct isp_device {
252 struct v4l2_device v4l2_dev;
253 struct media_device media_dev;
254 struct device *dev;
255 u32 revision;
256
257 /* platform HW resources */
258 struct isp_platform_data *pdata;
259 unsigned int irq_num;
260
261 void __iomem *mmio_base[OMAP3_ISP_IOMEM_LAST];
262 unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_LAST];
263 resource_size_t mmio_size[OMAP3_ISP_IOMEM_LAST];
264
265 u64 raw_dmamask;
266
267 /* ISP Obj */
268 spinlock_t stat_lock; /* common lock for statistic drivers */
269 struct mutex isp_mutex; /* For handling ref_count field */
270 bool needs_reset;
271 int has_context;
272 int ref_count;
273 unsigned int autoidle;
274 u32 xclk_divisor[2]; /* Two clocks, a and b. */
275#define ISP_CLK_CAM_ICK 0
276#define ISP_CLK_CAM_MCLK 1
277#define ISP_CLK_DPLL4_M5_CK 2
278#define ISP_CLK_CSI2_FCK 3
279#define ISP_CLK_L3_ICK 4
280 struct clk *clock[5];
281
282 /* ISP modules */
283 struct ispstat isp_af;
284 struct ispstat isp_aewb;
285 struct ispstat isp_hist;
286 struct isp_res_device isp_res;
287 struct isp_prev_device isp_prev;
288 struct isp_ccdc_device isp_ccdc;
289 struct isp_csi2_device isp_csi2a;
290 struct isp_csi2_device isp_csi2c;
291 struct isp_ccp2_device isp_ccp2;
292 struct isp_csiphy isp_csiphy1;
293 struct isp_csiphy isp_csiphy2;
294
295 unsigned int sbl_resources;
296 unsigned int subclk_resources;
297
298 struct iommu_domain *domain;
299
300 struct isp_platform_callback platform_cb;
301};
302
303#define v4l2_dev_to_isp_device(dev) \
304 container_of(dev, struct isp_device, v4l2_dev)
305
306void omap3isp_hist_dma_done(struct isp_device *isp);
307
308void omap3isp_flush(struct isp_device *isp);
309
310int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
311 atomic_t *stopping);
312
313int omap3isp_module_sync_is_stopping(wait_queue_head_t *wait,
314 atomic_t *stopping);
315
316int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
317 enum isp_pipeline_stream_state state);
318void omap3isp_configure_bridge(struct isp_device *isp,
319 enum ccdc_input_entity input,
320 const struct isp_parallel_platform_data *pdata,
321 unsigned int shift);
322
323#define ISP_XCLK_NONE 0
324#define ISP_XCLK_A 1
325#define ISP_XCLK_B 2
326
327struct isp_device *omap3isp_get(struct isp_device *isp);
328void omap3isp_put(struct isp_device *isp);
329
330void omap3isp_print_status(struct isp_device *isp);
331
332void omap3isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res);
333void omap3isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res);
334
335void omap3isp_subclk_enable(struct isp_device *isp,
336 enum isp_subclk_resource res);
337void omap3isp_subclk_disable(struct isp_device *isp,
338 enum isp_subclk_resource res);
339
340int omap3isp_pipeline_pm_use(struct media_entity *entity, int use);
341
342int omap3isp_register_entities(struct platform_device *pdev,
343 struct v4l2_device *v4l2_dev);
344void omap3isp_unregister_entities(struct platform_device *pdev);
345
346/*
347 * isp_reg_readl - Read value of an OMAP3 ISP register
348 * @dev: Device pointer specific to the OMAP3 ISP.
349 * @isp_mmio_range: Range to which the register offset refers to.
350 * @reg_offset: Register offset to read from.
351 *
352 * Returns an unsigned 32 bit value with the required register contents.
353 */
354static inline
355u32 isp_reg_readl(struct isp_device *isp, enum isp_mem_resources isp_mmio_range,
356 u32 reg_offset)
357{
358 return __raw_readl(isp->mmio_base[isp_mmio_range] + reg_offset);
359}
360
361/*
362 * isp_reg_writel - Write value to an OMAP3 ISP register
363 * @dev: Device pointer specific to the OMAP3 ISP.
364 * @reg_value: 32 bit value to write to the register.
365 * @isp_mmio_range: Range to which the register offset refers to.
366 * @reg_offset: Register offset to write into.
367 */
368static inline
369void isp_reg_writel(struct isp_device *isp, u32 reg_value,
370 enum isp_mem_resources isp_mmio_range, u32 reg_offset)
371{
372 __raw_writel(reg_value, isp->mmio_base[isp_mmio_range] + reg_offset);
373}
374
375/*
376 * isp_reg_and - Clear individual bits in an OMAP3 ISP register
377 * @dev: Device pointer specific to the OMAP3 ISP.
378 * @mmio_range: Range to which the register offset refers to.
379 * @reg: Register offset to work on.
380 * @clr_bits: 32 bit value which would be cleared in the register.
381 */
382static inline
383void isp_reg_clr(struct isp_device *isp, enum isp_mem_resources mmio_range,
384 u32 reg, u32 clr_bits)
385{
386 u32 v = isp_reg_readl(isp, mmio_range, reg);
387
388 isp_reg_writel(isp, v & ~clr_bits, mmio_range, reg);
389}
390
391/*
392 * isp_reg_set - Set individual bits in an OMAP3 ISP register
393 * @dev: Device pointer specific to the OMAP3 ISP.
394 * @mmio_range: Range to which the register offset refers to.
395 * @reg: Register offset to work on.
396 * @set_bits: 32 bit value which would be set in the register.
397 */
398static inline
399void isp_reg_set(struct isp_device *isp, enum isp_mem_resources mmio_range,
400 u32 reg, u32 set_bits)
401{
402 u32 v = isp_reg_readl(isp, mmio_range, reg);
403
404 isp_reg_writel(isp, v | set_bits, mmio_range, reg);
405}
406
407/*
408 * isp_reg_clr_set - Clear and set invidial bits in an OMAP3 ISP register
409 * @dev: Device pointer specific to the OMAP3 ISP.
410 * @mmio_range: Range to which the register offset refers to.
411 * @reg: Register offset to work on.
412 * @clr_bits: 32 bit value which would be cleared in the register.
413 * @set_bits: 32 bit value which would be set in the register.
414 *
415 * The clear operation is done first, and then the set operation.
416 */
417static inline
418void isp_reg_clr_set(struct isp_device *isp, enum isp_mem_resources mmio_range,
419 u32 reg, u32 clr_bits, u32 set_bits)
420{
421 u32 v = isp_reg_readl(isp, mmio_range, reg);
422
423 isp_reg_writel(isp, (v & ~clr_bits) | set_bits, mmio_range, reg);
424}
425
426static inline enum v4l2_buf_type
427isp_pad_buffer_type(const struct v4l2_subdev *subdev, int pad)
428{
429 if (pad >= subdev->entity.num_pads)
430 return 0;
431
432 if (subdev->entity.pads[pad].flags & MEDIA_PAD_FL_SINK)
433 return V4L2_BUF_TYPE_VIDEO_OUTPUT;
434 else
435 return V4L2_BUF_TYPE_VIDEO_CAPTURE;
436}
437
438#endif /* OMAP3_ISP_CORE_H */
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
new file mode 100644
index 00000000000..8748e0855c6
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -0,0 +1,2315 @@
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
41static struct v4l2_mbus_framefmt *
42__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
43 unsigned int pad, enum v4l2_subdev_format_whence which);
44
45static const unsigned int ccdc_fmts[] = {
46 V4L2_MBUS_FMT_Y8_1X8,
47 V4L2_MBUS_FMT_Y10_1X10,
48 V4L2_MBUS_FMT_Y12_1X12,
49 V4L2_MBUS_FMT_SGRBG8_1X8,
50 V4L2_MBUS_FMT_SRGGB8_1X8,
51 V4L2_MBUS_FMT_SBGGR8_1X8,
52 V4L2_MBUS_FMT_SGBRG8_1X8,
53 V4L2_MBUS_FMT_SGRBG10_1X10,
54 V4L2_MBUS_FMT_SRGGB10_1X10,
55 V4L2_MBUS_FMT_SBGGR10_1X10,
56 V4L2_MBUS_FMT_SGBRG10_1X10,
57 V4L2_MBUS_FMT_SGRBG12_1X12,
58 V4L2_MBUS_FMT_SRGGB12_1X12,
59 V4L2_MBUS_FMT_SBGGR12_1X12,
60 V4L2_MBUS_FMT_SGBRG12_1X12,
61};
62
63/*
64 * ccdc_print_status - Print current CCDC Module register values.
65 * @ccdc: Pointer to ISP CCDC device.
66 *
67 * Also prints other debug information stored in the CCDC module.
68 */
69#define CCDC_PRINT_REGISTER(isp, name)\
70 dev_dbg(isp->dev, "###CCDC " #name "=0x%08x\n", \
71 isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_##name))
72
73static void ccdc_print_status(struct isp_ccdc_device *ccdc)
74{
75 struct isp_device *isp = to_isp_device(ccdc);
76
77 dev_dbg(isp->dev, "-------------CCDC Register dump-------------\n");
78
79 CCDC_PRINT_REGISTER(isp, PCR);
80 CCDC_PRINT_REGISTER(isp, SYN_MODE);
81 CCDC_PRINT_REGISTER(isp, HD_VD_WID);
82 CCDC_PRINT_REGISTER(isp, PIX_LINES);
83 CCDC_PRINT_REGISTER(isp, HORZ_INFO);
84 CCDC_PRINT_REGISTER(isp, VERT_START);
85 CCDC_PRINT_REGISTER(isp, VERT_LINES);
86 CCDC_PRINT_REGISTER(isp, CULLING);
87 CCDC_PRINT_REGISTER(isp, HSIZE_OFF);
88 CCDC_PRINT_REGISTER(isp, SDOFST);
89 CCDC_PRINT_REGISTER(isp, SDR_ADDR);
90 CCDC_PRINT_REGISTER(isp, CLAMP);
91 CCDC_PRINT_REGISTER(isp, DCSUB);
92 CCDC_PRINT_REGISTER(isp, COLPTN);
93 CCDC_PRINT_REGISTER(isp, BLKCMP);
94 CCDC_PRINT_REGISTER(isp, FPC);
95 CCDC_PRINT_REGISTER(isp, FPC_ADDR);
96 CCDC_PRINT_REGISTER(isp, VDINT);
97 CCDC_PRINT_REGISTER(isp, ALAW);
98 CCDC_PRINT_REGISTER(isp, REC656IF);
99 CCDC_PRINT_REGISTER(isp, CFG);
100 CCDC_PRINT_REGISTER(isp, FMTCFG);
101 CCDC_PRINT_REGISTER(isp, FMT_HORZ);
102 CCDC_PRINT_REGISTER(isp, FMT_VERT);
103 CCDC_PRINT_REGISTER(isp, PRGEVEN0);
104 CCDC_PRINT_REGISTER(isp, PRGEVEN1);
105 CCDC_PRINT_REGISTER(isp, PRGODD0);
106 CCDC_PRINT_REGISTER(isp, PRGODD1);
107 CCDC_PRINT_REGISTER(isp, VP_OUT);
108 CCDC_PRINT_REGISTER(isp, LSC_CONFIG);
109 CCDC_PRINT_REGISTER(isp, LSC_INITIAL);
110 CCDC_PRINT_REGISTER(isp, LSC_TABLE_BASE);
111 CCDC_PRINT_REGISTER(isp, LSC_TABLE_OFFSET);
112
113 dev_dbg(isp->dev, "--------------------------------------------\n");
114}
115
116/*
117 * omap3isp_ccdc_busy - Get busy state of the CCDC.
118 * @ccdc: Pointer to ISP CCDC device.
119 */
120int omap3isp_ccdc_busy(struct isp_ccdc_device *ccdc)
121{
122 struct isp_device *isp = to_isp_device(ccdc);
123
124 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
125 ISPCCDC_PCR_BUSY;
126}
127
128/* -----------------------------------------------------------------------------
129 * Lens Shading Compensation
130 */
131
132/*
133 * ccdc_lsc_validate_config - Check that LSC configuration is valid.
134 * @ccdc: Pointer to ISP CCDC device.
135 * @lsc_cfg: the LSC configuration to check.
136 *
137 * Returns 0 if the LSC configuration is valid, or -EINVAL if invalid.
138 */
139static int ccdc_lsc_validate_config(struct isp_ccdc_device *ccdc,
140 struct omap3isp_ccdc_lsc_config *lsc_cfg)
141{
142 struct isp_device *isp = to_isp_device(ccdc);
143 struct v4l2_mbus_framefmt *format;
144 unsigned int paxel_width, paxel_height;
145 unsigned int paxel_shift_x, paxel_shift_y;
146 unsigned int min_width, min_height, min_size;
147 unsigned int input_width, input_height;
148
149 paxel_shift_x = lsc_cfg->gain_mode_m;
150 paxel_shift_y = lsc_cfg->gain_mode_n;
151
152 if ((paxel_shift_x < 2) || (paxel_shift_x > 6) ||
153 (paxel_shift_y < 2) || (paxel_shift_y > 6)) {
154 dev_dbg(isp->dev, "CCDC: LSC: Invalid paxel size\n");
155 return -EINVAL;
156 }
157
158 if (lsc_cfg->offset & 3) {
159 dev_dbg(isp->dev, "CCDC: LSC: Offset must be a multiple of "
160 "4\n");
161 return -EINVAL;
162 }
163
164 if ((lsc_cfg->initial_x & 1) || (lsc_cfg->initial_y & 1)) {
165 dev_dbg(isp->dev, "CCDC: LSC: initial_x and y must be even\n");
166 return -EINVAL;
167 }
168
169 format = __ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
170 V4L2_SUBDEV_FORMAT_ACTIVE);
171 input_width = format->width;
172 input_height = format->height;
173
174 /* Calculate minimum bytesize for validation */
175 paxel_width = 1 << paxel_shift_x;
176 min_width = ((input_width + lsc_cfg->initial_x + paxel_width - 1)
177 >> paxel_shift_x) + 1;
178
179 paxel_height = 1 << paxel_shift_y;
180 min_height = ((input_height + lsc_cfg->initial_y + paxel_height - 1)
181 >> paxel_shift_y) + 1;
182
183 min_size = 4 * min_width * min_height;
184 if (min_size > lsc_cfg->size) {
185 dev_dbg(isp->dev, "CCDC: LSC: too small table\n");
186 return -EINVAL;
187 }
188 if (lsc_cfg->offset < (min_width * 4)) {
189 dev_dbg(isp->dev, "CCDC: LSC: Offset is too small\n");
190 return -EINVAL;
191 }
192 if ((lsc_cfg->size / lsc_cfg->offset) < min_height) {
193 dev_dbg(isp->dev, "CCDC: LSC: Wrong size/offset combination\n");
194 return -EINVAL;
195 }
196 return 0;
197}
198
199/*
200 * ccdc_lsc_program_table - Program Lens Shading Compensation table address.
201 * @ccdc: Pointer to ISP CCDC device.
202 */
203static void ccdc_lsc_program_table(struct isp_ccdc_device *ccdc, u32 addr)
204{
205 isp_reg_writel(to_isp_device(ccdc), addr,
206 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
207}
208
209/*
210 * ccdc_lsc_setup_regs - Configures the lens shading compensation module
211 * @ccdc: Pointer to ISP CCDC device.
212 */
213static void ccdc_lsc_setup_regs(struct isp_ccdc_device *ccdc,
214 struct omap3isp_ccdc_lsc_config *cfg)
215{
216 struct isp_device *isp = to_isp_device(ccdc);
217 int reg;
218
219 isp_reg_writel(isp, cfg->offset, OMAP3_ISP_IOMEM_CCDC,
220 ISPCCDC_LSC_TABLE_OFFSET);
221
222 reg = 0;
223 reg |= cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT;
224 reg |= cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT;
225 reg |= cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT;
226 isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
227
228 reg = 0;
229 reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
230 reg |= cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT;
231 reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
232 reg |= cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT;
233 isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC,
234 ISPCCDC_LSC_INITIAL);
235}
236
237static int ccdc_lsc_wait_prefetch(struct isp_ccdc_device *ccdc)
238{
239 struct isp_device *isp = to_isp_device(ccdc);
240 unsigned int wait;
241
242 isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ,
243 OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
244
245 /* timeout 1 ms */
246 for (wait = 0; wait < 1000; wait++) {
247 if (isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS) &
248 IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ) {
249 isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ,
250 OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
251 return 0;
252 }
253
254 rmb();
255 udelay(1);
256 }
257
258 return -ETIMEDOUT;
259}
260
261/*
262 * __ccdc_lsc_enable - Enables/Disables the Lens Shading Compensation module.
263 * @ccdc: Pointer to ISP CCDC device.
264 * @enable: 0 Disables LSC, 1 Enables LSC.
265 */
266static int __ccdc_lsc_enable(struct isp_ccdc_device *ccdc, int enable)
267{
268 struct isp_device *isp = to_isp_device(ccdc);
269 const struct v4l2_mbus_framefmt *format =
270 __ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
271 V4L2_SUBDEV_FORMAT_ACTIVE);
272
273 if ((format->code != V4L2_MBUS_FMT_SGRBG10_1X10) &&
274 (format->code != V4L2_MBUS_FMT_SRGGB10_1X10) &&
275 (format->code != V4L2_MBUS_FMT_SBGGR10_1X10) &&
276 (format->code != V4L2_MBUS_FMT_SGBRG10_1X10))
277 return -EINVAL;
278
279 if (enable)
280 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_LSC_READ);
281
282 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG,
283 ISPCCDC_LSC_ENABLE, enable ? ISPCCDC_LSC_ENABLE : 0);
284
285 if (enable) {
286 if (ccdc_lsc_wait_prefetch(ccdc) < 0) {
287 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC,
288 ISPCCDC_LSC_CONFIG, ISPCCDC_LSC_ENABLE);
289 ccdc->lsc.state = LSC_STATE_STOPPED;
290 dev_warn(to_device(ccdc), "LSC prefecth timeout\n");
291 return -ETIMEDOUT;
292 }
293 ccdc->lsc.state = LSC_STATE_RUNNING;
294 } else {
295 ccdc->lsc.state = LSC_STATE_STOPPING;
296 }
297
298 return 0;
299}
300
301static int ccdc_lsc_busy(struct isp_ccdc_device *ccdc)
302{
303 struct isp_device *isp = to_isp_device(ccdc);
304
305 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG) &
306 ISPCCDC_LSC_BUSY;
307}
308
309/* __ccdc_lsc_configure - Apply a new configuration to the LSC engine
310 * @ccdc: Pointer to ISP CCDC device
311 * @req: New configuration request
312 *
313 * context: in_interrupt()
314 */
315static int __ccdc_lsc_configure(struct isp_ccdc_device *ccdc,
316 struct ispccdc_lsc_config_req *req)
317{
318 if (!req->enable)
319 return -EINVAL;
320
321 if (ccdc_lsc_validate_config(ccdc, &req->config) < 0) {
322 dev_dbg(to_device(ccdc), "Discard LSC configuration\n");
323 return -EINVAL;
324 }
325
326 if (ccdc_lsc_busy(ccdc))
327 return -EBUSY;
328
329 ccdc_lsc_setup_regs(ccdc, &req->config);
330 ccdc_lsc_program_table(ccdc, req->table);
331 return 0;
332}
333
334/*
335 * ccdc_lsc_error_handler - Handle LSC prefetch error scenario.
336 * @ccdc: Pointer to ISP CCDC device.
337 *
338 * Disables LSC, and defers enablement to shadow registers update time.
339 */
340static void ccdc_lsc_error_handler(struct isp_ccdc_device *ccdc)
341{
342 struct isp_device *isp = to_isp_device(ccdc);
343 /*
344 * From OMAP3 TRM: When this event is pending, the module
345 * goes into transparent mode (output =input). Normal
346 * operation can be resumed at the start of the next frame
347 * after:
348 * 1) Clearing this event
349 * 2) Disabling the LSC module
350 * 3) Enabling it
351 */
352 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG,
353 ISPCCDC_LSC_ENABLE);
354 ccdc->lsc.state = LSC_STATE_STOPPED;
355}
356
357static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc,
358 struct ispccdc_lsc_config_req *req)
359{
360 struct isp_device *isp = to_isp_device(ccdc);
361
362 if (req == NULL)
363 return;
364
365 if (req->iovm)
366 dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
367 req->iovm->sgt->nents, DMA_TO_DEVICE);
368 if (req->table)
369 omap_iommu_vfree(isp->domain, isp->dev, req->table);
370 kfree(req);
371}
372
373static void ccdc_lsc_free_queue(struct isp_ccdc_device *ccdc,
374 struct list_head *queue)
375{
376 struct ispccdc_lsc_config_req *req, *n;
377 unsigned long flags;
378
379 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
380 list_for_each_entry_safe(req, n, queue, list) {
381 list_del(&req->list);
382 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
383 ccdc_lsc_free_request(ccdc, req);
384 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
385 }
386 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
387}
388
389static void ccdc_lsc_free_table_work(struct work_struct *work)
390{
391 struct isp_ccdc_device *ccdc;
392 struct ispccdc_lsc *lsc;
393
394 lsc = container_of(work, struct ispccdc_lsc, table_work);
395 ccdc = container_of(lsc, struct isp_ccdc_device, lsc);
396
397 ccdc_lsc_free_queue(ccdc, &lsc->free_queue);
398}
399
400/*
401 * ccdc_lsc_config - Configure the LSC module from a userspace request
402 *
403 * Store the request LSC configuration in the LSC engine request pointer. The
404 * configuration will be applied to the hardware when the CCDC will be enabled,
405 * or at the next LSC interrupt if the CCDC is already running.
406 */
407static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
408 struct omap3isp_ccdc_update_config *config)
409{
410 struct isp_device *isp = to_isp_device(ccdc);
411 struct ispccdc_lsc_config_req *req;
412 unsigned long flags;
413 void *table;
414 u16 update;
415 int ret;
416
417 update = config->update &
418 (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC);
419 if (!update)
420 return 0;
421
422 if (update != (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC)) {
423 dev_dbg(to_device(ccdc), "%s: Both LSC configuration and table "
424 "need to be supplied\n", __func__);
425 return -EINVAL;
426 }
427
428 req = kzalloc(sizeof(*req), GFP_KERNEL);
429 if (req == NULL)
430 return -ENOMEM;
431
432 if (config->flag & OMAP3ISP_CCDC_CONFIG_LSC) {
433 if (copy_from_user(&req->config, config->lsc_cfg,
434 sizeof(req->config))) {
435 ret = -EFAULT;
436 goto done;
437 }
438
439 req->enable = 1;
440
441 req->table = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
442 req->config.size, IOMMU_FLAG);
443 if (IS_ERR_VALUE(req->table)) {
444 req->table = 0;
445 ret = -ENOMEM;
446 goto done;
447 }
448
449 req->iovm = omap_find_iovm_area(isp->dev, req->table);
450 if (req->iovm == NULL) {
451 ret = -ENOMEM;
452 goto done;
453 }
454
455 if (!dma_map_sg(isp->dev, req->iovm->sgt->sgl,
456 req->iovm->sgt->nents, DMA_TO_DEVICE)) {
457 ret = -ENOMEM;
458 req->iovm = NULL;
459 goto done;
460 }
461
462 dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl,
463 req->iovm->sgt->nents, DMA_TO_DEVICE);
464
465 table = omap_da_to_va(isp->dev, req->table);
466 if (copy_from_user(table, config->lsc, req->config.size)) {
467 ret = -EFAULT;
468 goto done;
469 }
470
471 dma_sync_sg_for_device(isp->dev, req->iovm->sgt->sgl,
472 req->iovm->sgt->nents, DMA_TO_DEVICE);
473 }
474
475 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
476 if (ccdc->lsc.request) {
477 list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue);
478 schedule_work(&ccdc->lsc.table_work);
479 }
480 ccdc->lsc.request = req;
481 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
482
483 ret = 0;
484
485done:
486 if (ret < 0)
487 ccdc_lsc_free_request(ccdc, req);
488
489 return ret;
490}
491
492static inline int ccdc_lsc_is_configured(struct isp_ccdc_device *ccdc)
493{
494 unsigned long flags;
495
496 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
497 if (ccdc->lsc.active) {
498 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
499 return 1;
500 }
501 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
502 return 0;
503}
504
505static int ccdc_lsc_enable(struct isp_ccdc_device *ccdc)
506{
507 struct ispccdc_lsc *lsc = &ccdc->lsc;
508
509 if (lsc->state != LSC_STATE_STOPPED)
510 return -EINVAL;
511
512 if (lsc->active) {
513 list_add_tail(&lsc->active->list, &lsc->free_queue);
514 lsc->active = NULL;
515 }
516
517 if (__ccdc_lsc_configure(ccdc, lsc->request) < 0) {
518 omap3isp_sbl_disable(to_isp_device(ccdc),
519 OMAP3_ISP_SBL_CCDC_LSC_READ);
520 list_add_tail(&lsc->request->list, &lsc->free_queue);
521 lsc->request = NULL;
522 goto done;
523 }
524
525 lsc->active = lsc->request;
526 lsc->request = NULL;
527 __ccdc_lsc_enable(ccdc, 1);
528
529done:
530 if (!list_empty(&lsc->free_queue))
531 schedule_work(&lsc->table_work);
532
533 return 0;
534}
535
536/* -----------------------------------------------------------------------------
537 * Parameters configuration
538 */
539
540/*
541 * ccdc_configure_clamp - Configure optical-black or digital clamping
542 * @ccdc: Pointer to ISP CCDC device.
543 *
544 * The CCDC performs either optical-black or digital clamp. Configure and enable
545 * the selected clamp method.
546 */
547static void ccdc_configure_clamp(struct isp_ccdc_device *ccdc)
548{
549 struct isp_device *isp = to_isp_device(ccdc);
550 u32 clamp;
551
552 if (ccdc->obclamp) {
553 clamp = ccdc->clamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
554 clamp |= ccdc->clamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
555 clamp |= ccdc->clamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
556 clamp |= ccdc->clamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
557 isp_reg_writel(isp, clamp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP);
558 } else {
559 isp_reg_writel(isp, ccdc->clamp.dcsubval,
560 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB);
561 }
562
563 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
564 ISPCCDC_CLAMP_CLAMPEN,
565 ccdc->obclamp ? ISPCCDC_CLAMP_CLAMPEN : 0);
566}
567
568/*
569 * ccdc_configure_fpc - Configure Faulty Pixel Correction
570 * @ccdc: Pointer to ISP CCDC device.
571 */
572static void ccdc_configure_fpc(struct isp_ccdc_device *ccdc)
573{
574 struct isp_device *isp = to_isp_device(ccdc);
575
576 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, ISPCCDC_FPC_FPCEN);
577
578 if (!ccdc->fpc_en)
579 return;
580
581 isp_reg_writel(isp, ccdc->fpc.fpcaddr, OMAP3_ISP_IOMEM_CCDC,
582 ISPCCDC_FPC_ADDR);
583 /* The FPNUM field must be set before enabling FPC. */
584 isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
585 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
586 isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT) |
587 ISPCCDC_FPC_FPCEN, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
588}
589
590/*
591 * ccdc_configure_black_comp - Configure Black Level Compensation.
592 * @ccdc: Pointer to ISP CCDC device.
593 */
594static void ccdc_configure_black_comp(struct isp_ccdc_device *ccdc)
595{
596 struct isp_device *isp = to_isp_device(ccdc);
597 u32 blcomp;
598
599 blcomp = ccdc->blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
600 blcomp |= ccdc->blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
601 blcomp |= ccdc->blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
602 blcomp |= ccdc->blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
603
604 isp_reg_writel(isp, blcomp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP);
605}
606
607/*
608 * ccdc_configure_lpf - Configure Low-Pass Filter (LPF).
609 * @ccdc: Pointer to ISP CCDC device.
610 */
611static void ccdc_configure_lpf(struct isp_ccdc_device *ccdc)
612{
613 struct isp_device *isp = to_isp_device(ccdc);
614
615 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
616 ISPCCDC_SYN_MODE_LPF,
617 ccdc->lpf ? ISPCCDC_SYN_MODE_LPF : 0);
618}
619
620/*
621 * ccdc_configure_alaw - Configure A-law compression.
622 * @ccdc: Pointer to ISP CCDC device.
623 */
624static void ccdc_configure_alaw(struct isp_ccdc_device *ccdc)
625{
626 struct isp_device *isp = to_isp_device(ccdc);
627 u32 alaw = 0;
628
629 switch (ccdc->syncif.datsz) {
630 case 8:
631 return;
632
633 case 10:
634 alaw = ISPCCDC_ALAW_GWDI_9_0;
635 break;
636 case 11:
637 alaw = ISPCCDC_ALAW_GWDI_10_1;
638 break;
639 case 12:
640 alaw = ISPCCDC_ALAW_GWDI_11_2;
641 break;
642 case 13:
643 alaw = ISPCCDC_ALAW_GWDI_12_3;
644 break;
645 }
646
647 if (ccdc->alaw)
648 alaw |= ISPCCDC_ALAW_CCDTBL;
649
650 isp_reg_writel(isp, alaw, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
651}
652
653/*
654 * ccdc_config_imgattr - Configure sensor image specific attributes.
655 * @ccdc: Pointer to ISP CCDC device.
656 * @colptn: Color pattern of the sensor.
657 */
658static void ccdc_config_imgattr(struct isp_ccdc_device *ccdc, u32 colptn)
659{
660 struct isp_device *isp = to_isp_device(ccdc);
661
662 isp_reg_writel(isp, colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
663}
664
665/*
666 * ccdc_config - Set CCDC configuration from userspace
667 * @ccdc: Pointer to ISP CCDC device.
668 * @userspace_add: Structure containing CCDC configuration sent from userspace.
669 *
670 * Returns 0 if successful, -EINVAL if the pointer to the configuration
671 * structure is null, or the copy_from_user function fails to copy user space
672 * memory to kernel space memory.
673 */
674static int ccdc_config(struct isp_ccdc_device *ccdc,
675 struct omap3isp_ccdc_update_config *ccdc_struct)
676{
677 struct isp_device *isp = to_isp_device(ccdc);
678 unsigned long flags;
679
680 spin_lock_irqsave(&ccdc->lock, flags);
681 ccdc->shadow_update = 1;
682 spin_unlock_irqrestore(&ccdc->lock, flags);
683
684 if (OMAP3ISP_CCDC_ALAW & ccdc_struct->update) {
685 ccdc->alaw = !!(OMAP3ISP_CCDC_ALAW & ccdc_struct->flag);
686 ccdc->update |= OMAP3ISP_CCDC_ALAW;
687 }
688
689 if (OMAP3ISP_CCDC_LPF & ccdc_struct->update) {
690 ccdc->lpf = !!(OMAP3ISP_CCDC_LPF & ccdc_struct->flag);
691 ccdc->update |= OMAP3ISP_CCDC_LPF;
692 }
693
694 if (OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->update) {
695 if (copy_from_user(&ccdc->clamp, ccdc_struct->bclamp,
696 sizeof(ccdc->clamp))) {
697 ccdc->shadow_update = 0;
698 return -EFAULT;
699 }
700
701 ccdc->obclamp = !!(OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->flag);
702 ccdc->update |= OMAP3ISP_CCDC_BLCLAMP;
703 }
704
705 if (OMAP3ISP_CCDC_BCOMP & ccdc_struct->update) {
706 if (copy_from_user(&ccdc->blcomp, ccdc_struct->blcomp,
707 sizeof(ccdc->blcomp))) {
708 ccdc->shadow_update = 0;
709 return -EFAULT;
710 }
711
712 ccdc->update |= OMAP3ISP_CCDC_BCOMP;
713 }
714
715 ccdc->shadow_update = 0;
716
717 if (OMAP3ISP_CCDC_FPC & ccdc_struct->update) {
718 u32 table_old = 0;
719 u32 table_new;
720 u32 size;
721
722 if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED)
723 return -EBUSY;
724
725 ccdc->fpc_en = !!(OMAP3ISP_CCDC_FPC & ccdc_struct->flag);
726
727 if (ccdc->fpc_en) {
728 if (copy_from_user(&ccdc->fpc, ccdc_struct->fpc,
729 sizeof(ccdc->fpc)))
730 return -EFAULT;
731
732 /*
733 * table_new must be 64-bytes aligned, but it's
734 * already done by omap_iommu_vmalloc().
735 */
736 size = ccdc->fpc.fpnum * 4;
737 table_new = omap_iommu_vmalloc(isp->domain, isp->dev,
738 0, size, IOMMU_FLAG);
739 if (IS_ERR_VALUE(table_new))
740 return -ENOMEM;
741
742 if (copy_from_user(omap_da_to_va(isp->dev, table_new),
743 (__force void __user *)
744 ccdc->fpc.fpcaddr, size)) {
745 omap_iommu_vfree(isp->domain, isp->dev,
746 table_new);
747 return -EFAULT;
748 }
749
750 table_old = ccdc->fpc.fpcaddr;
751 ccdc->fpc.fpcaddr = table_new;
752 }
753
754 ccdc_configure_fpc(ccdc);
755 if (table_old != 0)
756 omap_iommu_vfree(isp->domain, isp->dev, table_old);
757 }
758
759 return ccdc_lsc_config(ccdc, ccdc_struct);
760}
761
762static void ccdc_apply_controls(struct isp_ccdc_device *ccdc)
763{
764 if (ccdc->update & OMAP3ISP_CCDC_ALAW) {
765 ccdc_configure_alaw(ccdc);
766 ccdc->update &= ~OMAP3ISP_CCDC_ALAW;
767 }
768
769 if (ccdc->update & OMAP3ISP_CCDC_LPF) {
770 ccdc_configure_lpf(ccdc);
771 ccdc->update &= ~OMAP3ISP_CCDC_LPF;
772 }
773
774 if (ccdc->update & OMAP3ISP_CCDC_BLCLAMP) {
775 ccdc_configure_clamp(ccdc);
776 ccdc->update &= ~OMAP3ISP_CCDC_BLCLAMP;
777 }
778
779 if (ccdc->update & OMAP3ISP_CCDC_BCOMP) {
780 ccdc_configure_black_comp(ccdc);
781 ccdc->update &= ~OMAP3ISP_CCDC_BCOMP;
782 }
783}
784
785/*
786 * omap3isp_ccdc_restore_context - Restore values of the CCDC module registers
787 * @dev: Pointer to ISP device
788 */
789void omap3isp_ccdc_restore_context(struct isp_device *isp)
790{
791 struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
792
793 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC);
794
795 ccdc->update = OMAP3ISP_CCDC_ALAW | OMAP3ISP_CCDC_LPF
796 | OMAP3ISP_CCDC_BLCLAMP | OMAP3ISP_CCDC_BCOMP;
797 ccdc_apply_controls(ccdc);
798 ccdc_configure_fpc(ccdc);
799}
800
801/* -----------------------------------------------------------------------------
802 * Format- and pipeline-related configuration helpers
803 */
804
805/*
806 * ccdc_config_vp - Configure the Video Port.
807 * @ccdc: Pointer to ISP CCDC device.
808 */
809static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
810{
811 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
812 struct isp_device *isp = to_isp_device(ccdc);
813 unsigned long l3_ick = pipe->l3_ick;
814 unsigned int max_div = isp->revision == ISP_REVISION_15_0 ? 64 : 8;
815 unsigned int div = 0;
816 u32 fmtcfg_vp;
817
818 fmtcfg_vp = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG)
819 & ~(ISPCCDC_FMTCFG_VPIN_MASK | ISPCCDC_FMTCFG_VPIF_FRQ_MASK);
820
821 switch (ccdc->syncif.datsz) {
822 case 8:
823 case 10:
824 fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
825 break;
826 case 11:
827 fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
828 break;
829 case 12:
830 fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
831 break;
832 case 13:
833 fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
834 break;
835 };
836
837 if (pipe->input)
838 div = DIV_ROUND_UP(l3_ick, pipe->max_rate);
839 else if (ccdc->vpcfg.pixelclk)
840 div = l3_ick / ccdc->vpcfg.pixelclk;
841
842 div = clamp(div, 2U, max_div);
843 fmtcfg_vp |= (div - 2) << ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT;
844
845 isp_reg_writel(isp, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
846}
847
848/*
849 * ccdc_enable_vp - Enable Video Port.
850 * @ccdc: Pointer to ISP CCDC device.
851 * @enable: 0 Disables VP, 1 Enables VP
852 *
853 * This is needed for outputting image to Preview, H3A and HIST ISP submodules.
854 */
855static void ccdc_enable_vp(struct isp_ccdc_device *ccdc, u8 enable)
856{
857 struct isp_device *isp = to_isp_device(ccdc);
858
859 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
860 ISPCCDC_FMTCFG_VPEN, enable ? ISPCCDC_FMTCFG_VPEN : 0);
861}
862
863/*
864 * ccdc_config_outlineoffset - Configure memory saving output line offset
865 * @ccdc: Pointer to ISP CCDC device.
866 * @offset: Address offset to start a new line. Must be twice the
867 * Output width and aligned on 32 byte boundary
868 * @oddeven: Specifies the odd/even line pattern to be chosen to store the
869 * output.
870 * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
871 *
872 * - Configures the output line offset when stored in memory
873 * - Sets the odd/even line pattern to store the output
874 * (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
875 * - Configures the number of even and odd line fields in case of rearranging
876 * the lines.
877 */
878static void ccdc_config_outlineoffset(struct isp_ccdc_device *ccdc,
879 u32 offset, u8 oddeven, u8 numlines)
880{
881 struct isp_device *isp = to_isp_device(ccdc);
882
883 isp_reg_writel(isp, offset & 0xffff,
884 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF);
885
886 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
887 ISPCCDC_SDOFST_FINV);
888
889 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
890 ISPCCDC_SDOFST_FOFST_4L);
891
892 switch (oddeven) {
893 case EVENEVEN:
894 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
895 (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
896 break;
897 case ODDEVEN:
898 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
899 (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
900 break;
901 case EVENODD:
902 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
903 (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
904 break;
905 case ODDODD:
906 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
907 (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
908 break;
909 default:
910 break;
911 }
912}
913
914/*
915 * ccdc_set_outaddr - Set memory address to save output image
916 * @ccdc: Pointer to ISP CCDC device.
917 * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
918 *
919 * Sets the memory address where the output will be saved.
920 */
921static void ccdc_set_outaddr(struct isp_ccdc_device *ccdc, u32 addr)
922{
923 struct isp_device *isp = to_isp_device(ccdc);
924
925 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR);
926}
927
928/*
929 * omap3isp_ccdc_max_rate - Calculate maximum input data rate based on the input
930 * @ccdc: Pointer to ISP CCDC device.
931 * @max_rate: Maximum calculated data rate.
932 *
933 * Returns in *max_rate less value between calculated and passed
934 */
935void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
936 unsigned int *max_rate)
937{
938 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
939 unsigned int rate;
940
941 if (pipe == NULL)
942 return;
943
944 /*
945 * TRM says that for parallel sensors the maximum data rate
946 * should be 90% form L3/2 clock, otherwise just L3/2.
947 */
948 if (ccdc->input == CCDC_INPUT_PARALLEL)
949 rate = pipe->l3_ick / 2 * 9 / 10;
950 else
951 rate = pipe->l3_ick / 2;
952
953 *max_rate = min(*max_rate, rate);
954}
955
956/*
957 * ccdc_config_sync_if - Set CCDC sync interface configuration
958 * @ccdc: Pointer to ISP CCDC device.
959 * @syncif: Structure containing the sync parameters like field state, CCDC in
960 * master/slave mode, raw/yuv data, polarity of data, field, hs, vs
961 * signals.
962 */
963static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
964 struct ispccdc_syncif *syncif)
965{
966 struct isp_device *isp = to_isp_device(ccdc);
967 u32 syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC,
968 ISPCCDC_SYN_MODE);
969
970 syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
971
972 if (syncif->fldstat)
973 syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
974 else
975 syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
976
977 syn_mode &= ~ISPCCDC_SYN_MODE_DATSIZ_MASK;
978 switch (syncif->datsz) {
979 case 8:
980 syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
981 break;
982 case 10:
983 syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
984 break;
985 case 11:
986 syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
987 break;
988 case 12:
989 syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
990 break;
991 };
992
993 if (syncif->fldmode)
994 syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
995 else
996 syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
997
998 if (syncif->datapol)
999 syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
1000 else
1001 syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
1002
1003 if (syncif->fldpol)
1004 syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
1005 else
1006 syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
1007
1008 if (syncif->hdpol)
1009 syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
1010 else
1011 syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
1012
1013 if (syncif->vdpol)
1014 syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
1015 else
1016 syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
1017
1018 if (syncif->ccdc_mastermode) {
1019 syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
1020 isp_reg_writel(isp,
1021 syncif->hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT
1022 | syncif->vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT,
1023 OMAP3_ISP_IOMEM_CCDC,
1024 ISPCCDC_HD_VD_WID);
1025
1026 isp_reg_writel(isp,
1027 syncif->ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
1028 | syncif->hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
1029 OMAP3_ISP_IOMEM_CCDC,
1030 ISPCCDC_PIX_LINES);
1031 } else
1032 syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
1033 ISPCCDC_SYN_MODE_VDHDOUT);
1034
1035 isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
1036
1037 if (!syncif->bt_r656_en)
1038 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
1039 ISPCCDC_REC656IF_R656ON);
1040}
1041
1042/* CCDC formats descriptions */
1043static const u32 ccdc_sgrbg_pattern =
1044 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1045 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1046 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1047 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1048 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1049 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1050 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1051 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1052 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1053 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1054 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1055 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1056 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1057 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1058 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1059 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1060
1061static const u32 ccdc_srggb_pattern =
1062 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1063 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1064 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1065 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1066 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1067 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1068 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1069 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1070 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1071 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1072 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1073 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1074 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1075 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1076 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1077 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1078
1079static const u32 ccdc_sbggr_pattern =
1080 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1081 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1082 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1083 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1084 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1085 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1086 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1087 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1088 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1089 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1090 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1091 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1092 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1093 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1094 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1095 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1096
1097static const u32 ccdc_sgbrg_pattern =
1098 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1099 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1100 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1101 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1102 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1103 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1104 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1105 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1106 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1107 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1108 ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1109 ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1110 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1111 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1112 ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1113 ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1114
1115static void ccdc_configure(struct isp_ccdc_device *ccdc)
1116{
1117 struct isp_device *isp = to_isp_device(ccdc);
1118 struct isp_parallel_platform_data *pdata = NULL;
1119 struct v4l2_subdev *sensor;
1120 struct v4l2_mbus_framefmt *format;
1121 const struct isp_format_info *fmt_info;
1122 struct v4l2_subdev_format fmt_src;
1123 unsigned int depth_out;
1124 unsigned int depth_in = 0;
1125 struct media_pad *pad;
1126 unsigned long flags;
1127 unsigned int shift;
1128 u32 syn_mode;
1129 u32 ccdc_pattern;
1130
1131 pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
1132 sensor = media_entity_to_v4l2_subdev(pad->entity);
1133 if (ccdc->input == CCDC_INPUT_PARALLEL)
1134 pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
1135 ->bus.parallel;
1136
1137 /* Compute shift value for lane shifter to configure the bridge. */
1138 fmt_src.pad = pad->index;
1139 fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1140 if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) {
1141 fmt_info = omap3isp_video_format_info(fmt_src.format.code);
1142 depth_in = fmt_info->bpp;
1143 }
1144
1145 fmt_info = omap3isp_video_format_info
1146 (isp->isp_ccdc.formats[CCDC_PAD_SINK].code);
1147 depth_out = fmt_info->bpp;
1148
1149 shift = depth_in - depth_out;
1150 omap3isp_configure_bridge(isp, ccdc->input, pdata, shift);
1151
1152 ccdc->syncif.datsz = depth_out;
1153 ccdc->syncif.hdpol = pdata ? pdata->hs_pol : 0;
1154 ccdc->syncif.vdpol = pdata ? pdata->vs_pol : 0;
1155 ccdc_config_sync_if(ccdc, &ccdc->syncif);
1156
1157 /* CCDC_PAD_SINK */
1158 format = &ccdc->formats[CCDC_PAD_SINK];
1159
1160 syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
1161
1162 /* Use the raw, unprocessed data when writing to memory. The H3A and
1163 * histogram modules are still fed with lens shading corrected data.
1164 */
1165 syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
1166
1167 if (ccdc->output & CCDC_OUTPUT_MEMORY)
1168 syn_mode |= ISPCCDC_SYN_MODE_WEN;
1169 else
1170 syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
1171
1172 if (ccdc->output & CCDC_OUTPUT_RESIZER)
1173 syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
1174 else
1175 syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
1176
1177 /* Use PACK8 mode for 1byte per pixel formats. */
1178 if (omap3isp_video_format_info(format->code)->bpp <= 8)
1179 syn_mode |= ISPCCDC_SYN_MODE_PACK8;
1180 else
1181 syn_mode &= ~ISPCCDC_SYN_MODE_PACK8;
1182
1183 isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
1184
1185 /* Mosaic filter */
1186 switch (format->code) {
1187 case V4L2_MBUS_FMT_SRGGB10_1X10:
1188 case V4L2_MBUS_FMT_SRGGB12_1X12:
1189 ccdc_pattern = ccdc_srggb_pattern;
1190 break;
1191 case V4L2_MBUS_FMT_SBGGR10_1X10:
1192 case V4L2_MBUS_FMT_SBGGR12_1X12:
1193 ccdc_pattern = ccdc_sbggr_pattern;
1194 break;
1195 case V4L2_MBUS_FMT_SGBRG10_1X10:
1196 case V4L2_MBUS_FMT_SGBRG12_1X12:
1197 ccdc_pattern = ccdc_sgbrg_pattern;
1198 break;
1199 default:
1200 /* Use GRBG */
1201 ccdc_pattern = ccdc_sgrbg_pattern;
1202 break;
1203 }
1204 ccdc_config_imgattr(ccdc, ccdc_pattern);
1205
1206 /* Generate VD0 on the last line of the image and VD1 on the
1207 * 2/3 height line.
1208 */
1209 isp_reg_writel(isp, ((format->height - 2) << ISPCCDC_VDINT_0_SHIFT) |
1210 ((format->height * 2 / 3) << ISPCCDC_VDINT_1_SHIFT),
1211 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT);
1212
1213 /* CCDC_PAD_SOURCE_OF */
1214 format = &ccdc->formats[CCDC_PAD_SOURCE_OF];
1215
1216 isp_reg_writel(isp, (0 << ISPCCDC_HORZ_INFO_SPH_SHIFT) |
1217 ((format->width - 1) << ISPCCDC_HORZ_INFO_NPH_SHIFT),
1218 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO);
1219 isp_reg_writel(isp, 0 << ISPCCDC_VERT_START_SLV0_SHIFT,
1220 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START);
1221 isp_reg_writel(isp, (format->height - 1)
1222 << ISPCCDC_VERT_LINES_NLV_SHIFT,
1223 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES);
1224
1225 ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, 0, 0);
1226
1227 /* CCDC_PAD_SOURCE_VP */
1228 format = &ccdc->formats[CCDC_PAD_SOURCE_VP];
1229
1230 isp_reg_writel(isp, (0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
1231 (format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
1232 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ);
1233 isp_reg_writel(isp, (0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
1234 ((format->height + 1) << ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
1235 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT);
1236
1237 isp_reg_writel(isp, (format->width << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
1238 (format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
1239 OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
1240
1241 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
1242 if (ccdc->lsc.request == NULL)
1243 goto unlock;
1244
1245 WARN_ON(ccdc->lsc.active);
1246
1247 /* Get last good LSC configuration. If it is not supported for
1248 * the current active resolution discard it.
1249 */
1250 if (ccdc->lsc.active == NULL &&
1251 __ccdc_lsc_configure(ccdc, ccdc->lsc.request) == 0) {
1252 ccdc->lsc.active = ccdc->lsc.request;
1253 } else {
1254 list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue);
1255 schedule_work(&ccdc->lsc.table_work);
1256 }
1257
1258 ccdc->lsc.request = NULL;
1259
1260unlock:
1261 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
1262
1263 ccdc_apply_controls(ccdc);
1264}
1265
1266static void __ccdc_enable(struct isp_ccdc_device *ccdc, int enable)
1267{
1268 struct isp_device *isp = to_isp_device(ccdc);
1269
1270 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR,
1271 ISPCCDC_PCR_EN, enable ? ISPCCDC_PCR_EN : 0);
1272}
1273
1274static int ccdc_disable(struct isp_ccdc_device *ccdc)
1275{
1276 unsigned long flags;
1277 int ret = 0;
1278
1279 spin_lock_irqsave(&ccdc->lock, flags);
1280 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS)
1281 ccdc->stopping = CCDC_STOP_REQUEST;
1282 spin_unlock_irqrestore(&ccdc->lock, flags);
1283
1284 ret = wait_event_timeout(ccdc->wait,
1285 ccdc->stopping == CCDC_STOP_FINISHED,
1286 msecs_to_jiffies(2000));
1287 if (ret == 0) {
1288 ret = -ETIMEDOUT;
1289 dev_warn(to_device(ccdc), "CCDC stop timeout!\n");
1290 }
1291
1292 omap3isp_sbl_disable(to_isp_device(ccdc), OMAP3_ISP_SBL_CCDC_LSC_READ);
1293
1294 mutex_lock(&ccdc->ioctl_lock);
1295 ccdc_lsc_free_request(ccdc, ccdc->lsc.request);
1296 ccdc->lsc.request = ccdc->lsc.active;
1297 ccdc->lsc.active = NULL;
1298 cancel_work_sync(&ccdc->lsc.table_work);
1299 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
1300 mutex_unlock(&ccdc->ioctl_lock);
1301
1302 ccdc->stopping = CCDC_STOP_NOT_REQUESTED;
1303
1304 return ret > 0 ? 0 : ret;
1305}
1306
1307static void ccdc_enable(struct isp_ccdc_device *ccdc)
1308{
1309 if (ccdc_lsc_is_configured(ccdc))
1310 __ccdc_lsc_enable(ccdc, 1);
1311 __ccdc_enable(ccdc, 1);
1312}
1313
1314/* -----------------------------------------------------------------------------
1315 * Interrupt handling
1316 */
1317
1318/*
1319 * ccdc_sbl_busy - Poll idle state of CCDC and related SBL memory write bits
1320 * @ccdc: Pointer to ISP CCDC device.
1321 *
1322 * Returns zero if the CCDC is idle and the image has been written to
1323 * memory, too.
1324 */
1325static int ccdc_sbl_busy(struct isp_ccdc_device *ccdc)
1326{
1327 struct isp_device *isp = to_isp_device(ccdc);
1328
1329 return omap3isp_ccdc_busy(ccdc)
1330 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) &
1331 ISPSBL_CCDC_WR_0_DATA_READY)
1332 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) &
1333 ISPSBL_CCDC_WR_0_DATA_READY)
1334 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) &
1335 ISPSBL_CCDC_WR_0_DATA_READY)
1336 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) &
1337 ISPSBL_CCDC_WR_0_DATA_READY);
1338}
1339
1340/*
1341 * ccdc_sbl_wait_idle - Wait until the CCDC and related SBL are idle
1342 * @ccdc: Pointer to ISP CCDC device.
1343 * @max_wait: Max retry count in us for wait for idle/busy transition.
1344 */
1345static int ccdc_sbl_wait_idle(struct isp_ccdc_device *ccdc,
1346 unsigned int max_wait)
1347{
1348 unsigned int wait = 0;
1349
1350 if (max_wait == 0)
1351 max_wait = 10000; /* 10 ms */
1352
1353 for (wait = 0; wait <= max_wait; wait++) {
1354 if (!ccdc_sbl_busy(ccdc))
1355 return 0;
1356
1357 rmb();
1358 udelay(1);
1359 }
1360
1361 return -EBUSY;
1362}
1363
1364/* __ccdc_handle_stopping - Handle CCDC and/or LSC stopping sequence
1365 * @ccdc: Pointer to ISP CCDC device.
1366 * @event: Pointing which event trigger handler
1367 *
1368 * Return 1 when the event and stopping request combination is satisfied,
1369 * zero otherwise.
1370 */
1371static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
1372{
1373 int rval = 0;
1374
1375 switch ((ccdc->stopping & 3) | event) {
1376 case CCDC_STOP_REQUEST | CCDC_EVENT_VD1:
1377 if (ccdc->lsc.state != LSC_STATE_STOPPED)
1378 __ccdc_lsc_enable(ccdc, 0);
1379 __ccdc_enable(ccdc, 0);
1380 ccdc->stopping = CCDC_STOP_EXECUTED;
1381 return 1;
1382
1383 case CCDC_STOP_EXECUTED | CCDC_EVENT_VD0:
1384 ccdc->stopping |= CCDC_STOP_CCDC_FINISHED;
1385 if (ccdc->lsc.state == LSC_STATE_STOPPED)
1386 ccdc->stopping |= CCDC_STOP_LSC_FINISHED;
1387 rval = 1;
1388 break;
1389
1390 case CCDC_STOP_EXECUTED | CCDC_EVENT_LSC_DONE:
1391 ccdc->stopping |= CCDC_STOP_LSC_FINISHED;
1392 rval = 1;
1393 break;
1394
1395 case CCDC_STOP_EXECUTED | CCDC_EVENT_VD1:
1396 return 1;
1397 }
1398
1399 if (ccdc->stopping == CCDC_STOP_FINISHED) {
1400 wake_up(&ccdc->wait);
1401 rval = 1;
1402 }
1403
1404 return rval;
1405}
1406
1407static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
1408{
1409 struct isp_pipeline *pipe =
1410 to_isp_pipeline(&ccdc->video_out.video.entity);
1411 struct video_device *vdev = &ccdc->subdev.devnode;
1412 struct v4l2_event event;
1413
1414 memset(&event, 0, sizeof(event));
1415 event.type = V4L2_EVENT_FRAME_SYNC;
1416 event.u.frame_sync.frame_sequence = atomic_read(&pipe->frame_number);
1417
1418 v4l2_event_queue(vdev, &event);
1419}
1420
1421/*
1422 * ccdc_lsc_isr - Handle LSC events
1423 * @ccdc: Pointer to ISP CCDC device.
1424 * @events: LSC events
1425 */
1426static void ccdc_lsc_isr(struct isp_ccdc_device *ccdc, u32 events)
1427{
1428 unsigned long flags;
1429
1430 if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) {
1431 ccdc_lsc_error_handler(ccdc);
1432 ccdc->error = 1;
1433 dev_dbg(to_device(ccdc), "lsc prefetch error\n");
1434 }
1435
1436 if (!(events & IRQ0STATUS_CCDC_LSC_DONE_IRQ))
1437 return;
1438
1439 /* LSC_DONE interrupt occur, there are two cases
1440 * 1. stopping for reconfiguration
1441 * 2. stopping because of STREAM OFF command
1442 */
1443 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
1444
1445 if (ccdc->lsc.state == LSC_STATE_STOPPING)
1446 ccdc->lsc.state = LSC_STATE_STOPPED;
1447
1448 if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_LSC_DONE))
1449 goto done;
1450
1451 if (ccdc->lsc.state != LSC_STATE_RECONFIG)
1452 goto done;
1453
1454 /* LSC is in STOPPING state, change to the new state */
1455 ccdc->lsc.state = LSC_STATE_STOPPED;
1456
1457 /* This is an exception. Start of frame and LSC_DONE interrupt
1458 * have been received on the same time. Skip this event and wait
1459 * for better times.
1460 */
1461 if (events & IRQ0STATUS_HS_VS_IRQ)
1462 goto done;
1463
1464 /* The LSC engine is stopped at this point. Enable it if there's a
1465 * pending request.
1466 */
1467 if (ccdc->lsc.request == NULL)
1468 goto done;
1469
1470 ccdc_lsc_enable(ccdc);
1471
1472done:
1473 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
1474}
1475
1476static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
1477{
1478 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
1479 struct isp_device *isp = to_isp_device(ccdc);
1480 struct isp_buffer *buffer;
1481 int restart = 0;
1482
1483 /* The CCDC generates VD0 interrupts even when disabled (the datasheet
1484 * doesn't explicitly state if that's supposed to happen or not, so it
1485 * can be considered as a hardware bug or as a feature, but we have to
1486 * deal with it anyway). Disabling the CCDC when no buffer is available
1487 * would thus not be enough, we need to handle the situation explicitly.
1488 */
1489 if (list_empty(&ccdc->video_out.dmaqueue))
1490 goto done;
1491
1492 /* We're in continuous mode, and memory writes were disabled due to a
1493 * buffer underrun. Reenable them now that we have a buffer. The buffer
1494 * address has been set in ccdc_video_queue.
1495 */
1496 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && ccdc->underrun) {
1497 restart = 1;
1498 ccdc->underrun = 0;
1499 goto done;
1500 }
1501
1502 if (ccdc_sbl_wait_idle(ccdc, 1000)) {
1503 dev_info(isp->dev, "CCDC won't become idle!\n");
1504 goto done;
1505 }
1506
1507 buffer = omap3isp_video_buffer_next(&ccdc->video_out, ccdc->error);
1508 if (buffer != NULL) {
1509 ccdc_set_outaddr(ccdc, buffer->isp_addr);
1510 restart = 1;
1511 }
1512
1513 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
1514
1515 if (ccdc->state == ISP_PIPELINE_STREAM_SINGLESHOT &&
1516 isp_pipeline_ready(pipe))
1517 omap3isp_pipeline_set_stream(pipe,
1518 ISP_PIPELINE_STREAM_SINGLESHOT);
1519
1520done:
1521 ccdc->error = 0;
1522 return restart;
1523}
1524
1525/*
1526 * ccdc_vd0_isr - Handle VD0 event
1527 * @ccdc: Pointer to ISP CCDC device.
1528 *
1529 * Executes LSC deferred enablement before next frame starts.
1530 */
1531static void ccdc_vd0_isr(struct isp_ccdc_device *ccdc)
1532{
1533 unsigned long flags;
1534 int restart = 0;
1535
1536 if (ccdc->output & CCDC_OUTPUT_MEMORY)
1537 restart = ccdc_isr_buffer(ccdc);
1538
1539 spin_lock_irqsave(&ccdc->lock, flags);
1540 if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD0)) {
1541 spin_unlock_irqrestore(&ccdc->lock, flags);
1542 return;
1543 }
1544
1545 if (!ccdc->shadow_update)
1546 ccdc_apply_controls(ccdc);
1547 spin_unlock_irqrestore(&ccdc->lock, flags);
1548
1549 if (restart)
1550 ccdc_enable(ccdc);
1551}
1552
1553/*
1554 * ccdc_vd1_isr - Handle VD1 event
1555 * @ccdc: Pointer to ISP CCDC device.
1556 */
1557static void ccdc_vd1_isr(struct isp_ccdc_device *ccdc)
1558{
1559 unsigned long flags;
1560
1561 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
1562
1563 /*
1564 * Depending on the CCDC pipeline state, CCDC stopping should be
1565 * handled differently. In SINGLESHOT we emulate an internal CCDC
1566 * stopping because the CCDC hw works only in continuous mode.
1567 * When CONTINUOUS pipeline state is used and the CCDC writes it's
1568 * data to memory the CCDC and LSC are stopped immediately but
1569 * without change the CCDC stopping state machine. The CCDC
1570 * stopping state machine should be used only when user request
1571 * for stopping is received (SINGLESHOT is an exeption).
1572 */
1573 switch (ccdc->state) {
1574 case ISP_PIPELINE_STREAM_SINGLESHOT:
1575 ccdc->stopping = CCDC_STOP_REQUEST;
1576 break;
1577
1578 case ISP_PIPELINE_STREAM_CONTINUOUS:
1579 if (ccdc->output & CCDC_OUTPUT_MEMORY) {
1580 if (ccdc->lsc.state != LSC_STATE_STOPPED)
1581 __ccdc_lsc_enable(ccdc, 0);
1582 __ccdc_enable(ccdc, 0);
1583 }
1584 break;
1585
1586 case ISP_PIPELINE_STREAM_STOPPED:
1587 break;
1588 }
1589
1590 if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD1))
1591 goto done;
1592
1593 if (ccdc->lsc.request == NULL)
1594 goto done;
1595
1596 /*
1597 * LSC need to be reconfigured. Stop it here and on next LSC_DONE IRQ
1598 * do the appropriate changes in registers
1599 */
1600 if (ccdc->lsc.state == LSC_STATE_RUNNING) {
1601 __ccdc_lsc_enable(ccdc, 0);
1602 ccdc->lsc.state = LSC_STATE_RECONFIG;
1603 goto done;
1604 }
1605
1606 /* LSC has been in STOPPED state, enable it */
1607 if (ccdc->lsc.state == LSC_STATE_STOPPED)
1608 ccdc_lsc_enable(ccdc);
1609
1610done:
1611 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
1612}
1613
1614/*
1615 * omap3isp_ccdc_isr - Configure CCDC during interframe time.
1616 * @ccdc: Pointer to ISP CCDC device.
1617 * @events: CCDC events
1618 */
1619int omap3isp_ccdc_isr(struct isp_ccdc_device *ccdc, u32 events)
1620{
1621 if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED)
1622 return 0;
1623
1624 if (events & IRQ0STATUS_CCDC_VD1_IRQ)
1625 ccdc_vd1_isr(ccdc);
1626
1627 ccdc_lsc_isr(ccdc, events);
1628
1629 if (events & IRQ0STATUS_CCDC_VD0_IRQ)
1630 ccdc_vd0_isr(ccdc);
1631
1632 if (events & IRQ0STATUS_HS_VS_IRQ)
1633 ccdc_hs_vs_isr(ccdc);
1634
1635 return 0;
1636}
1637
1638/* -----------------------------------------------------------------------------
1639 * ISP video operations
1640 */
1641
1642static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
1643{
1644 struct isp_ccdc_device *ccdc = &video->isp->isp_ccdc;
1645
1646 if (!(ccdc->output & CCDC_OUTPUT_MEMORY))
1647 return -ENODEV;
1648
1649 ccdc_set_outaddr(ccdc, buffer->isp_addr);
1650
1651 /* We now have a buffer queued on the output, restart the pipeline
1652 * on the next CCDC interrupt if running in continuous mode (or when
1653 * starting the stream).
1654 */
1655 ccdc->underrun = 1;
1656
1657 return 0;
1658}
1659
1660static const struct isp_video_operations ccdc_video_ops = {
1661 .queue = ccdc_video_queue,
1662};
1663
1664/* -----------------------------------------------------------------------------
1665 * V4L2 subdev operations
1666 */
1667
1668/*
1669 * ccdc_ioctl - CCDC module private ioctl's
1670 * @sd: ISP CCDC V4L2 subdevice
1671 * @cmd: ioctl command
1672 * @arg: ioctl argument
1673 *
1674 * Return 0 on success or a negative error code otherwise.
1675 */
1676static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1677{
1678 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1679 int ret;
1680
1681 switch (cmd) {
1682 case VIDIOC_OMAP3ISP_CCDC_CFG:
1683 mutex_lock(&ccdc->ioctl_lock);
1684 ret = ccdc_config(ccdc, arg);
1685 mutex_unlock(&ccdc->ioctl_lock);
1686 break;
1687
1688 default:
1689 return -ENOIOCTLCMD;
1690 }
1691
1692 return ret;
1693}
1694
1695static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1696 struct v4l2_event_subscription *sub)
1697{
1698 if (sub->type != V4L2_EVENT_FRAME_SYNC)
1699 return -EINVAL;
1700
1701 /* line number is zero at frame start */
1702 if (sub->id != 0)
1703 return -EINVAL;
1704
1705 return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS);
1706}
1707
1708static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1709 struct v4l2_event_subscription *sub)
1710{
1711 return v4l2_event_unsubscribe(fh, sub);
1712}
1713
1714/*
1715 * ccdc_set_stream - Enable/Disable streaming on the CCDC module
1716 * @sd: ISP CCDC V4L2 subdevice
1717 * @enable: Enable/disable stream
1718 *
1719 * When writing to memory, the CCDC hardware can't be enabled without a memory
1720 * buffer to write to. As the s_stream operation is called in response to a
1721 * STREAMON call without any buffer queued yet, just update the enabled field
1722 * and return immediately. The CCDC will be enabled in ccdc_isr_buffer().
1723 *
1724 * When not writing to memory enable the CCDC immediately.
1725 */
1726static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
1727{
1728 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1729 struct isp_device *isp = to_isp_device(ccdc);
1730 int ret = 0;
1731
1732 if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) {
1733 if (enable == ISP_PIPELINE_STREAM_STOPPED)
1734 return 0;
1735
1736 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_CCDC);
1737 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
1738 ISPCCDC_CFG_VDLC);
1739
1740 ccdc_configure(ccdc);
1741
1742 /* TODO: Don't configure the video port if all of its output
1743 * links are inactive.
1744 */
1745 ccdc_config_vp(ccdc);
1746 ccdc_enable_vp(ccdc, 1);
1747 ccdc->error = 0;
1748 ccdc_print_status(ccdc);
1749 }
1750
1751 switch (enable) {
1752 case ISP_PIPELINE_STREAM_CONTINUOUS:
1753 if (ccdc->output & CCDC_OUTPUT_MEMORY)
1754 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
1755
1756 if (ccdc->underrun || !(ccdc->output & CCDC_OUTPUT_MEMORY))
1757 ccdc_enable(ccdc);
1758
1759 ccdc->underrun = 0;
1760 break;
1761
1762 case ISP_PIPELINE_STREAM_SINGLESHOT:
1763 if (ccdc->output & CCDC_OUTPUT_MEMORY &&
1764 ccdc->state != ISP_PIPELINE_STREAM_SINGLESHOT)
1765 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
1766
1767 ccdc_enable(ccdc);
1768 break;
1769
1770 case ISP_PIPELINE_STREAM_STOPPED:
1771 ret = ccdc_disable(ccdc);
1772 if (ccdc->output & CCDC_OUTPUT_MEMORY)
1773 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
1774 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_CCDC);
1775 ccdc->underrun = 0;
1776 break;
1777 }
1778
1779 ccdc->state = enable;
1780 return ret;
1781}
1782
1783static struct v4l2_mbus_framefmt *
1784__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
1785 unsigned int pad, enum v4l2_subdev_format_whence which)
1786{
1787 if (which == V4L2_SUBDEV_FORMAT_TRY)
1788 return v4l2_subdev_get_try_format(fh, pad);
1789 else
1790 return &ccdc->formats[pad];
1791}
1792
1793/*
1794 * ccdc_try_format - Try video format on a pad
1795 * @ccdc: ISP CCDC device
1796 * @fh : V4L2 subdev file handle
1797 * @pad: Pad number
1798 * @fmt: Format
1799 */
1800static void
1801ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
1802 unsigned int pad, struct v4l2_mbus_framefmt *fmt,
1803 enum v4l2_subdev_format_whence which)
1804{
1805 struct v4l2_mbus_framefmt *format;
1806 const struct isp_format_info *info;
1807 unsigned int width = fmt->width;
1808 unsigned int height = fmt->height;
1809 unsigned int i;
1810
1811 switch (pad) {
1812 case CCDC_PAD_SINK:
1813 /* TODO: If the CCDC output formatter pad is connected directly
1814 * to the resizer, only YUV formats can be used.
1815 */
1816 for (i = 0; i < ARRAY_SIZE(ccdc_fmts); i++) {
1817 if (fmt->code == ccdc_fmts[i])
1818 break;
1819 }
1820
1821 /* If not found, use SGRBG10 as default */
1822 if (i >= ARRAY_SIZE(ccdc_fmts))
1823 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
1824
1825 /* Clamp the input size. */
1826 fmt->width = clamp_t(u32, width, 32, 4096);
1827 fmt->height = clamp_t(u32, height, 32, 4096);
1828 break;
1829
1830 case CCDC_PAD_SOURCE_OF:
1831 format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
1832 memcpy(fmt, format, sizeof(*fmt));
1833
1834 /* The data formatter truncates the number of horizontal output
1835 * pixels to a multiple of 16. To avoid clipping data, allow
1836 * callers to request an output size bigger than the input size
1837 * up to the nearest multiple of 16.
1838 */
1839 fmt->width = clamp_t(u32, width, 32, fmt->width + 15);
1840 fmt->width &= ~15;
1841 fmt->height = clamp_t(u32, height, 32, fmt->height);
1842 break;
1843
1844 case CCDC_PAD_SOURCE_VP:
1845 format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
1846 memcpy(fmt, format, sizeof(*fmt));
1847
1848 /* The video port interface truncates the data to 10 bits. */
1849 info = omap3isp_video_format_info(fmt->code);
1850 fmt->code = info->truncated;
1851
1852 /* The number of lines that can be clocked out from the video
1853 * port output must be at least one line less than the number
1854 * of input lines.
1855 */
1856 fmt->width = clamp_t(u32, width, 32, fmt->width);
1857 fmt->height = clamp_t(u32, height, 32, fmt->height - 1);
1858 break;
1859 }
1860
1861 /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is
1862 * stored on 2 bytes.
1863 */
1864 fmt->colorspace = V4L2_COLORSPACE_SRGB;
1865 fmt->field = V4L2_FIELD_NONE;
1866}
1867
1868/*
1869 * ccdc_enum_mbus_code - Handle pixel format enumeration
1870 * @sd : pointer to v4l2 subdev structure
1871 * @fh : V4L2 subdev file handle
1872 * @code : pointer to v4l2_subdev_mbus_code_enum structure
1873 * return -EINVAL or zero on success
1874 */
1875static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
1876 struct v4l2_subdev_fh *fh,
1877 struct v4l2_subdev_mbus_code_enum *code)
1878{
1879 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1880 struct v4l2_mbus_framefmt *format;
1881
1882 switch (code->pad) {
1883 case CCDC_PAD_SINK:
1884 if (code->index >= ARRAY_SIZE(ccdc_fmts))
1885 return -EINVAL;
1886
1887 code->code = ccdc_fmts[code->index];
1888 break;
1889
1890 case CCDC_PAD_SOURCE_OF:
1891 case CCDC_PAD_SOURCE_VP:
1892 /* No format conversion inside CCDC */
1893 if (code->index != 0)
1894 return -EINVAL;
1895
1896 format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK,
1897 V4L2_SUBDEV_FORMAT_TRY);
1898
1899 code->code = format->code;
1900 break;
1901
1902 default:
1903 return -EINVAL;
1904 }
1905
1906 return 0;
1907}
1908
1909static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
1910 struct v4l2_subdev_fh *fh,
1911 struct v4l2_subdev_frame_size_enum *fse)
1912{
1913 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1914 struct v4l2_mbus_framefmt format;
1915
1916 if (fse->index != 0)
1917 return -EINVAL;
1918
1919 format.code = fse->code;
1920 format.width = 1;
1921 format.height = 1;
1922 ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1923 fse->min_width = format.width;
1924 fse->min_height = format.height;
1925
1926 if (format.code != fse->code)
1927 return -EINVAL;
1928
1929 format.code = fse->code;
1930 format.width = -1;
1931 format.height = -1;
1932 ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1933 fse->max_width = format.width;
1934 fse->max_height = format.height;
1935
1936 return 0;
1937}
1938
1939/*
1940 * ccdc_get_format - Retrieve the video format on a pad
1941 * @sd : ISP CCDC V4L2 subdevice
1942 * @fh : V4L2 subdev file handle
1943 * @fmt: Format
1944 *
1945 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
1946 * to the format type.
1947 */
1948static int ccdc_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1949 struct v4l2_subdev_format *fmt)
1950{
1951 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1952 struct v4l2_mbus_framefmt *format;
1953
1954 format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
1955 if (format == NULL)
1956 return -EINVAL;
1957
1958 fmt->format = *format;
1959 return 0;
1960}
1961
1962/*
1963 * ccdc_set_format - Set the video format on a pad
1964 * @sd : ISP CCDC V4L2 subdevice
1965 * @fh : V4L2 subdev file handle
1966 * @fmt: Format
1967 *
1968 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
1969 * to the format type.
1970 */
1971static int ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1972 struct v4l2_subdev_format *fmt)
1973{
1974 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1975 struct v4l2_mbus_framefmt *format;
1976
1977 format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
1978 if (format == NULL)
1979 return -EINVAL;
1980
1981 ccdc_try_format(ccdc, fh, fmt->pad, &fmt->format, fmt->which);
1982 *format = fmt->format;
1983
1984 /* Propagate the format from sink to source */
1985 if (fmt->pad == CCDC_PAD_SINK) {
1986 format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_OF,
1987 fmt->which);
1988 *format = fmt->format;
1989 ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_OF, format,
1990 fmt->which);
1991
1992 format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_VP,
1993 fmt->which);
1994 *format = fmt->format;
1995 ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_VP, format,
1996 fmt->which);
1997 }
1998
1999 return 0;
2000}
2001
2002/*
2003 * ccdc_init_formats - Initialize formats on all pads
2004 * @sd: ISP CCDC V4L2 subdevice
2005 * @fh: V4L2 subdev file handle
2006 *
2007 * Initialize all pad formats with default values. If fh is not NULL, try
2008 * formats are initialized on the file handle. Otherwise active formats are
2009 * initialized on the device.
2010 */
2011static int ccdc_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
2012{
2013 struct v4l2_subdev_format format;
2014
2015 memset(&format, 0, sizeof(format));
2016 format.pad = CCDC_PAD_SINK;
2017 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
2018 format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
2019 format.format.width = 4096;
2020 format.format.height = 4096;
2021 ccdc_set_format(sd, fh, &format);
2022
2023 return 0;
2024}
2025
2026/* V4L2 subdev core operations */
2027static const struct v4l2_subdev_core_ops ccdc_v4l2_core_ops = {
2028 .ioctl = ccdc_ioctl,
2029 .subscribe_event = ccdc_subscribe_event,
2030 .unsubscribe_event = ccdc_unsubscribe_event,
2031};
2032
2033/* V4L2 subdev video operations */
2034static const struct v4l2_subdev_video_ops ccdc_v4l2_video_ops = {
2035 .s_stream = ccdc_set_stream,
2036};
2037
2038/* V4L2 subdev pad operations */
2039static const struct v4l2_subdev_pad_ops ccdc_v4l2_pad_ops = {
2040 .enum_mbus_code = ccdc_enum_mbus_code,
2041 .enum_frame_size = ccdc_enum_frame_size,
2042 .get_fmt = ccdc_get_format,
2043 .set_fmt = ccdc_set_format,
2044};
2045
2046/* V4L2 subdev operations */
2047static const struct v4l2_subdev_ops ccdc_v4l2_ops = {
2048 .core = &ccdc_v4l2_core_ops,
2049 .video = &ccdc_v4l2_video_ops,
2050 .pad = &ccdc_v4l2_pad_ops,
2051};
2052
2053/* V4L2 subdev internal operations */
2054static const struct v4l2_subdev_internal_ops ccdc_v4l2_internal_ops = {
2055 .open = ccdc_init_formats,
2056};
2057
2058/* -----------------------------------------------------------------------------
2059 * Media entity operations
2060 */
2061
2062/*
2063 * ccdc_link_setup - Setup CCDC connections
2064 * @entity: CCDC media entity
2065 * @local: Pad at the local end of the link
2066 * @remote: Pad at the remote end of the link
2067 * @flags: Link flags
2068 *
2069 * return -EINVAL or zero on success
2070 */
2071static int ccdc_link_setup(struct media_entity *entity,
2072 const struct media_pad *local,
2073 const struct media_pad *remote, u32 flags)
2074{
2075 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
2076 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
2077 struct isp_device *isp = to_isp_device(ccdc);
2078
2079 switch (local->index | media_entity_type(remote->entity)) {
2080 case CCDC_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
2081 /* Read from the sensor (parallel interface), CCP2, CSI2a or
2082 * CSI2c.
2083 */
2084 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
2085 ccdc->input = CCDC_INPUT_NONE;
2086 break;
2087 }
2088
2089 if (ccdc->input != CCDC_INPUT_NONE)
2090 return -EBUSY;
2091
2092 if (remote->entity == &isp->isp_ccp2.subdev.entity)
2093 ccdc->input = CCDC_INPUT_CCP2B;
2094 else if (remote->entity == &isp->isp_csi2a.subdev.entity)
2095 ccdc->input = CCDC_INPUT_CSI2A;
2096 else if (remote->entity == &isp->isp_csi2c.subdev.entity)
2097 ccdc->input = CCDC_INPUT_CSI2C;
2098 else
2099 ccdc->input = CCDC_INPUT_PARALLEL;
2100
2101 break;
2102
2103 /*
2104 * The ISP core doesn't support pipelines with multiple video outputs.
2105 * Revisit this when it will be implemented, and return -EBUSY for now.
2106 */
2107
2108 case CCDC_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV:
2109 /* Write to preview engine, histogram and H3A. When none of
2110 * those links are active, the video port can be disabled.
2111 */
2112 if (flags & MEDIA_LNK_FL_ENABLED) {
2113 if (ccdc->output & ~CCDC_OUTPUT_PREVIEW)
2114 return -EBUSY;
2115 ccdc->output |= CCDC_OUTPUT_PREVIEW;
2116 } else {
2117 ccdc->output &= ~CCDC_OUTPUT_PREVIEW;
2118 }
2119 break;
2120
2121 case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_DEVNODE:
2122 /* Write to memory */
2123 if (flags & MEDIA_LNK_FL_ENABLED) {
2124 if (ccdc->output & ~CCDC_OUTPUT_MEMORY)
2125 return -EBUSY;
2126 ccdc->output |= CCDC_OUTPUT_MEMORY;
2127 } else {
2128 ccdc->output &= ~CCDC_OUTPUT_MEMORY;
2129 }
2130 break;
2131
2132 case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_V4L2_SUBDEV:
2133 /* Write to resizer */
2134 if (flags & MEDIA_LNK_FL_ENABLED) {
2135 if (ccdc->output & ~CCDC_OUTPUT_RESIZER)
2136 return -EBUSY;
2137 ccdc->output |= CCDC_OUTPUT_RESIZER;
2138 } else {
2139 ccdc->output &= ~CCDC_OUTPUT_RESIZER;
2140 }
2141 break;
2142
2143 default:
2144 return -EINVAL;
2145 }
2146
2147 return 0;
2148}
2149
2150/* media operations */
2151static const struct media_entity_operations ccdc_media_ops = {
2152 .link_setup = ccdc_link_setup,
2153};
2154
2155void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
2156{
2157 v4l2_device_unregister_subdev(&ccdc->subdev);
2158 omap3isp_video_unregister(&ccdc->video_out);
2159}
2160
2161int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
2162 struct v4l2_device *vdev)
2163{
2164 int ret;
2165
2166 /* Register the subdev and video node. */
2167 ret = v4l2_device_register_subdev(vdev, &ccdc->subdev);
2168 if (ret < 0)
2169 goto error;
2170
2171 ret = omap3isp_video_register(&ccdc->video_out, vdev);
2172 if (ret < 0)
2173 goto error;
2174
2175 return 0;
2176
2177error:
2178 omap3isp_ccdc_unregister_entities(ccdc);
2179 return ret;
2180}
2181
2182/* -----------------------------------------------------------------------------
2183 * ISP CCDC initialisation and cleanup
2184 */
2185
2186/*
2187 * ccdc_init_entities - Initialize V4L2 subdev and media entity
2188 * @ccdc: ISP CCDC module
2189 *
2190 * Return 0 on success and a negative error code on failure.
2191 */
2192static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
2193{
2194 struct v4l2_subdev *sd = &ccdc->subdev;
2195 struct media_pad *pads = ccdc->pads;
2196 struct media_entity *me = &sd->entity;
2197 int ret;
2198
2199 ccdc->input = CCDC_INPUT_NONE;
2200
2201 v4l2_subdev_init(sd, &ccdc_v4l2_ops);
2202 sd->internal_ops = &ccdc_v4l2_internal_ops;
2203 strlcpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name));
2204 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
2205 v4l2_set_subdevdata(sd, ccdc);
2206 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
2207
2208 pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
2209 pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
2210 pads[CCDC_PAD_SOURCE_OF].flags = MEDIA_PAD_FL_SOURCE;
2211
2212 me->ops = &ccdc_media_ops;
2213 ret = media_entity_init(me, CCDC_PADS_NUM, pads, 0);
2214 if (ret < 0)
2215 return ret;
2216
2217 ccdc_init_formats(sd, NULL);
2218
2219 ccdc->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2220 ccdc->video_out.ops = &ccdc_video_ops;
2221 ccdc->video_out.isp = to_isp_device(ccdc);
2222 ccdc->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
2223 ccdc->video_out.bpl_alignment = 32;
2224
2225 ret = omap3isp_video_init(&ccdc->video_out, "CCDC");
2226 if (ret < 0)
2227 goto error_video;
2228
2229 /* Connect the CCDC subdev to the video node. */
2230 ret = media_entity_create_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
2231 &ccdc->video_out.video.entity, 0, 0);
2232 if (ret < 0)
2233 goto error_link;
2234
2235 return 0;
2236
2237error_link:
2238 omap3isp_video_cleanup(&ccdc->video_out);
2239error_video:
2240 media_entity_cleanup(me);
2241 return ret;
2242}
2243
2244/*
2245 * omap3isp_ccdc_init - CCDC module initialization.
2246 * @dev: Device pointer specific to the OMAP3 ISP.
2247 *
2248 * TODO: Get the initialisation values from platform data.
2249 *
2250 * Return 0 on success or a negative error code otherwise.
2251 */
2252int omap3isp_ccdc_init(struct isp_device *isp)
2253{
2254 struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
2255 int ret;
2256
2257 spin_lock_init(&ccdc->lock);
2258 init_waitqueue_head(&ccdc->wait);
2259 mutex_init(&ccdc->ioctl_lock);
2260
2261 ccdc->stopping = CCDC_STOP_NOT_REQUESTED;
2262
2263 INIT_WORK(&ccdc->lsc.table_work, ccdc_lsc_free_table_work);
2264 ccdc->lsc.state = LSC_STATE_STOPPED;
2265 INIT_LIST_HEAD(&ccdc->lsc.free_queue);
2266 spin_lock_init(&ccdc->lsc.req_lock);
2267
2268 ccdc->syncif.ccdc_mastermode = 0;
2269 ccdc->syncif.datapol = 0;
2270 ccdc->syncif.datsz = 0;
2271 ccdc->syncif.fldmode = 0;
2272 ccdc->syncif.fldout = 0;
2273 ccdc->syncif.fldpol = 0;
2274 ccdc->syncif.fldstat = 0;
2275
2276 ccdc->clamp.oblen = 0;
2277 ccdc->clamp.dcsubval = 0;
2278
2279 ccdc->vpcfg.pixelclk = 0;
2280
2281 ccdc->update = OMAP3ISP_CCDC_BLCLAMP;
2282 ccdc_apply_controls(ccdc);
2283
2284 ret = ccdc_init_entities(ccdc);
2285 if (ret < 0) {
2286 mutex_destroy(&ccdc->ioctl_lock);
2287 return ret;
2288 }
2289
2290 return 0;
2291}
2292
2293/*
2294 * omap3isp_ccdc_cleanup - CCDC module cleanup.
2295 * @dev: Device pointer specific to the OMAP3 ISP.
2296 */
2297void omap3isp_ccdc_cleanup(struct isp_device *isp)
2298{
2299 struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
2300
2301 omap3isp_video_cleanup(&ccdc->video_out);
2302 media_entity_cleanup(&ccdc->subdev.entity);
2303
2304 /* Free LSC requests. As the CCDC is stopped there's no active request,
2305 * so only the pending request and the free queue need to be handled.
2306 */
2307 ccdc_lsc_free_request(ccdc, ccdc->lsc.request);
2308 cancel_work_sync(&ccdc->lsc.table_work);
2309 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
2310
2311 if (ccdc->fpc.fpcaddr != 0)
2312 omap_iommu_vfree(isp->domain, isp->dev, ccdc->fpc.fpcaddr);
2313
2314 mutex_destroy(&ccdc->ioctl_lock);
2315}
diff --git a/drivers/media/video/omap3isp/ispccdc.h b/drivers/media/video/omap3isp/ispccdc.h
new file mode 100644
index 00000000000..483a19cac1a
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispccdc.h
@@ -0,0 +1,219 @@
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
49/*
50 * struct ispccdc_syncif - Structure for Sync Interface between sensor and CCDC
51 * @ccdc_mastermode: Master mode. 1 - Master, 0 - Slave.
52 * @fldstat: Field state. 0 - Odd Field, 1 - Even Field.
53 * @datsz: Data size.
54 * @fldmode: 0 - Progressive, 1 - Interlaced.
55 * @datapol: 0 - Positive, 1 - Negative.
56 * @fldpol: 0 - Positive, 1 - Negative.
57 * @hdpol: 0 - Positive, 1 - Negative.
58 * @vdpol: 0 - Positive, 1 - Negative.
59 * @fldout: 0 - Input, 1 - Output.
60 * @hs_width: Width of the Horizontal Sync pulse, used for HS/VS Output.
61 * @vs_width: Width of the Vertical Sync pulse, used for HS/VS Output.
62 * @ppln: Number of pixels per line, used for HS/VS Output.
63 * @hlprf: Number of half lines per frame, used for HS/VS Output.
64 * @bt_r656_en: 1 - Enable ITU-R BT656 mode, 0 - Sync mode.
65 */
66struct ispccdc_syncif {
67 u8 ccdc_mastermode;
68 u8 fldstat;
69 u8 datsz;
70 u8 fldmode;
71 u8 datapol;
72 u8 fldpol;
73 u8 hdpol;
74 u8 vdpol;
75 u8 fldout;
76 u8 hs_width;
77 u8 vs_width;
78 u8 ppln;
79 u8 hlprf;
80 u8 bt_r656_en;
81};
82
83/*
84 * struct ispccdc_vp - Structure for Video Port parameters
85 * @pixelclk: Input pixel clock in Hz
86 */
87struct ispccdc_vp {
88 unsigned int pixelclk;
89};
90
91enum ispccdc_lsc_state {
92 LSC_STATE_STOPPED = 0,
93 LSC_STATE_STOPPING = 1,
94 LSC_STATE_RUNNING = 2,
95 LSC_STATE_RECONFIG = 3,
96};
97
98struct ispccdc_lsc_config_req {
99 struct list_head list;
100 struct omap3isp_ccdc_lsc_config config;
101 unsigned char enable;
102 u32 table;
103 struct iovm_struct *iovm;
104};
105
106/*
107 * ispccdc_lsc - CCDC LSC parameters
108 * @update_config: Set when user changes config
109 * @request_enable: Whether LSC is requested to be enabled
110 * @config: LSC config set by user
111 * @update_table: Set when user provides a new LSC table to table_new
112 * @table_new: LSC table set by user, ISP address
113 * @table_inuse: LSC table currently in use, ISP address
114 */
115struct ispccdc_lsc {
116 enum ispccdc_lsc_state state;
117 struct work_struct table_work;
118
119 /* LSC queue of configurations */
120 spinlock_t req_lock;
121 struct ispccdc_lsc_config_req *request; /* requested configuration */
122 struct ispccdc_lsc_config_req *active; /* active configuration */
123 struct list_head free_queue; /* configurations for freeing */
124};
125
126#define CCDC_STOP_NOT_REQUESTED 0x00
127#define CCDC_STOP_REQUEST 0x01
128#define CCDC_STOP_EXECUTED (0x02 | CCDC_STOP_REQUEST)
129#define CCDC_STOP_CCDC_FINISHED 0x04
130#define CCDC_STOP_LSC_FINISHED 0x08
131#define CCDC_STOP_FINISHED \
132 (CCDC_STOP_EXECUTED | CCDC_STOP_CCDC_FINISHED | CCDC_STOP_LSC_FINISHED)
133
134#define CCDC_EVENT_VD1 0x10
135#define CCDC_EVENT_VD0 0x20
136#define CCDC_EVENT_LSC_DONE 0x40
137
138/* Sink and source CCDC pads */
139#define CCDC_PAD_SINK 0
140#define CCDC_PAD_SOURCE_OF 1
141#define CCDC_PAD_SOURCE_VP 2
142#define CCDC_PADS_NUM 3
143
144/*
145 * struct isp_ccdc_device - Structure for the CCDC module to store its own
146 * information
147 * @subdev: V4L2 subdevice
148 * @pads: Sink and source media entity pads
149 * @formats: Active video formats
150 * @input: Active input
151 * @output: Active outputs
152 * @video_out: Output video node
153 * @error: A hardware error occurred during capture
154 * @alaw: A-law compression enabled (1) or disabled (0)
155 * @lpf: Low pass filter enabled (1) or disabled (0)
156 * @obclamp: Optical-black clamp enabled (1) or disabled (0)
157 * @fpc_en: Faulty pixels correction enabled (1) or disabled (0)
158 * @blcomp: Black level compensation configuration
159 * @clamp: Optical-black or digital clamp configuration
160 * @fpc: Faulty pixels correction configuration
161 * @lsc: Lens shading compensation configuration
162 * @update: Bitmask of controls to update during the next interrupt
163 * @shadow_update: Controls update in progress by userspace
164 * @syncif: Interface synchronization configuration
165 * @vpcfg: Video port configuration
166 * @underrun: A buffer underrun occurred and a new buffer has been queued
167 * @state: Streaming state
168 * @lock: Serializes shadow_update with interrupt handler
169 * @wait: Wait queue used to stop the module
170 * @stopping: Stopping state
171 * @ioctl_lock: Serializes ioctl calls and LSC requests freeing
172 */
173struct isp_ccdc_device {
174 struct v4l2_subdev subdev;
175 struct media_pad pads[CCDC_PADS_NUM];
176 struct v4l2_mbus_framefmt formats[CCDC_PADS_NUM];
177
178 enum ccdc_input_entity input;
179 unsigned int output;
180 struct isp_video video_out;
181 unsigned int error;
182
183 unsigned int alaw:1,
184 lpf:1,
185 obclamp:1,
186 fpc_en:1;
187 struct omap3isp_ccdc_blcomp blcomp;
188 struct omap3isp_ccdc_bclamp clamp;
189 struct omap3isp_ccdc_fpc fpc;
190 struct ispccdc_lsc lsc;
191 unsigned int update;
192 unsigned int shadow_update;
193
194 struct ispccdc_syncif syncif;
195 struct ispccdc_vp vpcfg;
196
197 unsigned int underrun:1;
198 enum isp_pipeline_stream_state state;
199 spinlock_t lock;
200 wait_queue_head_t wait;
201 unsigned int stopping;
202 struct mutex ioctl_lock;
203};
204
205struct isp_device;
206
207int omap3isp_ccdc_init(struct isp_device *isp);
208void omap3isp_ccdc_cleanup(struct isp_device *isp);
209int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
210 struct v4l2_device *vdev);
211void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc);
212
213int omap3isp_ccdc_busy(struct isp_ccdc_device *isp_ccdc);
214int omap3isp_ccdc_isr(struct isp_ccdc_device *isp_ccdc, u32 events);
215void omap3isp_ccdc_restore_context(struct isp_device *isp);
216void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
217 unsigned int *max_rate);
218
219#endif /* OMAP3_ISP_CCDC_H */
diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c
new file mode 100644
index 00000000000..ec9e395f333
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispccp2.c
@@ -0,0 +1,1196 @@
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 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
165 int i;
166
167 if (enable && ccp2->vdds_csib)
168 regulator_enable(ccp2->vdds_csib);
169
170 /* Enable/Disable all the LCx channels */
171 for (i = 0; i < CCP2_LCx_CHANS_NUM; i++)
172 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i),
173 ISPCCP2_LCx_CTRL_CHAN_EN,
174 enable ? ISPCCP2_LCx_CTRL_CHAN_EN : 0);
175
176 /* Enable/Disable ccp2 interface in ccp2 mode */
177 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
178 ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN,
179 enable ? (ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN) : 0);
180
181 /* For frame count propagation */
182 if (pipe->do_propagation) {
183 /* We may want the Frame Start IRQ from LC0 */
184 if (enable)
185 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2,
186 ISPCCP2_LC01_IRQENABLE,
187 ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ);
188 else
189 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCP2,
190 ISPCCP2_LC01_IRQENABLE,
191 ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ);
192 }
193
194 if (!enable && ccp2->vdds_csib)
195 regulator_disable(ccp2->vdds_csib);
196}
197
198/*
199 * ccp2_mem_enable - Enable CCP2 memory interface.
200 * @ccp2: pointer to ISP CCP2 device
201 * @enable: enable/disable flag
202 */
203static void ccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable)
204{
205 struct isp_device *isp = to_isp_device(ccp2);
206
207 if (enable)
208 ccp2_if_enable(ccp2, 0);
209
210 /* Enable/Disable ccp2 interface in ccp2 mode */
211 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
212 ISPCCP2_CTRL_MODE, enable ? ISPCCP2_CTRL_MODE : 0);
213
214 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL,
215 ISPCCP2_LCM_CTRL_CHAN_EN,
216 enable ? ISPCCP2_LCM_CTRL_CHAN_EN : 0);
217}
218
219/*
220 * ccp2_phyif_config - Initialize CCP2 phy interface config
221 * @ccp2: Pointer to ISP CCP2 device
222 * @config: CCP2 platform data
223 *
224 * Configure the CCP2 physical interface module from platform data.
225 *
226 * Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success.
227 */
228static int ccp2_phyif_config(struct isp_ccp2_device *ccp2,
229 const struct isp_ccp2_platform_data *pdata)
230{
231 struct isp_device *isp = to_isp_device(ccp2);
232 u32 val;
233
234 /* CCP2B mode */
235 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL) |
236 ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE;
237 /* Data/strobe physical layer */
238 BIT_SET(val, ISPCCP2_CTRL_PHY_SEL_SHIFT, ISPCCP2_CTRL_PHY_SEL_MASK,
239 pdata->phy_layer);
240 BIT_SET(val, ISPCCP2_CTRL_INV_SHIFT, ISPCCP2_CTRL_INV_MASK,
241 pdata->strobe_clk_pol);
242 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
243
244 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
245 if (!(val & ISPCCP2_CTRL_MODE)) {
246 if (pdata->ccp2_mode)
247 dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");
248 if (pdata->phy_layer == ISPCCP2_CTRL_PHY_SEL_STROBE)
249 /* Strobe mode requires CCP2 */
250 return -EIO;
251 }
252
253 return 0;
254}
255
256/*
257 * ccp2_vp_config - Initialize CCP2 video port interface.
258 * @ccp2: Pointer to ISP CCP2 device
259 * @vpclk_div: Video port divisor
260 *
261 * Configure the CCP2 video port with the given clock divisor. The valid divisor
262 * values depend on the ISP revision:
263 *
264 * - revision 1.0 and 2.0 1 to 4
265 * - revision 15.0 1 to 65536
266 *
267 * The exact divisor value used might differ from the requested value, as ISP
268 * revision 15.0 represent the divisor by 65536 divided by an integer.
269 */
270static void ccp2_vp_config(struct isp_ccp2_device *ccp2,
271 unsigned int vpclk_div)
272{
273 struct isp_device *isp = to_isp_device(ccp2);
274 u32 val;
275
276 /* ISPCCP2_CTRL Video port */
277 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
278 val |= ISPCCP2_CTRL_VP_ONLY_EN; /* Disable the memory write port */
279
280 if (isp->revision == ISP_REVISION_15_0) {
281 vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 65536);
282 vpclk_div = min(ISPCCP2_VPCLK_FRACDIV / vpclk_div, 65535U);
283 BIT_SET(val, ISPCCP2_CTRL_VPCLK_DIV_SHIFT,
284 ISPCCP2_CTRL_VPCLK_DIV_MASK, vpclk_div);
285 } else {
286 vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 4);
287 BIT_SET(val, ISPCCP2_CTRL_VP_OUT_CTRL_SHIFT,
288 ISPCCP2_CTRL_VP_OUT_CTRL_MASK, vpclk_div - 1);
289 }
290
291 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
292}
293
294/*
295 * ccp2_lcx_config - Initialize CCP2 logical channel interface.
296 * @ccp2: Pointer to ISP CCP2 device
297 * @config: Pointer to ISP LCx config structure.
298 *
299 * This will analyze the parameters passed by the interface config
300 * and configure CSI1/CCP2 logical channel
301 *
302 */
303static void ccp2_lcx_config(struct isp_ccp2_device *ccp2,
304 struct isp_interface_lcx_config *config)
305{
306 struct isp_device *isp = to_isp_device(ccp2);
307 u32 val, format;
308
309 switch (config->format) {
310 case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
311 format = ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP;
312 break;
313 case V4L2_MBUS_FMT_SGRBG10_1X10:
314 default:
315 format = ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP; /* RAW10+VP */
316 break;
317 }
318 /* ISPCCP2_LCx_CTRL logical channel #0 */
319 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0))
320 | (ISPCCP2_LCx_CTRL_REGION_EN); /* Region */
321
322 if (isp->revision == ISP_REVISION_15_0) {
323 /* CRC */
324 BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT_15_0,
325 ISPCCP2_LCx_CTRL_CRC_MASK,
326 config->crc);
327 /* Format = RAW10+VP or RAW8+DPCM10+VP*/
328 BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT_15_0,
329 ISPCCP2_LCx_CTRL_FORMAT_MASK_15_0, format);
330 } else {
331 BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT,
332 ISPCCP2_LCx_CTRL_CRC_MASK,
333 config->crc);
334
335 BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT,
336 ISPCCP2_LCx_CTRL_FORMAT_MASK, format);
337 }
338 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0));
339
340 /* ISPCCP2_DAT_START for logical channel #0 */
341 isp_reg_writel(isp, config->data_start << ISPCCP2_LCx_DAT_SHIFT,
342 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_START(0));
343
344 /* ISPCCP2_DAT_SIZE for logical channel #0 */
345 isp_reg_writel(isp, config->data_size << ISPCCP2_LCx_DAT_SHIFT,
346 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_SIZE(0));
347
348 /* Enable error IRQs for logical channel #0 */
349 val = ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
350 ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
351 ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |
352 ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |
353 ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ |
354 ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |
355 ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;
356
357 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQSTATUS);
358 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, val);
359}
360
361/*
362 * ccp2_if_configure - Configure ccp2 with data from sensor
363 * @ccp2: Pointer to ISP CCP2 device
364 *
365 * Return 0 on success or a negative error code
366 */
367static int ccp2_if_configure(struct isp_ccp2_device *ccp2)
368{
369 const struct isp_v4l2_subdevs_group *pdata;
370 struct v4l2_mbus_framefmt *format;
371 struct media_pad *pad;
372 struct v4l2_subdev *sensor;
373 u32 lines = 0;
374 int ret;
375
376 ccp2_pwr_cfg(ccp2);
377
378 pad = media_entity_remote_source(&ccp2->pads[CCP2_PAD_SINK]);
379 sensor = media_entity_to_v4l2_subdev(pad->entity);
380 pdata = sensor->host_priv;
381
382 ret = ccp2_phyif_config(ccp2, &pdata->bus.ccp2);
383 if (ret < 0)
384 return ret;
385
386 ccp2_vp_config(ccp2, pdata->bus.ccp2.vpclk_div + 1);
387
388 v4l2_subdev_call(sensor, sensor, g_skip_top_lines, &lines);
389
390 format = &ccp2->formats[CCP2_PAD_SINK];
391
392 ccp2->if_cfg.data_start = lines;
393 ccp2->if_cfg.crc = pdata->bus.ccp2.crc;
394 ccp2->if_cfg.format = format->code;
395 ccp2->if_cfg.data_size = format->height;
396
397 ccp2_lcx_config(ccp2, &ccp2->if_cfg);
398
399 return 0;
400}
401
402static int ccp2_adjust_bandwidth(struct isp_ccp2_device *ccp2)
403{
404 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
405 struct isp_device *isp = to_isp_device(ccp2);
406 const struct v4l2_mbus_framefmt *ofmt = &ccp2->formats[CCP2_PAD_SOURCE];
407 unsigned long l3_ick = pipe->l3_ick;
408 struct v4l2_fract *timeperframe;
409 unsigned int vpclk_div = 2;
410 unsigned int value;
411 u64 bound;
412 u64 area;
413
414 /* Compute the minimum clock divisor, based on the pipeline maximum
415 * data rate. This is an absolute lower bound if we don't want SBL
416 * overflows, so round the value up.
417 */
418 vpclk_div = max_t(unsigned int, DIV_ROUND_UP(l3_ick, pipe->max_rate),
419 vpclk_div);
420
421 /* Compute the maximum clock divisor, based on the requested frame rate.
422 * This is a soft lower bound to achieve a frame rate equal or higher
423 * than the requested value, so round the value down.
424 */
425 timeperframe = &pipe->max_timeperframe;
426
427 if (timeperframe->numerator) {
428 area = ofmt->width * ofmt->height;
429 bound = div_u64(area * timeperframe->denominator,
430 timeperframe->numerator);
431 value = min_t(u64, bound, l3_ick);
432 vpclk_div = max_t(unsigned int, l3_ick / value, vpclk_div);
433 }
434
435 dev_dbg(isp->dev, "%s: minimum clock divisor = %u\n", __func__,
436 vpclk_div);
437
438 return vpclk_div;
439}
440
441/*
442 * ccp2_mem_configure - Initialize CCP2 memory input/output interface
443 * @ccp2: Pointer to ISP CCP2 device
444 * @config: Pointer to ISP mem interface config structure
445 *
446 * This will analyze the parameters passed by the interface config
447 * structure, and configure the respective registers for proper
448 * CSI1/CCP2 memory input.
449 */
450static void ccp2_mem_configure(struct isp_ccp2_device *ccp2,
451 struct isp_interface_mem_config *config)
452{
453 struct isp_device *isp = to_isp_device(ccp2);
454 u32 sink_pixcode = ccp2->formats[CCP2_PAD_SINK].code;
455 u32 source_pixcode = ccp2->formats[CCP2_PAD_SOURCE].code;
456 unsigned int dpcm_decompress = 0;
457 u32 val, hwords;
458
459 if (sink_pixcode != source_pixcode &&
460 sink_pixcode == V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
461 dpcm_decompress = 1;
462
463 ccp2_pwr_cfg(ccp2);
464
465 /* Hsize, Skip */
466 isp_reg_writel(isp, ISPCCP2_LCM_HSIZE_SKIP_MIN |
467 (config->hsize_count << ISPCCP2_LCM_HSIZE_SHIFT),
468 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_HSIZE);
469
470 /* Vsize, no. of lines */
471 isp_reg_writel(isp, config->vsize_count << ISPCCP2_LCM_VSIZE_SHIFT,
472 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_VSIZE);
473
474 if (ccp2->video_in.bpl_padding == 0)
475 config->src_ofst = 0;
476 else
477 config->src_ofst = ccp2->video_in.bpl_value;
478
479 isp_reg_writel(isp, config->src_ofst, OMAP3_ISP_IOMEM_CCP2,
480 ISPCCP2_LCM_SRC_OFST);
481
482 /* Source and Destination formats */
483 val = ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10 <<
484 ISPCCP2_LCM_CTRL_DST_FORMAT_SHIFT;
485
486 if (dpcm_decompress) {
487 /* source format is RAW8 */
488 val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8 <<
489 ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;
490
491 /* RAW8 + DPCM10 - simple predictor */
492 val |= ISPCCP2_LCM_CTRL_SRC_DPCM_PRED;
493
494 /* enable source DPCM decompression */
495 val |= ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10 <<
496 ISPCCP2_LCM_CTRL_SRC_DECOMPR_SHIFT;
497 } else {
498 /* source format is RAW10 */
499 val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10 <<
500 ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;
501 }
502
503 /* Burst size to 32x64 */
504 val |= ISPCCP2_LCM_CTRL_BURST_SIZE_32X <<
505 ISPCCP2_LCM_CTRL_BURST_SIZE_SHIFT;
506
507 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL);
508
509 /* Prefetch setup */
510 if (dpcm_decompress)
511 hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +
512 config->hsize_count) >> 3;
513 else
514 hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +
515 config->hsize_count) >> 2;
516
517 isp_reg_writel(isp, hwords << ISPCCP2_LCM_PREFETCH_SHIFT,
518 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_PREFETCH);
519
520 /* Video port */
521 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
522 ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE);
523 ccp2_vp_config(ccp2, ccp2_adjust_bandwidth(ccp2));
524
525 /* Clear LCM interrupts */
526 isp_reg_writel(isp, ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ |
527 ISPCCP2_LCM_IRQSTATUS_EOF_IRQ,
528 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQSTATUS);
529
530 /* Enable LCM interupts */
531 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQENABLE,
532 ISPCCP2_LCM_IRQSTATUS_EOF_IRQ |
533 ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ);
534}
535
536/*
537 * ccp2_set_inaddr - Sets memory address of input frame.
538 * @ccp2: Pointer to ISP CCP2 device
539 * @addr: 32bit memory address aligned on 32byte boundary.
540 *
541 * Configures the memory address from which the input frame is to be read.
542 */
543static void ccp2_set_inaddr(struct isp_ccp2_device *ccp2, u32 addr)
544{
545 struct isp_device *isp = to_isp_device(ccp2);
546
547 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_SRC_ADDR);
548}
549
550/* -----------------------------------------------------------------------------
551 * Interrupt handling
552 */
553
554static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
555{
556 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
557 struct isp_buffer *buffer;
558
559 buffer = omap3isp_video_buffer_next(&ccp2->video_in, ccp2->error);
560 if (buffer != NULL)
561 ccp2_set_inaddr(ccp2, buffer->isp_addr);
562
563 pipe->state |= ISP_PIPELINE_IDLE_INPUT;
564
565 if (ccp2->state == ISP_PIPELINE_STREAM_SINGLESHOT) {
566 if (isp_pipeline_ready(pipe))
567 omap3isp_pipeline_set_stream(pipe,
568 ISP_PIPELINE_STREAM_SINGLESHOT);
569 }
570
571 ccp2->error = 0;
572}
573
574/*
575 * omap3isp_ccp2_isr - Handle ISP CCP2 interrupts
576 * @ccp2: Pointer to ISP CCP2 device
577 *
578 * This will handle the CCP2 interrupts
579 *
580 * Returns -EIO in case of error, or 0 on success.
581 */
582int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
583{
584 struct isp_device *isp = to_isp_device(ccp2);
585 int ret = 0;
586 static const u32 ISPCCP2_LC01_ERROR =
587 ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
588 ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
589 ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |
590 ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |
591 ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |
592 ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;
593 u32 lcx_irqstatus, lcm_irqstatus;
594
595 /* First clear the interrupts */
596 lcx_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,
597 ISPCCP2_LC01_IRQSTATUS);
598 isp_reg_writel(isp, lcx_irqstatus, OMAP3_ISP_IOMEM_CCP2,
599 ISPCCP2_LC01_IRQSTATUS);
600
601 lcm_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,
602 ISPCCP2_LCM_IRQSTATUS);
603 isp_reg_writel(isp, lcm_irqstatus, OMAP3_ISP_IOMEM_CCP2,
604 ISPCCP2_LCM_IRQSTATUS);
605 /* Errors */
606 if (lcx_irqstatus & ISPCCP2_LC01_ERROR) {
607 ccp2->error = 1;
608 dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus);
609 return -EIO;
610 }
611
612 if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) {
613 ccp2->error = 1;
614 dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus);
615 ret = -EIO;
616 }
617
618 if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping))
619 return 0;
620
621 /* Frame number propagation */
622 if (lcx_irqstatus & ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ) {
623 struct isp_pipeline *pipe =
624 to_isp_pipeline(&ccp2->subdev.entity);
625 if (pipe->do_propagation)
626 atomic_inc(&pipe->frame_number);
627 }
628
629 /* Handle queued buffers on frame end interrupts */
630 if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ)
631 ccp2_isr_buffer(ccp2);
632
633 return ret;
634}
635
636/* -----------------------------------------------------------------------------
637 * V4L2 subdev operations
638 */
639
640static const unsigned int ccp2_fmts[] = {
641 V4L2_MBUS_FMT_SGRBG10_1X10,
642 V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
643};
644
645/*
646 * __ccp2_get_format - helper function for getting ccp2 format
647 * @ccp2 : Pointer to ISP CCP2 device
648 * @fh : V4L2 subdev file handle
649 * @pad : pad number
650 * @which : wanted subdev format
651 * return format structure or NULL on error
652 */
653static struct v4l2_mbus_framefmt *
654__ccp2_get_format(struct isp_ccp2_device *ccp2, struct v4l2_subdev_fh *fh,
655 unsigned int pad, enum v4l2_subdev_format_whence which)
656{
657 if (which == V4L2_SUBDEV_FORMAT_TRY)
658 return v4l2_subdev_get_try_format(fh, pad);
659 else
660 return &ccp2->formats[pad];
661}
662
663/*
664 * ccp2_try_format - Handle try format by pad subdev method
665 * @ccp2 : Pointer to ISP CCP2 device
666 * @fh : V4L2 subdev file handle
667 * @pad : pad num
668 * @fmt : pointer to v4l2 mbus format structure
669 * @which : wanted subdev format
670 */
671static void ccp2_try_format(struct isp_ccp2_device *ccp2,
672 struct v4l2_subdev_fh *fh, unsigned int pad,
673 struct v4l2_mbus_framefmt *fmt,
674 enum v4l2_subdev_format_whence which)
675{
676 struct v4l2_mbus_framefmt *format;
677
678 switch (pad) {
679 case CCP2_PAD_SINK:
680 if (fmt->code != V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
681 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
682
683 if (ccp2->input == CCP2_INPUT_SENSOR) {
684 fmt->width = clamp_t(u32, fmt->width,
685 ISPCCP2_DAT_START_MIN,
686 ISPCCP2_DAT_START_MAX);
687 fmt->height = clamp_t(u32, fmt->height,
688 ISPCCP2_DAT_SIZE_MIN,
689 ISPCCP2_DAT_SIZE_MAX);
690 } else if (ccp2->input == CCP2_INPUT_MEMORY) {
691 fmt->width = clamp_t(u32, fmt->width,
692 ISPCCP2_LCM_HSIZE_COUNT_MIN,
693 ISPCCP2_LCM_HSIZE_COUNT_MAX);
694 fmt->height = clamp_t(u32, fmt->height,
695 ISPCCP2_LCM_VSIZE_MIN,
696 ISPCCP2_LCM_VSIZE_MAX);
697 }
698 break;
699
700 case CCP2_PAD_SOURCE:
701 /* Source format - copy sink format and change pixel code
702 * to SGRBG10_1X10 as we don't support CCP2 write to memory.
703 * When CCP2 write to memory feature will be added this
704 * should be changed properly.
705 */
706 format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK, which);
707 memcpy(fmt, format, sizeof(*fmt));
708 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
709 break;
710 }
711
712 fmt->field = V4L2_FIELD_NONE;
713 fmt->colorspace = V4L2_COLORSPACE_SRGB;
714}
715
716/*
717 * ccp2_enum_mbus_code - Handle pixel format enumeration
718 * @sd : pointer to v4l2 subdev structure
719 * @fh : V4L2 subdev file handle
720 * @code : pointer to v4l2_subdev_mbus_code_enum structure
721 * return -EINVAL or zero on success
722 */
723static int ccp2_enum_mbus_code(struct v4l2_subdev *sd,
724 struct v4l2_subdev_fh *fh,
725 struct v4l2_subdev_mbus_code_enum *code)
726{
727 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
728 struct v4l2_mbus_framefmt *format;
729
730 if (code->pad == CCP2_PAD_SINK) {
731 if (code->index >= ARRAY_SIZE(ccp2_fmts))
732 return -EINVAL;
733
734 code->code = ccp2_fmts[code->index];
735 } else {
736 if (code->index != 0)
737 return -EINVAL;
738
739 format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK,
740 V4L2_SUBDEV_FORMAT_TRY);
741 code->code = format->code;
742 }
743
744 return 0;
745}
746
747static int ccp2_enum_frame_size(struct v4l2_subdev *sd,
748 struct v4l2_subdev_fh *fh,
749 struct v4l2_subdev_frame_size_enum *fse)
750{
751 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
752 struct v4l2_mbus_framefmt format;
753
754 if (fse->index != 0)
755 return -EINVAL;
756
757 format.code = fse->code;
758 format.width = 1;
759 format.height = 1;
760 ccp2_try_format(ccp2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
761 fse->min_width = format.width;
762 fse->min_height = format.height;
763
764 if (format.code != fse->code)
765 return -EINVAL;
766
767 format.code = fse->code;
768 format.width = -1;
769 format.height = -1;
770 ccp2_try_format(ccp2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
771 fse->max_width = format.width;
772 fse->max_height = format.height;
773
774 return 0;
775}
776
777/*
778 * ccp2_get_format - Handle get format by pads subdev method
779 * @sd : pointer to v4l2 subdev structure
780 * @fh : V4L2 subdev file handle
781 * @fmt : pointer to v4l2 subdev format structure
782 * return -EINVAL or zero on success
783 */
784static int ccp2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
785 struct v4l2_subdev_format *fmt)
786{
787 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
788 struct v4l2_mbus_framefmt *format;
789
790 format = __ccp2_get_format(ccp2, fh, fmt->pad, fmt->which);
791 if (format == NULL)
792 return -EINVAL;
793
794 fmt->format = *format;
795 return 0;
796}
797
798/*
799 * ccp2_set_format - Handle set format by pads subdev method
800 * @sd : pointer to v4l2 subdev structure
801 * @fh : V4L2 subdev file handle
802 * @fmt : pointer to v4l2 subdev format structure
803 * returns zero
804 */
805static int ccp2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
806 struct v4l2_subdev_format *fmt)
807{
808 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
809 struct v4l2_mbus_framefmt *format;
810
811 format = __ccp2_get_format(ccp2, fh, fmt->pad, fmt->which);
812 if (format == NULL)
813 return -EINVAL;
814
815 ccp2_try_format(ccp2, fh, fmt->pad, &fmt->format, fmt->which);
816 *format = fmt->format;
817
818 /* Propagate the format from sink to source */
819 if (fmt->pad == CCP2_PAD_SINK) {
820 format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SOURCE,
821 fmt->which);
822 *format = fmt->format;
823 ccp2_try_format(ccp2, fh, CCP2_PAD_SOURCE, format, fmt->which);
824 }
825
826 return 0;
827}
828
829/*
830 * ccp2_init_formats - Initialize formats on all pads
831 * @sd: ISP CCP2 V4L2 subdevice
832 * @fh: V4L2 subdev file handle
833 *
834 * Initialize all pad formats with default values. If fh is not NULL, try
835 * formats are initialized on the file handle. Otherwise active formats are
836 * initialized on the device.
837 */
838static int ccp2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
839{
840 struct v4l2_subdev_format format;
841
842 memset(&format, 0, sizeof(format));
843 format.pad = CCP2_PAD_SINK;
844 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
845 format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
846 format.format.width = 4096;
847 format.format.height = 4096;
848 ccp2_set_format(sd, fh, &format);
849
850 return 0;
851}
852
853/*
854 * ccp2_s_stream - Enable/Disable streaming on ccp2 subdev
855 * @sd : pointer to v4l2 subdev structure
856 * @enable: 1 == Enable, 0 == Disable
857 * return zero
858 */
859static int ccp2_s_stream(struct v4l2_subdev *sd, int enable)
860{
861 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
862 struct isp_device *isp = to_isp_device(ccp2);
863 struct device *dev = to_device(ccp2);
864 int ret;
865
866 if (ccp2->state == ISP_PIPELINE_STREAM_STOPPED) {
867 if (enable == ISP_PIPELINE_STREAM_STOPPED)
868 return 0;
869 atomic_set(&ccp2->stopping, 0);
870 ccp2->error = 0;
871 }
872
873 switch (enable) {
874 case ISP_PIPELINE_STREAM_CONTINUOUS:
875 if (ccp2->phy) {
876 ret = omap3isp_csiphy_acquire(ccp2->phy);
877 if (ret < 0)
878 return ret;
879 }
880
881 ccp2_if_configure(ccp2);
882 ccp2_print_status(ccp2);
883
884 /* Enable CSI1/CCP2 interface */
885 ccp2_if_enable(ccp2, 1);
886 break;
887
888 case ISP_PIPELINE_STREAM_SINGLESHOT:
889 if (ccp2->state != ISP_PIPELINE_STREAM_SINGLESHOT) {
890 struct v4l2_mbus_framefmt *format;
891
892 format = &ccp2->formats[CCP2_PAD_SINK];
893
894 ccp2->mem_cfg.hsize_count = format->width;
895 ccp2->mem_cfg.vsize_count = format->height;
896 ccp2->mem_cfg.src_ofst = 0;
897
898 ccp2_mem_configure(ccp2, &ccp2->mem_cfg);
899 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI1_READ);
900 ccp2_print_status(ccp2);
901 }
902 ccp2_mem_enable(ccp2, 1);
903 break;
904
905 case ISP_PIPELINE_STREAM_STOPPED:
906 if (omap3isp_module_sync_idle(&sd->entity, &ccp2->wait,
907 &ccp2->stopping))
908 dev_dbg(dev, "%s: module stop timeout.\n", sd->name);
909 if (ccp2->input == CCP2_INPUT_MEMORY) {
910 ccp2_mem_enable(ccp2, 0);
911 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI1_READ);
912 } else if (ccp2->input == CCP2_INPUT_SENSOR) {
913 /* Disable CSI1/CCP2 interface */
914 ccp2_if_enable(ccp2, 0);
915 if (ccp2->phy)
916 omap3isp_csiphy_release(ccp2->phy);
917 }
918 break;
919 }
920
921 ccp2->state = enable;
922 return 0;
923}
924
925/* subdev video operations */
926static const struct v4l2_subdev_video_ops ccp2_sd_video_ops = {
927 .s_stream = ccp2_s_stream,
928};
929
930/* subdev pad operations */
931static const struct v4l2_subdev_pad_ops ccp2_sd_pad_ops = {
932 .enum_mbus_code = ccp2_enum_mbus_code,
933 .enum_frame_size = ccp2_enum_frame_size,
934 .get_fmt = ccp2_get_format,
935 .set_fmt = ccp2_set_format,
936};
937
938/* subdev operations */
939static const struct v4l2_subdev_ops ccp2_sd_ops = {
940 .video = &ccp2_sd_video_ops,
941 .pad = &ccp2_sd_pad_ops,
942};
943
944/* subdev internal operations */
945static const struct v4l2_subdev_internal_ops ccp2_sd_internal_ops = {
946 .open = ccp2_init_formats,
947};
948
949/* --------------------------------------------------------------------------
950 * ISP ccp2 video device node
951 */
952
953/*
954 * ccp2_video_queue - Queue video buffer.
955 * @video : Pointer to isp video structure
956 * @buffer: Pointer to isp_buffer structure
957 * return -EIO or zero on success
958 */
959static int ccp2_video_queue(struct isp_video *video, struct isp_buffer *buffer)
960{
961 struct isp_ccp2_device *ccp2 = &video->isp->isp_ccp2;
962
963 ccp2_set_inaddr(ccp2, buffer->isp_addr);
964 return 0;
965}
966
967static const struct isp_video_operations ccp2_video_ops = {
968 .queue = ccp2_video_queue,
969};
970
971/* -----------------------------------------------------------------------------
972 * Media entity operations
973 */
974
975/*
976 * ccp2_link_setup - Setup ccp2 connections.
977 * @entity : Pointer to media entity structure
978 * @local : Pointer to local pad array
979 * @remote : Pointer to remote pad array
980 * @flags : Link flags
981 * return -EINVAL on error or zero on success
982 */
983static int ccp2_link_setup(struct media_entity *entity,
984 const struct media_pad *local,
985 const struct media_pad *remote, u32 flags)
986{
987 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
988 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
989
990 switch (local->index | media_entity_type(remote->entity)) {
991 case CCP2_PAD_SINK | MEDIA_ENT_T_DEVNODE:
992 /* read from memory */
993 if (flags & MEDIA_LNK_FL_ENABLED) {
994 if (ccp2->input == CCP2_INPUT_SENSOR)
995 return -EBUSY;
996 ccp2->input = CCP2_INPUT_MEMORY;
997 } else {
998 if (ccp2->input == CCP2_INPUT_MEMORY)
999 ccp2->input = CCP2_INPUT_NONE;
1000 }
1001 break;
1002
1003 case CCP2_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
1004 /* read from sensor/phy */
1005 if (flags & MEDIA_LNK_FL_ENABLED) {
1006 if (ccp2->input == CCP2_INPUT_MEMORY)
1007 return -EBUSY;
1008 ccp2->input = CCP2_INPUT_SENSOR;
1009 } else {
1010 if (ccp2->input == CCP2_INPUT_SENSOR)
1011 ccp2->input = CCP2_INPUT_NONE;
1012 } break;
1013
1014 case CCP2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
1015 /* write to video port/ccdc */
1016 if (flags & MEDIA_LNK_FL_ENABLED)
1017 ccp2->output = CCP2_OUTPUT_CCDC;
1018 else
1019 ccp2->output = CCP2_OUTPUT_NONE;
1020 break;
1021
1022 default:
1023 return -EINVAL;
1024 }
1025
1026 return 0;
1027}
1028
1029/* media operations */
1030static const struct media_entity_operations ccp2_media_ops = {
1031 .link_setup = ccp2_link_setup,
1032};
1033
1034/*
1035 * ccp2_init_entities - Initialize ccp2 subdev and media entity.
1036 * @ccp2: Pointer to ISP CCP2 device
1037 * return negative error code or zero on success
1038 */
1039static int ccp2_init_entities(struct isp_ccp2_device *ccp2)
1040{
1041 struct v4l2_subdev *sd = &ccp2->subdev;
1042 struct media_pad *pads = ccp2->pads;
1043 struct media_entity *me = &sd->entity;
1044 int ret;
1045
1046 ccp2->input = CCP2_INPUT_NONE;
1047 ccp2->output = CCP2_OUTPUT_NONE;
1048
1049 v4l2_subdev_init(sd, &ccp2_sd_ops);
1050 sd->internal_ops = &ccp2_sd_internal_ops;
1051 strlcpy(sd->name, "OMAP3 ISP CCP2", sizeof(sd->name));
1052 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
1053 v4l2_set_subdevdata(sd, ccp2);
1054 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1055
1056 pads[CCP2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1057 pads[CCP2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1058
1059 me->ops = &ccp2_media_ops;
1060 ret = media_entity_init(me, CCP2_PADS_NUM, pads, 0);
1061 if (ret < 0)
1062 return ret;
1063
1064 ccp2_init_formats(sd, NULL);
1065
1066 /*
1067 * The CCP2 has weird line alignment requirements, possibly caused by
1068 * DPCM8 decompression. Line length for data read from memory must be a
1069 * multiple of 128 bits (16 bytes) in continuous mode (when no padding
1070 * is present at end of lines). Additionally, if padding is used, the
1071 * padded line length must be a multiple of 32 bytes. To simplify the
1072 * implementation we use a fixed 32 bytes alignment regardless of the
1073 * input format and width. If strict 128 bits alignment support is
1074 * required ispvideo will need to be made aware of this special dual
1075 * alignement requirements.
1076 */
1077 ccp2->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1078 ccp2->video_in.bpl_alignment = 32;
1079 ccp2->video_in.bpl_max = 0xffffffe0;
1080 ccp2->video_in.isp = to_isp_device(ccp2);
1081 ccp2->video_in.ops = &ccp2_video_ops;
1082 ccp2->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
1083
1084 ret = omap3isp_video_init(&ccp2->video_in, "CCP2");
1085 if (ret < 0)
1086 return ret;
1087
1088 /* Connect the video node to the ccp2 subdev. */
1089 ret = media_entity_create_link(&ccp2->video_in.video.entity, 0,
1090 &ccp2->subdev.entity, CCP2_PAD_SINK, 0);
1091 if (ret < 0)
1092 return ret;
1093
1094 return 0;
1095}
1096
1097/*
1098 * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev
1099 * @ccp2: Pointer to ISP CCP2 device
1100 */
1101void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)
1102{
1103 media_entity_cleanup(&ccp2->subdev.entity);
1104
1105 v4l2_device_unregister_subdev(&ccp2->subdev);
1106 omap3isp_video_unregister(&ccp2->video_in);
1107}
1108
1109/*
1110 * omap3isp_ccp2_register_entities - Register the subdev media entity
1111 * @ccp2: Pointer to ISP CCP2 device
1112 * @vdev: Pointer to v4l device
1113 * return negative error code or zero on success
1114 */
1115
1116int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
1117 struct v4l2_device *vdev)
1118{
1119 int ret;
1120
1121 /* Register the subdev and video nodes. */
1122 ret = v4l2_device_register_subdev(vdev, &ccp2->subdev);
1123 if (ret < 0)
1124 goto error;
1125
1126 ret = omap3isp_video_register(&ccp2->video_in, vdev);
1127 if (ret < 0)
1128 goto error;
1129
1130 return 0;
1131
1132error:
1133 omap3isp_ccp2_unregister_entities(ccp2);
1134 return ret;
1135}
1136
1137/* -----------------------------------------------------------------------------
1138 * ISP ccp2 initialisation and cleanup
1139 */
1140
1141/*
1142 * omap3isp_ccp2_cleanup - CCP2 un-initialization
1143 * @isp : Pointer to ISP device
1144 */
1145void omap3isp_ccp2_cleanup(struct isp_device *isp)
1146{
1147 struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
1148
1149 regulator_put(ccp2->vdds_csib);
1150}
1151
1152/*
1153 * omap3isp_ccp2_init - CCP2 initialization.
1154 * @isp : Pointer to ISP device
1155 * return negative error code or zero on success
1156 */
1157int omap3isp_ccp2_init(struct isp_device *isp)
1158{
1159 struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
1160 int ret;
1161
1162 init_waitqueue_head(&ccp2->wait);
1163
1164 /*
1165 * On the OMAP34xx the CSI1 receiver is operated in the CSIb IO
1166 * complex, which is powered by vdds_csib power rail. Hence the
1167 * request for the regulator.
1168 *
1169 * On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with
1170 * the CSI2c or CSI2a receivers. The PHY then needs to be explicitly
1171 * configured.
1172 *
1173 * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c).
1174 */
1175 if (isp->revision == ISP_REVISION_2_0) {
1176 ccp2->vdds_csib = regulator_get(isp->dev, "vdds_csib");
1177 if (IS_ERR(ccp2->vdds_csib)) {
1178 dev_dbg(isp->dev,
1179 "Could not get regulator vdds_csib\n");
1180 ccp2->vdds_csib = NULL;
1181 }
1182 } else if (isp->revision == ISP_REVISION_15_0) {
1183 ccp2->phy = &isp->isp_csiphy1;
1184 }
1185
1186 ret = ccp2_init_entities(ccp2);
1187 if (ret < 0)
1188 goto out;
1189
1190 ccp2_reset(ccp2);
1191out:
1192 if (ret)
1193 omap3isp_ccp2_cleanup(isp);
1194
1195 return ret;
1196}
diff --git a/drivers/media/video/omap3isp/ispccp2.h b/drivers/media/video/omap3isp/ispccp2.h
new file mode 100644
index 00000000000..6674e9de2cd
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispccp2.h
@@ -0,0 +1,99 @@
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 unsigned int error;
86 enum isp_pipeline_stream_state state;
87 wait_queue_head_t wait;
88 atomic_t stopping;
89};
90
91/* Function declarations */
92int omap3isp_ccp2_init(struct isp_device *isp);
93void omap3isp_ccp2_cleanup(struct isp_device *isp);
94int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
95 struct v4l2_device *vdev);
96void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2);
97int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
98
99#endif /* OMAP3_ISP_CCP2_H */
diff --git a/drivers/media/video/omap3isp/ispcsi2.c b/drivers/media/video/omap3isp/ispcsi2.c
new file mode 100644
index 00000000000..69161a682b3
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispcsi2.c
@@ -0,0 +1,1317 @@
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};
100
101/* To set the format on the CSI2 requires a mapping function that takes
102 * the following inputs:
103 * - 2 different formats (at this time)
104 * - 2 destinations (mem, vp+mem) (vp only handled separately)
105 * - 2 decompression options (on, off)
106 * - 2 isp revisions (certain format must be handled differently on OMAP3630)
107 * Output should be CSI2 frame format code
108 * Array indices as follows: [format][dest][decompr][is_3630]
109 * Not all combinations are valid. 0 means invalid.
110 */
111static const u16 __csi2_fmt_map[2][2][2][2] = {
112 /* RAW10 formats */
113 {
114 /* Output to memory */
115 {
116 /* No DPCM decompression */
117 { CSI2_PIX_FMT_RAW10_EXP16, CSI2_PIX_FMT_RAW10_EXP16 },
118 /* DPCM decompression */
119 { 0, 0 },
120 },
121 /* Output to both */
122 {
123 /* No DPCM decompression */
124 { CSI2_PIX_FMT_RAW10_EXP16_VP,
125 CSI2_PIX_FMT_RAW10_EXP16_VP },
126 /* DPCM decompression */
127 { 0, 0 },
128 },
129 },
130 /* RAW10 DPCM8 formats */
131 {
132 /* Output to memory */
133 {
134 /* No DPCM decompression */
135 { CSI2_PIX_FMT_RAW8, CSI2_USERDEF_8BIT_DATA1 },
136 /* DPCM decompression */
137 { CSI2_PIX_FMT_RAW8_DPCM10_EXP16,
138 CSI2_USERDEF_8BIT_DATA1_DPCM10 },
139 },
140 /* Output to both */
141 {
142 /* No DPCM decompression */
143 { CSI2_PIX_FMT_RAW8_VP,
144 CSI2_PIX_FMT_RAW8_VP },
145 /* DPCM decompression */
146 { CSI2_PIX_FMT_RAW8_DPCM10_VP,
147 CSI2_USERDEF_8BIT_DATA1_DPCM10_VP },
148 },
149 },
150};
151
152/*
153 * csi2_ctx_map_format - Map CSI2 sink media bus format to CSI2 format ID
154 * @csi2: ISP CSI2 device
155 *
156 * Returns CSI2 physical format id
157 */
158static u16 csi2_ctx_map_format(struct isp_csi2_device *csi2)
159{
160 const struct v4l2_mbus_framefmt *fmt = &csi2->formats[CSI2_PAD_SINK];
161 int fmtidx, destidx, is_3630;
162
163 switch (fmt->code) {
164 case V4L2_MBUS_FMT_SGRBG10_1X10:
165 case V4L2_MBUS_FMT_SRGGB10_1X10:
166 case V4L2_MBUS_FMT_SBGGR10_1X10:
167 case V4L2_MBUS_FMT_SGBRG10_1X10:
168 fmtidx = 0;
169 break;
170 case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
171 case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
172 case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
173 case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
174 fmtidx = 1;
175 break;
176 default:
177 WARN(1, KERN_ERR "CSI2: pixel format %08x unsupported!\n",
178 fmt->code);
179 return 0;
180 }
181
182 if (!(csi2->output & CSI2_OUTPUT_CCDC) &&
183 !(csi2->output & CSI2_OUTPUT_MEMORY)) {
184 /* Neither output enabled is a valid combination */
185 return CSI2_PIX_FMT_OTHERS;
186 }
187
188 /* If we need to skip frames at the beginning of the stream disable the
189 * video port to avoid sending the skipped frames to the CCDC.
190 */
191 destidx = csi2->frame_skip ? 0 : !!(csi2->output & CSI2_OUTPUT_CCDC);
192 is_3630 = csi2->isp->revision == ISP_REVISION_15_0;
193
194 return __csi2_fmt_map[fmtidx][destidx][csi2->dpcm_decompress][is_3630];
195}
196
197/*
198 * csi2_set_outaddr - Set memory address to save output image
199 * @csi2: Pointer to ISP CSI2a device.
200 * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
201 *
202 * Sets the memory address where the output will be saved.
203 *
204 * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
205 * boundary.
206 */
207static void csi2_set_outaddr(struct isp_csi2_device *csi2, u32 addr)
208{
209 struct isp_device *isp = csi2->isp;
210 struct isp_csi2_ctx_cfg *ctx = &csi2->contexts[0];
211
212 ctx->ping_addr = addr;
213 ctx->pong_addr = addr;
214 isp_reg_writel(isp, ctx->ping_addr,
215 csi2->regs1, ISPCSI2_CTX_DAT_PING_ADDR(ctx->ctxnum));
216 isp_reg_writel(isp, ctx->pong_addr,
217 csi2->regs1, ISPCSI2_CTX_DAT_PONG_ADDR(ctx->ctxnum));
218}
219
220/*
221 * is_usr_def_mapping - Checks whether USER_DEF_MAPPING should
222 * be enabled by CSI2.
223 * @format_id: mapped format id
224 *
225 */
226static inline int is_usr_def_mapping(u32 format_id)
227{
228 return (format_id & 0x40) ? 1 : 0;
229}
230
231/*
232 * csi2_ctx_enable - Enable specified CSI2 context
233 * @ctxnum: Context number, valid between 0 and 7 values.
234 * @enable: enable
235 *
236 */
237static void csi2_ctx_enable(struct isp_device *isp,
238 struct isp_csi2_device *csi2, u8 ctxnum, u8 enable)
239{
240 struct isp_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum];
241 unsigned int skip = 0;
242 u32 reg;
243
244 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL1(ctxnum));
245
246 if (enable) {
247 if (csi2->frame_skip)
248 skip = csi2->frame_skip;
249 else if (csi2->output & CSI2_OUTPUT_MEMORY)
250 skip = 1;
251
252 reg &= ~ISPCSI2_CTX_CTRL1_COUNT_MASK;
253 reg |= ISPCSI2_CTX_CTRL1_COUNT_UNLOCK
254 | (skip << ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
255 | ISPCSI2_CTX_CTRL1_CTX_EN;
256 } else {
257 reg &= ~ISPCSI2_CTX_CTRL1_CTX_EN;
258 }
259
260 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL1(ctxnum));
261 ctx->enabled = enable;
262}
263
264/*
265 * csi2_ctx_config - CSI2 context configuration.
266 * @ctx: context configuration
267 *
268 */
269static void csi2_ctx_config(struct isp_device *isp,
270 struct isp_csi2_device *csi2,
271 struct isp_csi2_ctx_cfg *ctx)
272{
273 u32 reg;
274
275 /* Set up CSI2_CTx_CTRL1 */
276 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL1(ctx->ctxnum));
277
278 if (ctx->eof_enabled)
279 reg |= ISPCSI2_CTX_CTRL1_EOF_EN;
280 else
281 reg &= ~ISPCSI2_CTX_CTRL1_EOF_EN;
282
283 if (ctx->eol_enabled)
284 reg |= ISPCSI2_CTX_CTRL1_EOL_EN;
285 else
286 reg &= ~ISPCSI2_CTX_CTRL1_EOL_EN;
287
288 if (ctx->checksum_enabled)
289 reg |= ISPCSI2_CTX_CTRL1_CS_EN;
290 else
291 reg &= ~ISPCSI2_CTX_CTRL1_CS_EN;
292
293 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL1(ctx->ctxnum));
294
295 /* Set up CSI2_CTx_CTRL2 */
296 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL2(ctx->ctxnum));
297
298 reg &= ~(ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK);
299 reg |= ctx->virtual_id << ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
300
301 reg &= ~(ISPCSI2_CTX_CTRL2_FORMAT_MASK);
302 reg |= ctx->format_id << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT;
303
304 if (ctx->dpcm_decompress) {
305 if (ctx->dpcm_predictor)
306 reg |= ISPCSI2_CTX_CTRL2_DPCM_PRED;
307 else
308 reg &= ~ISPCSI2_CTX_CTRL2_DPCM_PRED;
309 }
310
311 if (is_usr_def_mapping(ctx->format_id)) {
312 reg &= ~ISPCSI2_CTX_CTRL2_USER_DEF_MAP_MASK;
313 reg |= 2 << ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT;
314 }
315
316 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL2(ctx->ctxnum));
317
318 /* Set up CSI2_CTx_CTRL3 */
319 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL3(ctx->ctxnum));
320 reg &= ~(ISPCSI2_CTX_CTRL3_ALPHA_MASK);
321 reg |= (ctx->alpha << ISPCSI2_CTX_CTRL3_ALPHA_SHIFT);
322
323 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL3(ctx->ctxnum));
324
325 /* Set up CSI2_CTx_DAT_OFST */
326 reg = isp_reg_readl(isp, csi2->regs1,
327 ISPCSI2_CTX_DAT_OFST(ctx->ctxnum));
328 reg &= ~ISPCSI2_CTX_DAT_OFST_OFST_MASK;
329 reg |= ctx->data_offset << ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
330 isp_reg_writel(isp, reg, csi2->regs1,
331 ISPCSI2_CTX_DAT_OFST(ctx->ctxnum));
332
333 isp_reg_writel(isp, ctx->ping_addr,
334 csi2->regs1, ISPCSI2_CTX_DAT_PING_ADDR(ctx->ctxnum));
335
336 isp_reg_writel(isp, ctx->pong_addr,
337 csi2->regs1, ISPCSI2_CTX_DAT_PONG_ADDR(ctx->ctxnum));
338}
339
340/*
341 * csi2_timing_config - CSI2 timing configuration.
342 * @timing: csi2_timing_cfg structure
343 */
344static void csi2_timing_config(struct isp_device *isp,
345 struct isp_csi2_device *csi2,
346 struct isp_csi2_timing_cfg *timing)
347{
348 u32 reg;
349
350 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_TIMING);
351
352 if (timing->force_rx_mode)
353 reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO(timing->ionum);
354 else
355 reg &= ~ISPCSI2_TIMING_FORCE_RX_MODE_IO(timing->ionum);
356
357 if (timing->stop_state_16x)
358 reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO(timing->ionum);
359 else
360 reg &= ~ISPCSI2_TIMING_STOP_STATE_X16_IO(timing->ionum);
361
362 if (timing->stop_state_4x)
363 reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO(timing->ionum);
364 else
365 reg &= ~ISPCSI2_TIMING_STOP_STATE_X4_IO(timing->ionum);
366
367 reg &= ~ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(timing->ionum);
368 reg |= timing->stop_state_counter <<
369 ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(timing->ionum);
370
371 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_TIMING);
372}
373
374/*
375 * csi2_irq_ctx_set - Enables CSI2 Context IRQs.
376 * @enable: Enable/disable CSI2 Context interrupts
377 */
378static void csi2_irq_ctx_set(struct isp_device *isp,
379 struct isp_csi2_device *csi2, int enable)
380{
381 u32 reg = ISPCSI2_CTX_IRQSTATUS_FE_IRQ;
382 int i;
383
384 if (csi2->use_fs_irq)
385 reg |= ISPCSI2_CTX_IRQSTATUS_FS_IRQ;
386
387 for (i = 0; i < 8; i++) {
388 isp_reg_writel(isp, reg, csi2->regs1,
389 ISPCSI2_CTX_IRQSTATUS(i));
390 if (enable)
391 isp_reg_set(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
392 reg);
393 else
394 isp_reg_clr(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
395 reg);
396 }
397}
398
399/*
400 * csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
401 * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
402 */
403static void csi2_irq_complexio1_set(struct isp_device *isp,
404 struct isp_csi2_device *csi2, int enable)
405{
406 u32 reg;
407 reg = ISPCSI2_PHY_IRQENABLE_STATEALLULPMEXIT |
408 ISPCSI2_PHY_IRQENABLE_STATEALLULPMENTER |
409 ISPCSI2_PHY_IRQENABLE_STATEULPM5 |
410 ISPCSI2_PHY_IRQENABLE_ERRCONTROL5 |
411 ISPCSI2_PHY_IRQENABLE_ERRESC5 |
412 ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS5 |
413 ISPCSI2_PHY_IRQENABLE_ERRSOTHS5 |
414 ISPCSI2_PHY_IRQENABLE_STATEULPM4 |
415 ISPCSI2_PHY_IRQENABLE_ERRCONTROL4 |
416 ISPCSI2_PHY_IRQENABLE_ERRESC4 |
417 ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS4 |
418 ISPCSI2_PHY_IRQENABLE_ERRSOTHS4 |
419 ISPCSI2_PHY_IRQENABLE_STATEULPM3 |
420 ISPCSI2_PHY_IRQENABLE_ERRCONTROL3 |
421 ISPCSI2_PHY_IRQENABLE_ERRESC3 |
422 ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS3 |
423 ISPCSI2_PHY_IRQENABLE_ERRSOTHS3 |
424 ISPCSI2_PHY_IRQENABLE_STATEULPM2 |
425 ISPCSI2_PHY_IRQENABLE_ERRCONTROL2 |
426 ISPCSI2_PHY_IRQENABLE_ERRESC2 |
427 ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS2 |
428 ISPCSI2_PHY_IRQENABLE_ERRSOTHS2 |
429 ISPCSI2_PHY_IRQENABLE_STATEULPM1 |
430 ISPCSI2_PHY_IRQENABLE_ERRCONTROL1 |
431 ISPCSI2_PHY_IRQENABLE_ERRESC1 |
432 ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS1 |
433 ISPCSI2_PHY_IRQENABLE_ERRSOTHS1;
434 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
435 if (enable)
436 reg |= isp_reg_readl(isp, csi2->regs1, ISPCSI2_PHY_IRQENABLE);
437 else
438 reg = 0;
439 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_PHY_IRQENABLE);
440}
441
442/*
443 * csi2_irq_status_set - Enables CSI2 Status IRQs.
444 * @enable: Enable/disable CSI2 Status interrupts
445 */
446static void csi2_irq_status_set(struct isp_device *isp,
447 struct isp_csi2_device *csi2, int enable)
448{
449 u32 reg;
450 reg = ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
451 ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
452 ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ |
453 ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
454 ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
455 ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ |
456 ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ |
457 ISPCSI2_IRQSTATUS_CONTEXT(0);
458 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_IRQSTATUS);
459 if (enable)
460 reg |= isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQENABLE);
461 else
462 reg = 0;
463
464 isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_IRQENABLE);
465}
466
467/*
468 * omap3isp_csi2_reset - Resets the CSI2 module.
469 *
470 * Must be called with the phy lock held.
471 *
472 * Returns 0 if successful, or -EBUSY if power command didn't respond.
473 */
474int omap3isp_csi2_reset(struct isp_csi2_device *csi2)
475{
476 struct isp_device *isp = csi2->isp;
477 u8 soft_reset_retries = 0;
478 u32 reg;
479 int i;
480
481 if (!csi2->available)
482 return -ENODEV;
483
484 if (csi2->phy->phy_in_use)
485 return -EBUSY;
486
487 isp_reg_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
488 ISPCSI2_SYSCONFIG_SOFT_RESET);
489
490 do {
491 reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_SYSSTATUS) &
492 ISPCSI2_SYSSTATUS_RESET_DONE;
493 if (reg == ISPCSI2_SYSSTATUS_RESET_DONE)
494 break;
495 soft_reset_retries++;
496 if (soft_reset_retries < 5)
497 udelay(100);
498 } while (soft_reset_retries < 5);
499
500 if (soft_reset_retries == 5) {
501 printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
502 return -EBUSY;
503 }
504
505 if (isp->revision == ISP_REVISION_15_0)
506 isp_reg_set(isp, csi2->regs1, ISPCSI2_PHY_CFG,
507 ISPCSI2_PHY_CFG_RESET_CTRL);
508
509 i = 100;
510 do {
511 reg = isp_reg_readl(isp, csi2->phy->phy_regs, ISPCSIPHY_REG1)
512 & ISPCSIPHY_REG1_RESET_DONE_CTRLCLK;
513 if (reg == ISPCSIPHY_REG1_RESET_DONE_CTRLCLK)
514 break;
515 udelay(100);
516 } while (--i > 0);
517
518 if (i == 0) {
519 printk(KERN_ERR
520 "CSI2: Reset for CSI2_96M_FCLK domain Failed!\n");
521 return -EBUSY;
522 }
523
524 if (isp->autoidle)
525 isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
526 ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
527 ISPCSI2_SYSCONFIG_AUTO_IDLE,
528 ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART |
529 ((isp->revision == ISP_REVISION_15_0) ?
530 ISPCSI2_SYSCONFIG_AUTO_IDLE : 0));
531 else
532 isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
533 ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
534 ISPCSI2_SYSCONFIG_AUTO_IDLE,
535 ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO);
536
537 return 0;
538}
539
540static int csi2_configure(struct isp_csi2_device *csi2)
541{
542 const struct isp_v4l2_subdevs_group *pdata;
543 struct isp_device *isp = csi2->isp;
544 struct isp_csi2_timing_cfg *timing = &csi2->timing[0];
545 struct v4l2_subdev *sensor;
546 struct media_pad *pad;
547
548 /*
549 * CSI2 fields that can be updated while the context has
550 * been enabled or the interface has been enabled are not
551 * updated dynamically currently. So we do not allow to
552 * reconfigure if either has been enabled
553 */
554 if (csi2->contexts[0].enabled || csi2->ctrl.if_enable)
555 return -EBUSY;
556
557 pad = media_entity_remote_source(&csi2->pads[CSI2_PAD_SINK]);
558 sensor = media_entity_to_v4l2_subdev(pad->entity);
559 pdata = sensor->host_priv;
560
561 csi2->frame_skip = 0;
562 v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);
563
564 csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div;
565 csi2->ctrl.frame_mode = ISP_CSI2_FRAME_IMMEDIATE;
566 csi2->ctrl.ecc_enable = pdata->bus.csi2.crc;
567
568 timing->ionum = 1;
569 timing->force_rx_mode = 1;
570 timing->stop_state_16x = 1;
571 timing->stop_state_4x = 1;
572 timing->stop_state_counter = 0x1FF;
573
574 /*
575 * The CSI2 receiver can't do any format conversion except DPCM
576 * decompression, so every set_format call configures both pads
577 * and enables DPCM decompression as a special case:
578 */
579 if (csi2->formats[CSI2_PAD_SINK].code !=
580 csi2->formats[CSI2_PAD_SOURCE].code)
581 csi2->dpcm_decompress = true;
582 else
583 csi2->dpcm_decompress = false;
584
585 csi2->contexts[0].format_id = csi2_ctx_map_format(csi2);
586
587 if (csi2->video_out.bpl_padding == 0)
588 csi2->contexts[0].data_offset = 0;
589 else
590 csi2->contexts[0].data_offset = csi2->video_out.bpl_value;
591
592 /*
593 * Enable end of frame and end of line signals generation for
594 * context 0. These signals are generated from CSI2 receiver to
595 * qualify the last pixel of a frame and the last pixel of a line.
596 * Without enabling the signals CSI2 receiver writes data to memory
597 * beyond buffer size and/or data line offset is not handled correctly.
598 */
599 csi2->contexts[0].eof_enabled = 1;
600 csi2->contexts[0].eol_enabled = 1;
601
602 csi2_irq_complexio1_set(isp, csi2, 1);
603 csi2_irq_ctx_set(isp, csi2, 1);
604 csi2_irq_status_set(isp, csi2, 1);
605
606 /* Set configuration (timings, format and links) */
607 csi2_timing_config(isp, csi2, timing);
608 csi2_recv_config(isp, csi2, &csi2->ctrl);
609 csi2_ctx_config(isp, csi2, &csi2->contexts[0]);
610
611 return 0;
612}
613
614/*
615 * csi2_print_status - Prints CSI2 debug information.
616 */
617#define CSI2_PRINT_REGISTER(isp, regs, name)\
618 dev_dbg(isp->dev, "###CSI2 " #name "=0x%08x\n", \
619 isp_reg_readl(isp, regs, ISPCSI2_##name))
620
621static void csi2_print_status(struct isp_csi2_device *csi2)
622{
623 struct isp_device *isp = csi2->isp;
624
625 if (!csi2->available)
626 return;
627
628 dev_dbg(isp->dev, "-------------CSI2 Register dump-------------\n");
629
630 CSI2_PRINT_REGISTER(isp, csi2->regs1, SYSCONFIG);
631 CSI2_PRINT_REGISTER(isp, csi2->regs1, SYSSTATUS);
632 CSI2_PRINT_REGISTER(isp, csi2->regs1, IRQENABLE);
633 CSI2_PRINT_REGISTER(isp, csi2->regs1, IRQSTATUS);
634 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTRL);
635 CSI2_PRINT_REGISTER(isp, csi2->regs1, DBG_H);
636 CSI2_PRINT_REGISTER(isp, csi2->regs1, GNQ);
637 CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_CFG);
638 CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_IRQSTATUS);
639 CSI2_PRINT_REGISTER(isp, csi2->regs1, SHORT_PACKET);
640 CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_IRQENABLE);
641 CSI2_PRINT_REGISTER(isp, csi2->regs1, DBG_P);
642 CSI2_PRINT_REGISTER(isp, csi2->regs1, TIMING);
643 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL1(0));
644 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL2(0));
645 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_OFST(0));
646 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_PING_ADDR(0));
647 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_PONG_ADDR(0));
648 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_IRQENABLE(0));
649 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_IRQSTATUS(0));
650 CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL3(0));
651
652 dev_dbg(isp->dev, "--------------------------------------------\n");
653}
654
655/* -----------------------------------------------------------------------------
656 * Interrupt handling
657 */
658
659/*
660 * csi2_isr_buffer - Does buffer handling at end-of-frame
661 * when writing to memory.
662 */
663static void csi2_isr_buffer(struct isp_csi2_device *csi2)
664{
665 struct isp_device *isp = csi2->isp;
666 struct isp_buffer *buffer;
667
668 csi2_ctx_enable(isp, csi2, 0, 0);
669
670 buffer = omap3isp_video_buffer_next(&csi2->video_out, 0);
671
672 /*
673 * Let video queue operation restart engine if there is an underrun
674 * condition.
675 */
676 if (buffer == NULL)
677 return;
678
679 csi2_set_outaddr(csi2, buffer->isp_addr);
680 csi2_ctx_enable(isp, csi2, 0, 1);
681}
682
683static void csi2_isr_ctx(struct isp_csi2_device *csi2,
684 struct isp_csi2_ctx_cfg *ctx)
685{
686 struct isp_device *isp = csi2->isp;
687 unsigned int n = ctx->ctxnum;
688 u32 status;
689
690 status = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));
691 isp_reg_writel(isp, status, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));
692
693 /* Propagate frame number */
694 if (status & ISPCSI2_CTX_IRQSTATUS_FS_IRQ) {
695 struct isp_pipeline *pipe =
696 to_isp_pipeline(&csi2->subdev.entity);
697 if (pipe->do_propagation)
698 atomic_inc(&pipe->frame_number);
699 }
700
701 if (!(status & ISPCSI2_CTX_IRQSTATUS_FE_IRQ))
702 return;
703
704 /* Skip interrupts until we reach the frame skip count. The CSI2 will be
705 * automatically disabled, as the frame skip count has been programmed
706 * in the CSI2_CTx_CTRL1::COUNT field, so reenable it.
707 *
708 * It would have been nice to rely on the FRAME_NUMBER interrupt instead
709 * but it turned out that the interrupt is only generated when the CSI2
710 * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased
711 * correctly and reaches 0 when data is forwarded to the video port only
712 * but no interrupt arrives). Maybe a CSI2 hardware bug.
713 */
714 if (csi2->frame_skip) {
715 csi2->frame_skip--;
716 if (csi2->frame_skip == 0) {
717 ctx->format_id = csi2_ctx_map_format(csi2);
718 csi2_ctx_config(isp, csi2, ctx);
719 csi2_ctx_enable(isp, csi2, n, 1);
720 }
721 return;
722 }
723
724 if (csi2->output & CSI2_OUTPUT_MEMORY)
725 csi2_isr_buffer(csi2);
726}
727
728/*
729 * omap3isp_csi2_isr - CSI2 interrupt handling.
730 *
731 * Return -EIO on Transmission error
732 */
733int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
734{
735 u32 csi2_irqstatus, cpxio1_irqstatus;
736 struct isp_device *isp = csi2->isp;
737 int retval = 0;
738
739 if (!csi2->available)
740 return -ENODEV;
741
742 csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS);
743 isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS);
744
745 /* Failure Cases */
746 if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ) {
747 cpxio1_irqstatus = isp_reg_readl(isp, csi2->regs1,
748 ISPCSI2_PHY_IRQSTATUS);
749 isp_reg_writel(isp, cpxio1_irqstatus,
750 csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
751 dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ "
752 "%x\n", cpxio1_irqstatus);
753 retval = -EIO;
754 }
755
756 if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
757 ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
758 ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
759 ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
760 ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)) {
761 dev_dbg(isp->dev, "CSI2 Err:"
762 " OCP:%d,"
763 " Short_pack:%d,"
764 " ECC:%d,"
765 " CPXIO2:%d,"
766 " FIFO_OVF:%d,"
767 "\n",
768 (csi2_irqstatus &
769 ISPCSI2_IRQSTATUS_OCP_ERR_IRQ) ? 1 : 0,
770 (csi2_irqstatus &
771 ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ) ? 1 : 0,
772 (csi2_irqstatus &
773 ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ) ? 1 : 0,
774 (csi2_irqstatus &
775 ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0,
776 (csi2_irqstatus &
777 ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0);
778 retval = -EIO;
779 }
780
781 if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
782 return 0;
783
784 /* Successful cases */
785 if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0))
786 csi2_isr_ctx(csi2, &csi2->contexts[0]);
787
788 if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
789 dev_dbg(isp->dev, "CSI2: ECC correction done\n");
790
791 return retval;
792}
793
794/* -----------------------------------------------------------------------------
795 * ISP video operations
796 */
797
798/*
799 * csi2_queue - Queues the first buffer when using memory output
800 * @video: The video node
801 * @buffer: buffer to queue
802 */
803static int csi2_queue(struct isp_video *video, struct isp_buffer *buffer)
804{
805 struct isp_device *isp = video->isp;
806 struct isp_csi2_device *csi2 = &isp->isp_csi2a;
807
808 csi2_set_outaddr(csi2, buffer->isp_addr);
809
810 /*
811 * If streaming was enabled before there was a buffer queued
812 * or underrun happened in the ISR, the hardware was not enabled
813 * and DMA queue flag ISP_VIDEO_DMAQUEUE_UNDERRUN is still set.
814 * Enable it now.
815 */
816 if (csi2->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
817 /* Enable / disable context 0 and IRQs */
818 csi2_if_enable(isp, csi2, 1);
819 csi2_ctx_enable(isp, csi2, 0, 1);
820 isp_video_dmaqueue_flags_clr(&csi2->video_out);
821 }
822
823 return 0;
824}
825
826static const struct isp_video_operations csi2_ispvideo_ops = {
827 .queue = csi2_queue,
828};
829
830/* -----------------------------------------------------------------------------
831 * V4L2 subdev operations
832 */
833
834static struct v4l2_mbus_framefmt *
835__csi2_get_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
836 unsigned int pad, enum v4l2_subdev_format_whence which)
837{
838 if (which == V4L2_SUBDEV_FORMAT_TRY)
839 return v4l2_subdev_get_try_format(fh, pad);
840 else
841 return &csi2->formats[pad];
842}
843
844static void
845csi2_try_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
846 unsigned int pad, struct v4l2_mbus_framefmt *fmt,
847 enum v4l2_subdev_format_whence which)
848{
849 enum v4l2_mbus_pixelcode pixelcode;
850 struct v4l2_mbus_framefmt *format;
851 const struct isp_format_info *info;
852 unsigned int i;
853
854 switch (pad) {
855 case CSI2_PAD_SINK:
856 /* Clamp the width and height to valid range (1-8191). */
857 for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) {
858 if (fmt->code == csi2_input_fmts[i])
859 break;
860 }
861
862 /* If not found, use SGRBG10 as default */
863 if (i >= ARRAY_SIZE(csi2_input_fmts))
864 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
865
866 fmt->width = clamp_t(u32, fmt->width, 1, 8191);
867 fmt->height = clamp_t(u32, fmt->height, 1, 8191);
868 break;
869
870 case CSI2_PAD_SOURCE:
871 /* Source format same as sink format, except for DPCM
872 * compression.
873 */
874 pixelcode = fmt->code;
875 format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which);
876 memcpy(fmt, format, sizeof(*fmt));
877
878 /*
879 * Only Allow DPCM decompression, and check that the
880 * pattern is preserved
881 */
882 info = omap3isp_video_format_info(fmt->code);
883 if (info->uncompressed == pixelcode)
884 fmt->code = pixelcode;
885 break;
886 }
887
888 /* RGB, non-interlaced */
889 fmt->colorspace = V4L2_COLORSPACE_SRGB;
890 fmt->field = V4L2_FIELD_NONE;
891}
892
893/*
894 * csi2_enum_mbus_code - Handle pixel format enumeration
895 * @sd : pointer to v4l2 subdev structure
896 * @fh : V4L2 subdev file handle
897 * @code : pointer to v4l2_subdev_mbus_code_enum structure
898 * return -EINVAL or zero on success
899 */
900static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
901 struct v4l2_subdev_fh *fh,
902 struct v4l2_subdev_mbus_code_enum *code)
903{
904 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
905 struct v4l2_mbus_framefmt *format;
906 const struct isp_format_info *info;
907
908 if (code->pad == CSI2_PAD_SINK) {
909 if (code->index >= ARRAY_SIZE(csi2_input_fmts))
910 return -EINVAL;
911
912 code->code = csi2_input_fmts[code->index];
913 } else {
914 format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK,
915 V4L2_SUBDEV_FORMAT_TRY);
916 switch (code->index) {
917 case 0:
918 /* Passthrough sink pad code */
919 code->code = format->code;
920 break;
921 case 1:
922 /* Uncompressed code */
923 info = omap3isp_video_format_info(format->code);
924 if (info->uncompressed == format->code)
925 return -EINVAL;
926
927 code->code = info->uncompressed;
928 break;
929 default:
930 return -EINVAL;
931 }
932 }
933
934 return 0;
935}
936
937static int csi2_enum_frame_size(struct v4l2_subdev *sd,
938 struct v4l2_subdev_fh *fh,
939 struct v4l2_subdev_frame_size_enum *fse)
940{
941 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
942 struct v4l2_mbus_framefmt format;
943
944 if (fse->index != 0)
945 return -EINVAL;
946
947 format.code = fse->code;
948 format.width = 1;
949 format.height = 1;
950 csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
951 fse->min_width = format.width;
952 fse->min_height = format.height;
953
954 if (format.code != fse->code)
955 return -EINVAL;
956
957 format.code = fse->code;
958 format.width = -1;
959 format.height = -1;
960 csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
961 fse->max_width = format.width;
962 fse->max_height = format.height;
963
964 return 0;
965}
966
967/*
968 * csi2_get_format - Handle get format by pads subdev method
969 * @sd : pointer to v4l2 subdev structure
970 * @fh : V4L2 subdev file handle
971 * @fmt: pointer to v4l2 subdev format structure
972 * return -EINVAL or zero on success
973 */
974static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
975 struct v4l2_subdev_format *fmt)
976{
977 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
978 struct v4l2_mbus_framefmt *format;
979
980 format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
981 if (format == NULL)
982 return -EINVAL;
983
984 fmt->format = *format;
985 return 0;
986}
987
988/*
989 * csi2_set_format - Handle set format by pads subdev method
990 * @sd : pointer to v4l2 subdev structure
991 * @fh : V4L2 subdev file handle
992 * @fmt: pointer to v4l2 subdev format structure
993 * return -EINVAL or zero on success
994 */
995static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
996 struct v4l2_subdev_format *fmt)
997{
998 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
999 struct v4l2_mbus_framefmt *format;
1000
1001 format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
1002 if (format == NULL)
1003 return -EINVAL;
1004
1005 csi2_try_format(csi2, fh, fmt->pad, &fmt->format, fmt->which);
1006 *format = fmt->format;
1007
1008 /* Propagate the format from sink to source */
1009 if (fmt->pad == CSI2_PAD_SINK) {
1010 format = __csi2_get_format(csi2, fh, CSI2_PAD_SOURCE,
1011 fmt->which);
1012 *format = fmt->format;
1013 csi2_try_format(csi2, fh, CSI2_PAD_SOURCE, format, fmt->which);
1014 }
1015
1016 return 0;
1017}
1018
1019/*
1020 * csi2_init_formats - Initialize formats on all pads
1021 * @sd: ISP CSI2 V4L2 subdevice
1022 * @fh: V4L2 subdev file handle
1023 *
1024 * Initialize all pad formats with default values. If fh is not NULL, try
1025 * formats are initialized on the file handle. Otherwise active formats are
1026 * initialized on the device.
1027 */
1028static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1029{
1030 struct v4l2_subdev_format format;
1031
1032 memset(&format, 0, sizeof(format));
1033 format.pad = CSI2_PAD_SINK;
1034 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1035 format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
1036 format.format.width = 4096;
1037 format.format.height = 4096;
1038 csi2_set_format(sd, fh, &format);
1039
1040 return 0;
1041}
1042
1043/*
1044 * csi2_set_stream - Enable/Disable streaming on the CSI2 module
1045 * @sd: ISP CSI2 V4L2 subdevice
1046 * @enable: ISP pipeline stream state
1047 *
1048 * Return 0 on success or a negative error code otherwise.
1049 */
1050static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
1051{
1052 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
1053 struct isp_device *isp = csi2->isp;
1054 struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
1055 struct isp_video *video_out = &csi2->video_out;
1056
1057 switch (enable) {
1058 case ISP_PIPELINE_STREAM_CONTINUOUS:
1059 if (omap3isp_csiphy_acquire(csi2->phy) < 0)
1060 return -ENODEV;
1061 csi2->use_fs_irq = pipe->do_propagation;
1062 if (csi2->output & CSI2_OUTPUT_MEMORY)
1063 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI2A_WRITE);
1064 csi2_configure(csi2);
1065 csi2_print_status(csi2);
1066
1067 /*
1068 * When outputting to memory with no buffer available, let the
1069 * buffer queue handler start the hardware. A DMA queue flag
1070 * ISP_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
1071 * a buffer available.
1072 */
1073 if (csi2->output & CSI2_OUTPUT_MEMORY &&
1074 !(video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED))
1075 break;
1076 /* Enable context 0 and IRQs */
1077 atomic_set(&csi2->stopping, 0);
1078 csi2_ctx_enable(isp, csi2, 0, 1);
1079 csi2_if_enable(isp, csi2, 1);
1080 isp_video_dmaqueue_flags_clr(video_out);
1081 break;
1082
1083 case ISP_PIPELINE_STREAM_STOPPED:
1084 if (csi2->state == ISP_PIPELINE_STREAM_STOPPED)
1085 return 0;
1086 if (omap3isp_module_sync_idle(&sd->entity, &csi2->wait,
1087 &csi2->stopping))
1088 dev_dbg(isp->dev, "%s: module stop timeout.\n",
1089 sd->name);
1090 csi2_ctx_enable(isp, csi2, 0, 0);
1091 csi2_if_enable(isp, csi2, 0);
1092 csi2_irq_ctx_set(isp, csi2, 0);
1093 omap3isp_csiphy_release(csi2->phy);
1094 isp_video_dmaqueue_flags_clr(video_out);
1095 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI2A_WRITE);
1096 break;
1097 }
1098
1099 csi2->state = enable;
1100 return 0;
1101}
1102
1103/* subdev video operations */
1104static const struct v4l2_subdev_video_ops csi2_video_ops = {
1105 .s_stream = csi2_set_stream,
1106};
1107
1108/* subdev pad operations */
1109static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
1110 .enum_mbus_code = csi2_enum_mbus_code,
1111 .enum_frame_size = csi2_enum_frame_size,
1112 .get_fmt = csi2_get_format,
1113 .set_fmt = csi2_set_format,
1114};
1115
1116/* subdev operations */
1117static const struct v4l2_subdev_ops csi2_ops = {
1118 .video = &csi2_video_ops,
1119 .pad = &csi2_pad_ops,
1120};
1121
1122/* subdev internal operations */
1123static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
1124 .open = csi2_init_formats,
1125};
1126
1127/* -----------------------------------------------------------------------------
1128 * Media entity operations
1129 */
1130
1131/*
1132 * csi2_link_setup - Setup CSI2 connections.
1133 * @entity : Pointer to media entity structure
1134 * @local : Pointer to local pad array
1135 * @remote : Pointer to remote pad array
1136 * @flags : Link flags
1137 * return -EINVAL or zero on success
1138 */
1139static int csi2_link_setup(struct media_entity *entity,
1140 const struct media_pad *local,
1141 const struct media_pad *remote, u32 flags)
1142{
1143 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1144 struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
1145 struct isp_csi2_ctrl_cfg *ctrl = &csi2->ctrl;
1146
1147 /*
1148 * The ISP core doesn't support pipelines with multiple video outputs.
1149 * Revisit this when it will be implemented, and return -EBUSY for now.
1150 */
1151
1152 switch (local->index | media_entity_type(remote->entity)) {
1153 case CSI2_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
1154 if (flags & MEDIA_LNK_FL_ENABLED) {
1155 if (csi2->output & ~CSI2_OUTPUT_MEMORY)
1156 return -EBUSY;
1157 csi2->output |= CSI2_OUTPUT_MEMORY;
1158 } else {
1159 csi2->output &= ~CSI2_OUTPUT_MEMORY;
1160 }
1161 break;
1162
1163 case CSI2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
1164 if (flags & MEDIA_LNK_FL_ENABLED) {
1165 if (csi2->output & ~CSI2_OUTPUT_CCDC)
1166 return -EBUSY;
1167 csi2->output |= CSI2_OUTPUT_CCDC;
1168 } else {
1169 csi2->output &= ~CSI2_OUTPUT_CCDC;
1170 }
1171 break;
1172
1173 default:
1174 /* Link from camera to CSI2 is fixed... */
1175 return -EINVAL;
1176 }
1177
1178 ctrl->vp_only_enable =
1179 (csi2->output & CSI2_OUTPUT_MEMORY) ? false : true;
1180 ctrl->vp_clk_enable = !!(csi2->output & CSI2_OUTPUT_CCDC);
1181
1182 return 0;
1183}
1184
1185/* media operations */
1186static const struct media_entity_operations csi2_media_ops = {
1187 .link_setup = csi2_link_setup,
1188};
1189
1190/*
1191 * csi2_init_entities - Initialize subdev and media entity.
1192 * @csi2: Pointer to csi2 structure.
1193 * return -ENOMEM or zero on success
1194 */
1195static int csi2_init_entities(struct isp_csi2_device *csi2)
1196{
1197 struct v4l2_subdev *sd = &csi2->subdev;
1198 struct media_pad *pads = csi2->pads;
1199 struct media_entity *me = &sd->entity;
1200 int ret;
1201
1202 v4l2_subdev_init(sd, &csi2_ops);
1203 sd->internal_ops = &csi2_internal_ops;
1204 strlcpy(sd->name, "OMAP3 ISP CSI2a", sizeof(sd->name));
1205
1206 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
1207 v4l2_set_subdevdata(sd, csi2);
1208 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1209
1210 pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1211 pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1212
1213 me->ops = &csi2_media_ops;
1214 ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0);
1215 if (ret < 0)
1216 return ret;
1217
1218 csi2_init_formats(sd, NULL);
1219
1220 /* Video device node */
1221 csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1222 csi2->video_out.ops = &csi2_ispvideo_ops;
1223 csi2->video_out.bpl_alignment = 32;
1224 csi2->video_out.bpl_zero_padding = 1;
1225 csi2->video_out.bpl_max = 0x1ffe0;
1226 csi2->video_out.isp = csi2->isp;
1227 csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
1228
1229 ret = omap3isp_video_init(&csi2->video_out, "CSI2a");
1230 if (ret < 0)
1231 return ret;
1232
1233 /* Connect the CSI2 subdev to the video node. */
1234 ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
1235 &csi2->video_out.video.entity, 0, 0);
1236 if (ret < 0)
1237 return ret;
1238
1239 return 0;
1240}
1241
1242void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2)
1243{
1244 media_entity_cleanup(&csi2->subdev.entity);
1245
1246 v4l2_device_unregister_subdev(&csi2->subdev);
1247 omap3isp_video_unregister(&csi2->video_out);
1248}
1249
1250int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
1251 struct v4l2_device *vdev)
1252{
1253 int ret;
1254
1255 /* Register the subdev and video nodes. */
1256 ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
1257 if (ret < 0)
1258 goto error;
1259
1260 ret = omap3isp_video_register(&csi2->video_out, vdev);
1261 if (ret < 0)
1262 goto error;
1263
1264 return 0;
1265
1266error:
1267 omap3isp_csi2_unregister_entities(csi2);
1268 return ret;
1269}
1270
1271/* -----------------------------------------------------------------------------
1272 * ISP CSI2 initialisation and cleanup
1273 */
1274
1275/*
1276 * omap3isp_csi2_cleanup - Routine for module driver cleanup
1277 */
1278void omap3isp_csi2_cleanup(struct isp_device *isp)
1279{
1280}
1281
1282/*
1283 * omap3isp_csi2_init - Routine for module driver init
1284 */
1285int omap3isp_csi2_init(struct isp_device *isp)
1286{
1287 struct isp_csi2_device *csi2a = &isp->isp_csi2a;
1288 struct isp_csi2_device *csi2c = &isp->isp_csi2c;
1289 int ret;
1290
1291 csi2a->isp = isp;
1292 csi2a->available = 1;
1293 csi2a->regs1 = OMAP3_ISP_IOMEM_CSI2A_REGS1;
1294 csi2a->regs2 = OMAP3_ISP_IOMEM_CSI2A_REGS2;
1295 csi2a->phy = &isp->isp_csiphy2;
1296 csi2a->state = ISP_PIPELINE_STREAM_STOPPED;
1297 init_waitqueue_head(&csi2a->wait);
1298
1299 ret = csi2_init_entities(csi2a);
1300 if (ret < 0)
1301 goto fail;
1302
1303 if (isp->revision == ISP_REVISION_15_0) {
1304 csi2c->isp = isp;
1305 csi2c->available = 1;
1306 csi2c->regs1 = OMAP3_ISP_IOMEM_CSI2C_REGS1;
1307 csi2c->regs2 = OMAP3_ISP_IOMEM_CSI2C_REGS2;
1308 csi2c->phy = &isp->isp_csiphy1;
1309 csi2c->state = ISP_PIPELINE_STREAM_STOPPED;
1310 init_waitqueue_head(&csi2c->wait);
1311 }
1312
1313 return 0;
1314fail:
1315 omap3isp_csi2_cleanup(isp);
1316 return ret;
1317}
diff --git a/drivers/media/video/omap3isp/ispcsi2.h b/drivers/media/video/omap3isp/ispcsi2.h
new file mode 100644
index 00000000000..456fb7fb8a0
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispcsi2.h
@@ -0,0 +1,166 @@
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 bool use_fs_irq;
149
150 struct isp_csiphy *phy;
151 struct isp_csi2_ctx_cfg contexts[ISP_CSI2_MAX_CTX_NUM + 1];
152 struct isp_csi2_timing_cfg timing[2];
153 struct isp_csi2_ctrl_cfg ctrl;
154 enum isp_pipeline_stream_state state;
155 wait_queue_head_t wait;
156 atomic_t stopping;
157};
158
159int omap3isp_csi2_isr(struct isp_csi2_device *csi2);
160int omap3isp_csi2_reset(struct isp_csi2_device *csi2);
161int omap3isp_csi2_init(struct isp_device *isp);
162void omap3isp_csi2_cleanup(struct isp_device *isp);
163void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2);
164int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
165 struct v4l2_device *vdev);
166#endif /* OMAP3_ISP_CSI2_H */
diff --git a/drivers/media/video/omap3isp/ispcsiphy.c b/drivers/media/video/omap3isp/ispcsiphy.c
new file mode 100644
index 00000000000..5be37ce7d0c
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispcsiphy.c
@@ -0,0 +1,247 @@
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 omap3isp_csi2_reset(phy->csi2);
190
191 csiphy_dphy_config(phy);
192 csiphy_lanes_config(phy);
193
194 rval = csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_ON);
195 if (rval) {
196 regulator_disable(phy->vdd);
197 goto done;
198 }
199
200 csiphy_power_autoswitch_enable(phy, true);
201 phy->phy_in_use = 1;
202
203done:
204 mutex_unlock(&phy->mutex);
205 return rval;
206}
207
208void omap3isp_csiphy_release(struct isp_csiphy *phy)
209{
210 mutex_lock(&phy->mutex);
211 if (phy->phy_in_use) {
212 csiphy_power_autoswitch_enable(phy, false);
213 csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_OFF);
214 regulator_disable(phy->vdd);
215 phy->phy_in_use = 0;
216 }
217 mutex_unlock(&phy->mutex);
218}
219
220/*
221 * omap3isp_csiphy_init - Initialize the CSI PHY frontends
222 */
223int omap3isp_csiphy_init(struct isp_device *isp)
224{
225 struct isp_csiphy *phy1 = &isp->isp_csiphy1;
226 struct isp_csiphy *phy2 = &isp->isp_csiphy2;
227
228 isp->platform_cb.csiphy_config = csiphy_config;
229
230 phy2->isp = isp;
231 phy2->csi2 = &isp->isp_csi2a;
232 phy2->num_data_lanes = ISP_CSIPHY2_NUM_DATA_LANES;
233 phy2->cfg_regs = OMAP3_ISP_IOMEM_CSI2A_REGS1;
234 phy2->phy_regs = OMAP3_ISP_IOMEM_CSIPHY2;
235 mutex_init(&phy2->mutex);
236
237 if (isp->revision == ISP_REVISION_15_0) {
238 phy1->isp = isp;
239 phy1->csi2 = &isp->isp_csi2c;
240 phy1->num_data_lanes = ISP_CSIPHY1_NUM_DATA_LANES;
241 phy1->cfg_regs = OMAP3_ISP_IOMEM_CSI2C_REGS1;
242 phy1->phy_regs = OMAP3_ISP_IOMEM_CSIPHY1;
243 mutex_init(&phy1->mutex);
244 }
245
246 return 0;
247}
diff --git a/drivers/media/video/omap3isp/ispcsiphy.h b/drivers/media/video/omap3isp/ispcsiphy.h
new file mode 100644
index 00000000000..9596dc6830a
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispcsiphy.h
@@ -0,0 +1,74 @@
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
30struct isp_csi2_device;
31struct regulator;
32
33struct csiphy_lane {
34 u8 pos;
35 u8 pol;
36};
37
38#define ISP_CSIPHY2_NUM_DATA_LANES 2
39#define ISP_CSIPHY1_NUM_DATA_LANES 1
40
41struct isp_csiphy_lanes_cfg {
42 struct csiphy_lane data[ISP_CSIPHY2_NUM_DATA_LANES];
43 struct csiphy_lane clk;
44};
45
46struct isp_csiphy_dphy_cfg {
47 u8 ths_term;
48 u8 ths_settle;
49 u8 tclk_term;
50 unsigned tclk_miss:1;
51 u8 tclk_settle;
52};
53
54struct isp_csiphy {
55 struct isp_device *isp;
56 struct mutex mutex; /* serialize csiphy configuration */
57 u8 phy_in_use;
58 struct isp_csi2_device *csi2;
59 struct regulator *vdd;
60
61 /* mem resources - enums as defined in enum isp_mem_resources */
62 unsigned int cfg_regs;
63 unsigned int phy_regs;
64
65 u8 num_data_lanes; /* number of CSI2 Data Lanes supported */
66 struct isp_csiphy_lanes_cfg lanes;
67 struct isp_csiphy_dphy_cfg dphy;
68};
69
70int omap3isp_csiphy_acquire(struct isp_csiphy *phy);
71void omap3isp_csiphy_release(struct isp_csiphy *phy);
72int omap3isp_csiphy_init(struct isp_device *isp);
73
74#endif /* OMAP3_ISP_CSI_PHY_H */
diff --git a/drivers/media/video/omap3isp/isph3a.h b/drivers/media/video/omap3isp/isph3a.h
new file mode 100644
index 00000000000..fb09fd4ca75
--- /dev/null
+++ b/drivers/media/video/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/video/omap3isp/isph3a_aewb.c b/drivers/media/video/omap3isp/isph3a_aewb.c
new file mode 100644
index 00000000000..8068cefd8d8
--- /dev/null
+++ b/drivers/media/video/omap3isp/isph3a_aewb.c
@@ -0,0 +1,374 @@
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 /* This bit is already set if AF is enabled */
97 if (aewb->isp->isp_af.state != ISPSTAT_ENABLED)
98 isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
99 ISPCTRL_H3A_CLK_EN);
100 } else {
101 isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
102 ISPH3A_PCR_AEW_EN);
103 /* This bit can't be cleared if AF is enabled */
104 if (aewb->isp->isp_af.state != ISPSTAT_ENABLED)
105 isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
106 ISPCTRL_H3A_CLK_EN);
107 }
108}
109
110static int h3a_aewb_busy(struct ispstat *aewb)
111{
112 return isp_reg_readl(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
113 & ISPH3A_PCR_BUSYAEAWB;
114}
115
116static u32 h3a_aewb_get_buf_size(struct omap3isp_h3a_aewb_config *conf)
117{
118 /* Number of configured windows + extra row for black data */
119 u32 win_count = (conf->ver_win_count + 1) * conf->hor_win_count;
120
121 /*
122 * Unsaturated block counts for each 8 windows.
123 * 1 extra for the last (win_count % 8) windows if win_count is not
124 * divisible by 8.
125 */
126 win_count += (win_count + 7) / 8;
127
128 return win_count * AEWB_PACKET_SIZE;
129}
130
131static int h3a_aewb_validate_params(struct ispstat *aewb, void *new_conf)
132{
133 struct omap3isp_h3a_aewb_config *user_cfg = new_conf;
134 u32 buf_size;
135
136 if (unlikely(user_cfg->saturation_limit >
137 OMAP3ISP_AEWB_MAX_SATURATION_LIM))
138 return -EINVAL;
139
140 if (unlikely(user_cfg->win_height < OMAP3ISP_AEWB_MIN_WIN_H ||
141 user_cfg->win_height > OMAP3ISP_AEWB_MAX_WIN_H ||
142 user_cfg->win_height & 0x01))
143 return -EINVAL;
144
145 if (unlikely(user_cfg->win_width < OMAP3ISP_AEWB_MIN_WIN_W ||
146 user_cfg->win_width > OMAP3ISP_AEWB_MAX_WIN_W ||
147 user_cfg->win_width & 0x01))
148 return -EINVAL;
149
150 if (unlikely(user_cfg->ver_win_count < OMAP3ISP_AEWB_MIN_WINVC ||
151 user_cfg->ver_win_count > OMAP3ISP_AEWB_MAX_WINVC))
152 return -EINVAL;
153
154 if (unlikely(user_cfg->hor_win_count < OMAP3ISP_AEWB_MIN_WINHC ||
155 user_cfg->hor_win_count > OMAP3ISP_AEWB_MAX_WINHC))
156 return -EINVAL;
157
158 if (unlikely(user_cfg->ver_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
159 return -EINVAL;
160
161 if (unlikely(user_cfg->hor_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
162 return -EINVAL;
163
164 if (unlikely(user_cfg->blk_ver_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
165 return -EINVAL;
166
167 if (unlikely(user_cfg->blk_win_height < OMAP3ISP_AEWB_MIN_WIN_H ||
168 user_cfg->blk_win_height > OMAP3ISP_AEWB_MAX_WIN_H ||
169 user_cfg->blk_win_height & 0x01))
170 return -EINVAL;
171
172 if (unlikely(user_cfg->subsample_ver_inc < OMAP3ISP_AEWB_MIN_SUB_INC ||
173 user_cfg->subsample_ver_inc > OMAP3ISP_AEWB_MAX_SUB_INC ||
174 user_cfg->subsample_ver_inc & 0x01))
175 return -EINVAL;
176
177 if (unlikely(user_cfg->subsample_hor_inc < OMAP3ISP_AEWB_MIN_SUB_INC ||
178 user_cfg->subsample_hor_inc > OMAP3ISP_AEWB_MAX_SUB_INC ||
179 user_cfg->subsample_hor_inc & 0x01))
180 return -EINVAL;
181
182 buf_size = h3a_aewb_get_buf_size(user_cfg);
183 if (buf_size > user_cfg->buf_size)
184 user_cfg->buf_size = buf_size;
185 else if (user_cfg->buf_size > OMAP3ISP_AEWB_MAX_BUF_SIZE)
186 user_cfg->buf_size = OMAP3ISP_AEWB_MAX_BUF_SIZE;
187
188 return 0;
189}
190
191/*
192 * h3a_aewb_set_params - Helper function to check & store user given params.
193 * @new_conf: Pointer to AE and AWB parameters struct.
194 *
195 * As most of them are busy-lock registers, need to wait until AEW_BUSY = 0 to
196 * program them during ISR.
197 */
198static void h3a_aewb_set_params(struct ispstat *aewb, void *new_conf)
199{
200 struct omap3isp_h3a_aewb_config *user_cfg = new_conf;
201 struct omap3isp_h3a_aewb_config *cur_cfg = aewb->priv;
202 int update = 0;
203
204 if (cur_cfg->saturation_limit != user_cfg->saturation_limit) {
205 cur_cfg->saturation_limit = user_cfg->saturation_limit;
206 update = 1;
207 }
208 if (cur_cfg->alaw_enable != user_cfg->alaw_enable) {
209 cur_cfg->alaw_enable = user_cfg->alaw_enable;
210 update = 1;
211 }
212 if (cur_cfg->win_height != user_cfg->win_height) {
213 cur_cfg->win_height = user_cfg->win_height;
214 update = 1;
215 }
216 if (cur_cfg->win_width != user_cfg->win_width) {
217 cur_cfg->win_width = user_cfg->win_width;
218 update = 1;
219 }
220 if (cur_cfg->ver_win_count != user_cfg->ver_win_count) {
221 cur_cfg->ver_win_count = user_cfg->ver_win_count;
222 update = 1;
223 }
224 if (cur_cfg->hor_win_count != user_cfg->hor_win_count) {
225 cur_cfg->hor_win_count = user_cfg->hor_win_count;
226 update = 1;
227 }
228 if (cur_cfg->ver_win_start != user_cfg->ver_win_start) {
229 cur_cfg->ver_win_start = user_cfg->ver_win_start;
230 update = 1;
231 }
232 if (cur_cfg->hor_win_start != user_cfg->hor_win_start) {
233 cur_cfg->hor_win_start = user_cfg->hor_win_start;
234 update = 1;
235 }
236 if (cur_cfg->blk_ver_win_start != user_cfg->blk_ver_win_start) {
237 cur_cfg->blk_ver_win_start = user_cfg->blk_ver_win_start;
238 update = 1;
239 }
240 if (cur_cfg->blk_win_height != user_cfg->blk_win_height) {
241 cur_cfg->blk_win_height = user_cfg->blk_win_height;
242 update = 1;
243 }
244 if (cur_cfg->subsample_ver_inc != user_cfg->subsample_ver_inc) {
245 cur_cfg->subsample_ver_inc = user_cfg->subsample_ver_inc;
246 update = 1;
247 }
248 if (cur_cfg->subsample_hor_inc != user_cfg->subsample_hor_inc) {
249 cur_cfg->subsample_hor_inc = user_cfg->subsample_hor_inc;
250 update = 1;
251 }
252
253 if (update || !aewb->configured) {
254 aewb->inc_config++;
255 aewb->update = 1;
256 cur_cfg->buf_size = h3a_aewb_get_buf_size(cur_cfg);
257 }
258}
259
260static long h3a_aewb_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
261{
262 struct ispstat *stat = v4l2_get_subdevdata(sd);
263
264 switch (cmd) {
265 case VIDIOC_OMAP3ISP_AEWB_CFG:
266 return omap3isp_stat_config(stat, arg);
267 case VIDIOC_OMAP3ISP_STAT_REQ:
268 return omap3isp_stat_request_statistics(stat, arg);
269 case VIDIOC_OMAP3ISP_STAT_EN: {
270 unsigned long *en = arg;
271 return omap3isp_stat_enable(stat, !!*en);
272 }
273 }
274
275 return -ENOIOCTLCMD;
276}
277
278static const struct ispstat_ops h3a_aewb_ops = {
279 .validate_params = h3a_aewb_validate_params,
280 .set_params = h3a_aewb_set_params,
281 .setup_regs = h3a_aewb_setup_regs,
282 .enable = h3a_aewb_enable,
283 .busy = h3a_aewb_busy,
284};
285
286static const struct v4l2_subdev_core_ops h3a_aewb_subdev_core_ops = {
287 .ioctl = h3a_aewb_ioctl,
288 .subscribe_event = omap3isp_stat_subscribe_event,
289 .unsubscribe_event = omap3isp_stat_unsubscribe_event,
290};
291
292static const struct v4l2_subdev_video_ops h3a_aewb_subdev_video_ops = {
293 .s_stream = omap3isp_stat_s_stream,
294};
295
296static const struct v4l2_subdev_ops h3a_aewb_subdev_ops = {
297 .core = &h3a_aewb_subdev_core_ops,
298 .video = &h3a_aewb_subdev_video_ops,
299};
300
301/*
302 * omap3isp_h3a_aewb_init - Module Initialisation.
303 */
304int omap3isp_h3a_aewb_init(struct isp_device *isp)
305{
306 struct ispstat *aewb = &isp->isp_aewb;
307 struct omap3isp_h3a_aewb_config *aewb_cfg;
308 struct omap3isp_h3a_aewb_config *aewb_recover_cfg;
309 int ret;
310
311 aewb_cfg = kzalloc(sizeof(*aewb_cfg), GFP_KERNEL);
312 if (!aewb_cfg)
313 return -ENOMEM;
314
315 memset(aewb, 0, sizeof(*aewb));
316 aewb->ops = &h3a_aewb_ops;
317 aewb->priv = aewb_cfg;
318 aewb->dma_ch = -1;
319 aewb->event_type = V4L2_EVENT_OMAP3ISP_AEWB;
320 aewb->isp = isp;
321
322 /* Set recover state configuration */
323 aewb_recover_cfg = kzalloc(sizeof(*aewb_recover_cfg), GFP_KERNEL);
324 if (!aewb_recover_cfg) {
325 dev_err(aewb->isp->dev, "AEWB: cannot allocate memory for "
326 "recover configuration.\n");
327 ret = -ENOMEM;
328 goto err_recover_alloc;
329 }
330
331 aewb_recover_cfg->saturation_limit = OMAP3ISP_AEWB_MAX_SATURATION_LIM;
332 aewb_recover_cfg->win_height = OMAP3ISP_AEWB_MIN_WIN_H;
333 aewb_recover_cfg->win_width = OMAP3ISP_AEWB_MIN_WIN_W;
334 aewb_recover_cfg->ver_win_count = OMAP3ISP_AEWB_MIN_WINVC;
335 aewb_recover_cfg->hor_win_count = OMAP3ISP_AEWB_MIN_WINHC;
336 aewb_recover_cfg->blk_ver_win_start = aewb_recover_cfg->ver_win_start +
337 aewb_recover_cfg->win_height * aewb_recover_cfg->ver_win_count;
338 aewb_recover_cfg->blk_win_height = OMAP3ISP_AEWB_MIN_WIN_H;
339 aewb_recover_cfg->subsample_ver_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
340 aewb_recover_cfg->subsample_hor_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
341
342 if (h3a_aewb_validate_params(aewb, aewb_recover_cfg)) {
343 dev_err(aewb->isp->dev, "AEWB: recover configuration is "
344 "invalid.\n");
345 ret = -EINVAL;
346 goto err_conf;
347 }
348
349 aewb_recover_cfg->buf_size = h3a_aewb_get_buf_size(aewb_recover_cfg);
350 aewb->recover_priv = aewb_recover_cfg;
351
352 ret = omap3isp_stat_init(aewb, "AEWB", &h3a_aewb_subdev_ops);
353 if (ret)
354 goto err_conf;
355
356 return 0;
357
358err_conf:
359 kfree(aewb_recover_cfg);
360err_recover_alloc:
361 kfree(aewb_cfg);
362
363 return ret;
364}
365
366/*
367 * omap3isp_h3a_aewb_cleanup - Module exit.
368 */
369void omap3isp_h3a_aewb_cleanup(struct isp_device *isp)
370{
371 kfree(isp->isp_aewb.priv);
372 kfree(isp->isp_aewb.recover_priv);
373 omap3isp_stat_free(&isp->isp_aewb);
374}
diff --git a/drivers/media/video/omap3isp/isph3a_af.c b/drivers/media/video/omap3isp/isph3a_af.c
new file mode 100644
index 00000000000..ba54d0acdec
--- /dev/null
+++ b/drivers/media/video/omap3isp/isph3a_af.c
@@ -0,0 +1,429 @@
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 /* This bit is already set if AEWB is enabled */
147 if (af->isp->isp_aewb.state != ISPSTAT_ENABLED)
148 isp_reg_set(af->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
149 ISPCTRL_H3A_CLK_EN);
150 } else {
151 isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
152 ISPH3A_PCR_AF_EN);
153 /* This bit can't be cleared if AEWB is enabled */
154 if (af->isp->isp_aewb.state != ISPSTAT_ENABLED)
155 isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
156 ISPCTRL_H3A_CLK_EN);
157 }
158}
159
160static int h3a_af_busy(struct ispstat *af)
161{
162 return isp_reg_readl(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
163 & ISPH3A_PCR_BUSYAF;
164}
165
166static u32 h3a_af_get_buf_size(struct omap3isp_h3a_af_config *conf)
167{
168 return conf->paxel.h_cnt * conf->paxel.v_cnt * OMAP3ISP_AF_PAXEL_SIZE;
169}
170
171/* Function to check paxel parameters */
172static int h3a_af_validate_params(struct ispstat *af, void *new_conf)
173{
174 struct omap3isp_h3a_af_config *user_cfg = new_conf;
175 struct omap3isp_h3a_af_paxel *paxel_cfg = &user_cfg->paxel;
176 struct omap3isp_h3a_af_iir *iir_cfg = &user_cfg->iir;
177 int index;
178 u32 buf_size;
179
180 /* Check horizontal Count */
181 if (IS_OUT_OF_BOUNDS(paxel_cfg->h_cnt,
182 OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN,
183 OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MAX))
184 return -EINVAL;
185
186 /* Check Vertical Count */
187 if (IS_OUT_OF_BOUNDS(paxel_cfg->v_cnt,
188 OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN,
189 OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MAX))
190 return -EINVAL;
191
192 if (IS_OUT_OF_BOUNDS(paxel_cfg->height, OMAP3ISP_AF_PAXEL_HEIGHT_MIN,
193 OMAP3ISP_AF_PAXEL_HEIGHT_MAX) ||
194 paxel_cfg->height % 2)
195 return -EINVAL;
196
197 /* Check width */
198 if (IS_OUT_OF_BOUNDS(paxel_cfg->width, OMAP3ISP_AF_PAXEL_WIDTH_MIN,
199 OMAP3ISP_AF_PAXEL_WIDTH_MAX) ||
200 paxel_cfg->width % 2)
201 return -EINVAL;
202
203 /* Check Line Increment */
204 if (IS_OUT_OF_BOUNDS(paxel_cfg->line_inc,
205 OMAP3ISP_AF_PAXEL_INCREMENT_MIN,
206 OMAP3ISP_AF_PAXEL_INCREMENT_MAX) ||
207 paxel_cfg->line_inc % 2)
208 return -EINVAL;
209
210 /* Check Horizontal Start */
211 if ((paxel_cfg->h_start < iir_cfg->h_start) ||
212 IS_OUT_OF_BOUNDS(paxel_cfg->h_start,
213 OMAP3ISP_AF_PAXEL_HZSTART_MIN,
214 OMAP3ISP_AF_PAXEL_HZSTART_MAX))
215 return -EINVAL;
216
217 /* Check IIR */
218 for (index = 0; index < OMAP3ISP_AF_NUM_COEF; index++) {
219 if ((iir_cfg->coeff_set0[index]) > OMAP3ISP_AF_COEF_MAX)
220 return -EINVAL;
221
222 if ((iir_cfg->coeff_set1[index]) > OMAP3ISP_AF_COEF_MAX)
223 return -EINVAL;
224 }
225
226 if (IS_OUT_OF_BOUNDS(iir_cfg->h_start, OMAP3ISP_AF_IIRSH_MIN,
227 OMAP3ISP_AF_IIRSH_MAX))
228 return -EINVAL;
229
230 /* Hack: If paxel size is 12, the 10th AF window may be corrupted */
231 if ((paxel_cfg->h_cnt * paxel_cfg->v_cnt > 9) &&
232 (paxel_cfg->width * paxel_cfg->height == 12))
233 return -EINVAL;
234
235 buf_size = h3a_af_get_buf_size(user_cfg);
236 if (buf_size > user_cfg->buf_size)
237 /* User buf_size request wasn't enough */
238 user_cfg->buf_size = buf_size;
239 else if (user_cfg->buf_size > OMAP3ISP_AF_MAX_BUF_SIZE)
240 user_cfg->buf_size = OMAP3ISP_AF_MAX_BUF_SIZE;
241
242 return 0;
243}
244
245/* Update local parameters */
246static void h3a_af_set_params(struct ispstat *af, void *new_conf)
247{
248 struct omap3isp_h3a_af_config *user_cfg = new_conf;
249 struct omap3isp_h3a_af_config *cur_cfg = af->priv;
250 int update = 0;
251 int index;
252
253 /* alaw */
254 if (cur_cfg->alaw_enable != user_cfg->alaw_enable) {
255 update = 1;
256 goto out;
257 }
258
259 /* hmf */
260 if (cur_cfg->hmf.enable != user_cfg->hmf.enable) {
261 update = 1;
262 goto out;
263 }
264 if (cur_cfg->hmf.threshold != user_cfg->hmf.threshold) {
265 update = 1;
266 goto out;
267 }
268
269 /* rgbpos */
270 if (cur_cfg->rgb_pos != user_cfg->rgb_pos) {
271 update = 1;
272 goto out;
273 }
274
275 /* iir */
276 if (cur_cfg->iir.h_start != user_cfg->iir.h_start) {
277 update = 1;
278 goto out;
279 }
280 for (index = 0; index < OMAP3ISP_AF_NUM_COEF; index++) {
281 if (cur_cfg->iir.coeff_set0[index] !=
282 user_cfg->iir.coeff_set0[index]) {
283 update = 1;
284 goto out;
285 }
286 if (cur_cfg->iir.coeff_set1[index] !=
287 user_cfg->iir.coeff_set1[index]) {
288 update = 1;
289 goto out;
290 }
291 }
292
293 /* paxel */
294 if ((cur_cfg->paxel.width != user_cfg->paxel.width) ||
295 (cur_cfg->paxel.height != user_cfg->paxel.height) ||
296 (cur_cfg->paxel.h_start != user_cfg->paxel.h_start) ||
297 (cur_cfg->paxel.v_start != user_cfg->paxel.v_start) ||
298 (cur_cfg->paxel.h_cnt != user_cfg->paxel.h_cnt) ||
299 (cur_cfg->paxel.v_cnt != user_cfg->paxel.v_cnt) ||
300 (cur_cfg->paxel.line_inc != user_cfg->paxel.line_inc)) {
301 update = 1;
302 goto out;
303 }
304
305 /* af_mode */
306 if (cur_cfg->fvmode != user_cfg->fvmode)
307 update = 1;
308
309out:
310 if (update || !af->configured) {
311 memcpy(cur_cfg, user_cfg, sizeof(*cur_cfg));
312 af->inc_config++;
313 af->update = 1;
314 /*
315 * User might be asked for a bigger buffer than necessary for
316 * this configuration. In order to return the right amount of
317 * data during buffer request, let's calculate the size here
318 * instead of stick with user_cfg->buf_size.
319 */
320 cur_cfg->buf_size = h3a_af_get_buf_size(cur_cfg);
321 }
322}
323
324static long h3a_af_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
325{
326 struct ispstat *stat = v4l2_get_subdevdata(sd);
327
328 switch (cmd) {
329 case VIDIOC_OMAP3ISP_AF_CFG:
330 return omap3isp_stat_config(stat, arg);
331 case VIDIOC_OMAP3ISP_STAT_REQ:
332 return omap3isp_stat_request_statistics(stat, arg);
333 case VIDIOC_OMAP3ISP_STAT_EN: {
334 int *en = arg;
335 return omap3isp_stat_enable(stat, !!*en);
336 }
337 }
338
339 return -ENOIOCTLCMD;
340
341}
342
343static const struct ispstat_ops h3a_af_ops = {
344 .validate_params = h3a_af_validate_params,
345 .set_params = h3a_af_set_params,
346 .setup_regs = h3a_af_setup_regs,
347 .enable = h3a_af_enable,
348 .busy = h3a_af_busy,
349};
350
351static const struct v4l2_subdev_core_ops h3a_af_subdev_core_ops = {
352 .ioctl = h3a_af_ioctl,
353 .subscribe_event = omap3isp_stat_subscribe_event,
354 .unsubscribe_event = omap3isp_stat_unsubscribe_event,
355};
356
357static const struct v4l2_subdev_video_ops h3a_af_subdev_video_ops = {
358 .s_stream = omap3isp_stat_s_stream,
359};
360
361static const struct v4l2_subdev_ops h3a_af_subdev_ops = {
362 .core = &h3a_af_subdev_core_ops,
363 .video = &h3a_af_subdev_video_ops,
364};
365
366/* Function to register the AF character device driver. */
367int omap3isp_h3a_af_init(struct isp_device *isp)
368{
369 struct ispstat *af = &isp->isp_af;
370 struct omap3isp_h3a_af_config *af_cfg;
371 struct omap3isp_h3a_af_config *af_recover_cfg;
372 int ret;
373
374 af_cfg = kzalloc(sizeof(*af_cfg), GFP_KERNEL);
375 if (af_cfg == NULL)
376 return -ENOMEM;
377
378 memset(af, 0, sizeof(*af));
379 af->ops = &h3a_af_ops;
380 af->priv = af_cfg;
381 af->dma_ch = -1;
382 af->event_type = V4L2_EVENT_OMAP3ISP_AF;
383 af->isp = isp;
384
385 /* Set recover state configuration */
386 af_recover_cfg = kzalloc(sizeof(*af_recover_cfg), GFP_KERNEL);
387 if (!af_recover_cfg) {
388 dev_err(af->isp->dev, "AF: cannot allocate memory for recover "
389 "configuration.\n");
390 ret = -ENOMEM;
391 goto err_recover_alloc;
392 }
393
394 af_recover_cfg->paxel.h_start = OMAP3ISP_AF_PAXEL_HZSTART_MIN;
395 af_recover_cfg->paxel.width = OMAP3ISP_AF_PAXEL_WIDTH_MIN;
396 af_recover_cfg->paxel.height = OMAP3ISP_AF_PAXEL_HEIGHT_MIN;
397 af_recover_cfg->paxel.h_cnt = OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN;
398 af_recover_cfg->paxel.v_cnt = OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN;
399 af_recover_cfg->paxel.line_inc = OMAP3ISP_AF_PAXEL_INCREMENT_MIN;
400 if (h3a_af_validate_params(af, af_recover_cfg)) {
401 dev_err(af->isp->dev, "AF: recover configuration is "
402 "invalid.\n");
403 ret = -EINVAL;
404 goto err_conf;
405 }
406
407 af_recover_cfg->buf_size = h3a_af_get_buf_size(af_recover_cfg);
408 af->recover_priv = af_recover_cfg;
409
410 ret = omap3isp_stat_init(af, "AF", &h3a_af_subdev_ops);
411 if (ret)
412 goto err_conf;
413
414 return 0;
415
416err_conf:
417 kfree(af_recover_cfg);
418err_recover_alloc:
419 kfree(af_cfg);
420
421 return ret;
422}
423
424void omap3isp_h3a_af_cleanup(struct isp_device *isp)
425{
426 kfree(isp->isp_af.priv);
427 kfree(isp->isp_af.recover_priv);
428 omap3isp_stat_free(&isp->isp_af);
429}
diff --git a/drivers/media/video/omap3isp/isphist.c b/drivers/media/video/omap3isp/isphist.c
new file mode 100644
index 00000000000..1743856b30d
--- /dev/null
+++ b/drivers/media/video/omap3isp/isphist.c
@@ -0,0 +1,520 @@
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 isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
171 ISPCTRL_HIST_CLK_EN);
172 } else {
173 isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR,
174 ISPHIST_PCR_ENABLE);
175 isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
176 ISPCTRL_HIST_CLK_EN);
177 }
178}
179
180static int hist_busy(struct ispstat *hist)
181{
182 return isp_reg_readl(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR)
183 & ISPHIST_PCR_BUSY;
184}
185
186static void hist_dma_cb(int lch, u16 ch_status, void *data)
187{
188 struct ispstat *hist = data;
189
190 if (ch_status & ~OMAP_DMA_BLOCK_IRQ) {
191 dev_dbg(hist->isp->dev, "hist: DMA error. status = 0x%04x\n",
192 ch_status);
193 omap_stop_dma(lch);
194 hist_reset_mem(hist);
195 atomic_set(&hist->buf_err, 1);
196 }
197 isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
198 ISPHIST_CNT_CLEAR);
199
200 omap3isp_stat_dma_isr(hist);
201 if (hist->state != ISPSTAT_DISABLED)
202 omap3isp_hist_dma_done(hist->isp);
203}
204
205static int hist_buf_dma(struct ispstat *hist)
206{
207 dma_addr_t dma_addr = hist->active_buf->dma_addr;
208
209 if (unlikely(!dma_addr)) {
210 dev_dbg(hist->isp->dev, "hist: invalid DMA buffer address\n");
211 hist_reset_mem(hist);
212 return STAT_NO_BUF;
213 }
214
215 isp_reg_writel(hist->isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
216 isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
217 ISPHIST_CNT_CLEAR);
218 omap3isp_flush(hist->isp);
219 hist->dma_config.dst_start = dma_addr;
220 hist->dma_config.elem_count = hist->buf_size / sizeof(u32);
221 omap_set_dma_params(hist->dma_ch, &hist->dma_config);
222
223 omap_start_dma(hist->dma_ch);
224
225 return STAT_BUF_WAITING_DMA;
226}
227
228static int hist_buf_pio(struct ispstat *hist)
229{
230 struct isp_device *isp = hist->isp;
231 u32 *buf = hist->active_buf->virt_addr;
232 unsigned int i;
233
234 if (!buf) {
235 dev_dbg(isp->dev, "hist: invalid PIO buffer address\n");
236 hist_reset_mem(hist);
237 return STAT_NO_BUF;
238 }
239
240 isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
241
242 /*
243 * By setting it, the histogram internal buffer is being cleared at the
244 * same time it's being read. This bit must be cleared just after all
245 * data is acquired.
246 */
247 isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);
248
249 /*
250 * We'll read 4 times a 4-bytes-word at each iteration for
251 * optimization. It avoids 3/4 of the jumps. We also know buf_size is
252 * divisible by 16.
253 */
254 for (i = hist->buf_size / 16; i > 0; i--) {
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 *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
258 *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
259 }
260 isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
261 ISPHIST_CNT_CLEAR);
262
263 return STAT_BUF_DONE;
264}
265
266/*
267 * hist_buf_process - Callback from ISP driver for HIST interrupt.
268 */
269static int hist_buf_process(struct ispstat *hist)
270{
271 struct omap3isp_hist_config *user_cfg = hist->priv;
272 int ret;
273
274 if (atomic_read(&hist->buf_err) || hist->state != ISPSTAT_ENABLED) {
275 hist_reset_mem(hist);
276 return STAT_NO_BUF;
277 }
278
279 if (--(hist->wait_acc_frames))
280 return STAT_NO_BUF;
281
282 if (HIST_USING_DMA(hist))
283 ret = hist_buf_dma(hist);
284 else
285 ret = hist_buf_pio(hist);
286
287 hist->wait_acc_frames = user_cfg->num_acc_frames;
288
289 return ret;
290}
291
292static u32 hist_get_buf_size(struct omap3isp_hist_config *conf)
293{
294 return OMAP3ISP_HIST_MEM_SIZE_BINS(conf->hist_bins) * conf->num_regions;
295}
296
297/*
298 * hist_validate_params - Helper function to check user given params.
299 * @user_cfg: Pointer to user configuration structure.
300 *
301 * Returns 0 on success configuration.
302 */
303static int hist_validate_params(struct ispstat *hist, void *new_conf)
304{
305 struct omap3isp_hist_config *user_cfg = new_conf;
306 int c;
307 u32 buf_size;
308
309 if (user_cfg->cfa > OMAP3ISP_HIST_CFA_FOVEONX3)
310 return -EINVAL;
311
312 /* Regions size and position */
313
314 if ((user_cfg->num_regions < OMAP3ISP_HIST_MIN_REGIONS) ||
315 (user_cfg->num_regions > OMAP3ISP_HIST_MAX_REGIONS))
316 return -EINVAL;
317
318 /* Regions */
319 for (c = 0; c < user_cfg->num_regions; c++) {
320 if (user_cfg->region[c].h_start & ~ISPHIST_REG_START_END_MASK)
321 return -EINVAL;
322 if (user_cfg->region[c].h_end & ~ISPHIST_REG_START_END_MASK)
323 return -EINVAL;
324 if (user_cfg->region[c].v_start & ~ISPHIST_REG_START_END_MASK)
325 return -EINVAL;
326 if (user_cfg->region[c].v_end & ~ISPHIST_REG_START_END_MASK)
327 return -EINVAL;
328 if (user_cfg->region[c].h_start > user_cfg->region[c].h_end)
329 return -EINVAL;
330 if (user_cfg->region[c].v_start > user_cfg->region[c].v_end)
331 return -EINVAL;
332 }
333
334 switch (user_cfg->num_regions) {
335 case 1:
336 if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_256)
337 return -EINVAL;
338 break;
339 case 2:
340 if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_128)
341 return -EINVAL;
342 break;
343 default: /* 3 or 4 */
344 if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_64)
345 return -EINVAL;
346 break;
347 }
348
349 buf_size = hist_get_buf_size(user_cfg);
350 if (buf_size > user_cfg->buf_size)
351 /* User's buf_size request wasn't enoght */
352 user_cfg->buf_size = buf_size;
353 else if (user_cfg->buf_size > OMAP3ISP_HIST_MAX_BUF_SIZE)
354 user_cfg->buf_size = OMAP3ISP_HIST_MAX_BUF_SIZE;
355
356 return 0;
357}
358
359static int hist_comp_params(struct ispstat *hist,
360 struct omap3isp_hist_config *user_cfg)
361{
362 struct omap3isp_hist_config *cur_cfg = hist->priv;
363 int c;
364
365 if (cur_cfg->cfa != user_cfg->cfa)
366 return 1;
367
368 if (cur_cfg->num_acc_frames != user_cfg->num_acc_frames)
369 return 1;
370
371 if (cur_cfg->hist_bins != user_cfg->hist_bins)
372 return 1;
373
374 for (c = 0; c < OMAP3ISP_HIST_MAX_WG; c++) {
375 if (c == 3 && user_cfg->cfa == OMAP3ISP_HIST_CFA_FOVEONX3)
376 break;
377 else if (cur_cfg->wg[c] != user_cfg->wg[c])
378 return 1;
379 }
380
381 if (cur_cfg->num_regions != user_cfg->num_regions)
382 return 1;
383
384 /* Regions */
385 for (c = 0; c < user_cfg->num_regions; c++) {
386 if (cur_cfg->region[c].h_start != user_cfg->region[c].h_start)
387 return 1;
388 if (cur_cfg->region[c].h_end != user_cfg->region[c].h_end)
389 return 1;
390 if (cur_cfg->region[c].v_start != user_cfg->region[c].v_start)
391 return 1;
392 if (cur_cfg->region[c].v_end != user_cfg->region[c].v_end)
393 return 1;
394 }
395
396 return 0;
397}
398
399/*
400 * hist_update_params - Helper function to check and store user given params.
401 * @new_conf: Pointer to user configuration structure.
402 */
403static void hist_set_params(struct ispstat *hist, void *new_conf)
404{
405 struct omap3isp_hist_config *user_cfg = new_conf;
406 struct omap3isp_hist_config *cur_cfg = hist->priv;
407
408 if (!hist->configured || hist_comp_params(hist, user_cfg)) {
409 memcpy(cur_cfg, user_cfg, sizeof(*user_cfg));
410 if (user_cfg->num_acc_frames == 0)
411 user_cfg->num_acc_frames = 1;
412 hist->inc_config++;
413 hist->update = 1;
414 /*
415 * User might be asked for a bigger buffer than necessary for
416 * this configuration. In order to return the right amount of
417 * data during buffer request, let's calculate the size here
418 * instead of stick with user_cfg->buf_size.
419 */
420 cur_cfg->buf_size = hist_get_buf_size(cur_cfg);
421
422 }
423}
424
425static long hist_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
426{
427 struct ispstat *stat = v4l2_get_subdevdata(sd);
428
429 switch (cmd) {
430 case VIDIOC_OMAP3ISP_HIST_CFG:
431 return omap3isp_stat_config(stat, arg);
432 case VIDIOC_OMAP3ISP_STAT_REQ:
433 return omap3isp_stat_request_statistics(stat, arg);
434 case VIDIOC_OMAP3ISP_STAT_EN: {
435 int *en = arg;
436 return omap3isp_stat_enable(stat, !!*en);
437 }
438 }
439
440 return -ENOIOCTLCMD;
441
442}
443
444static const struct ispstat_ops hist_ops = {
445 .validate_params = hist_validate_params,
446 .set_params = hist_set_params,
447 .setup_regs = hist_setup_regs,
448 .enable = hist_enable,
449 .busy = hist_busy,
450 .buf_process = hist_buf_process,
451};
452
453static const struct v4l2_subdev_core_ops hist_subdev_core_ops = {
454 .ioctl = hist_ioctl,
455 .subscribe_event = omap3isp_stat_subscribe_event,
456 .unsubscribe_event = omap3isp_stat_unsubscribe_event,
457};
458
459static const struct v4l2_subdev_video_ops hist_subdev_video_ops = {
460 .s_stream = omap3isp_stat_s_stream,
461};
462
463static const struct v4l2_subdev_ops hist_subdev_ops = {
464 .core = &hist_subdev_core_ops,
465 .video = &hist_subdev_video_ops,
466};
467
468/*
469 * omap3isp_hist_init - Module Initialization.
470 */
471int omap3isp_hist_init(struct isp_device *isp)
472{
473 struct ispstat *hist = &isp->isp_hist;
474 struct omap3isp_hist_config *hist_cfg;
475 int ret = -1;
476
477 hist_cfg = kzalloc(sizeof(*hist_cfg), GFP_KERNEL);
478 if (hist_cfg == NULL)
479 return -ENOMEM;
480
481 memset(hist, 0, sizeof(*hist));
482 if (HIST_CONFIG_DMA)
483 ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, "DMA_ISP_HIST",
484 hist_dma_cb, hist, &hist->dma_ch);
485 if (ret) {
486 if (HIST_CONFIG_DMA)
487 dev_warn(isp->dev, "hist: DMA request channel failed. "
488 "Using PIO only.\n");
489 hist->dma_ch = -1;
490 } else {
491 dev_dbg(isp->dev, "hist: DMA channel = %d\n", hist->dma_ch);
492 hist_dma_config(hist);
493 omap_enable_dma_irq(hist->dma_ch, OMAP_DMA_BLOCK_IRQ);
494 }
495
496 hist->ops = &hist_ops;
497 hist->priv = hist_cfg;
498 hist->event_type = V4L2_EVENT_OMAP3ISP_HIST;
499 hist->isp = isp;
500
501 ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops);
502 if (ret) {
503 kfree(hist_cfg);
504 if (HIST_USING_DMA(hist))
505 omap_free_dma(hist->dma_ch);
506 }
507
508 return ret;
509}
510
511/*
512 * omap3isp_hist_cleanup - Module cleanup.
513 */
514void omap3isp_hist_cleanup(struct isp_device *isp)
515{
516 if (HIST_USING_DMA(&isp->isp_hist))
517 omap_free_dma(isp->isp_hist.dma_ch);
518 kfree(isp->isp_hist.priv);
519 omap3isp_stat_free(&isp->isp_hist);
520}
diff --git a/drivers/media/video/omap3isp/isphist.h b/drivers/media/video/omap3isp/isphist.h
new file mode 100644
index 00000000000..0b2a38ec94c
--- /dev/null
+++ b/drivers/media/video/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/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c
new file mode 100644
index 00000000000..aba537af87e
--- /dev/null
+++ b/drivers/media/video/omap3isp/isppreview.c
@@ -0,0 +1,2113 @@
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#define PREV_MIN_WIDTH 64
80#define PREV_MIN_HEIGHT 8
81#define PREV_MAX_HEIGHT 16384
82
83/*
84 * Coeficient Tables for the submodules in Preview.
85 * Array is initialised with the values from.the tables text file.
86 */
87
88/*
89 * CFA Filter Coefficient Table
90 *
91 */
92static u32 cfa_coef_table[] = {
93#include "cfa_coef_table.h"
94};
95
96/*
97 * Default Gamma Correction Table - All components
98 */
99static u32 gamma_table[] = {
100#include "gamma_table.h"
101};
102
103/*
104 * Noise Filter Threshold table
105 */
106static u32 noise_filter_table[] = {
107#include "noise_filter_table.h"
108};
109
110/*
111 * Luminance Enhancement Table
112 */
113static u32 luma_enhance_table[] = {
114#include "luma_enhance_table.h"
115};
116
117/*
118 * preview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview.
119 * @enable: 1 - Reverse the A-Law done in CCDC.
120 */
121static void
122preview_enable_invalaw(struct isp_prev_device *prev, u8 enable)
123{
124 struct isp_device *isp = to_isp_device(prev);
125
126 if (enable)
127 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
128 ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
129 else
130 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
131 ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
132}
133
134/*
135 * preview_enable_drkframe_capture - Enable/Disable of the darkframe capture.
136 * @prev -
137 * @enable: 1 - Enable, 0 - Disable
138 *
139 * NOTE: PRV_WSDR_ADDR and PRV_WADD_OFFSET must be set also
140 * The process is applied for each captured frame.
141 */
142static void
143preview_enable_drkframe_capture(struct isp_prev_device *prev, u8 enable)
144{
145 struct isp_device *isp = to_isp_device(prev);
146
147 if (enable)
148 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
149 ISPPRV_PCR_DRKFCAP);
150 else
151 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
152 ISPPRV_PCR_DRKFCAP);
153}
154
155/*
156 * preview_enable_drkframe - Enable/Disable of the darkframe subtract.
157 * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is
158 * subtracted with the pixels in the current frame.
159 *
160 * The process is applied for each captured frame.
161 */
162static void
163preview_enable_drkframe(struct isp_prev_device *prev, u8 enable)
164{
165 struct isp_device *isp = to_isp_device(prev);
166
167 if (enable)
168 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
169 ISPPRV_PCR_DRKFEN);
170 else
171 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
172 ISPPRV_PCR_DRKFEN);
173}
174
175/*
176 * preview_config_drkf_shadcomp - Configures shift value in shading comp.
177 * @scomp_shtval: 3bit value of shift used in shading compensation.
178 */
179static void
180preview_config_drkf_shadcomp(struct isp_prev_device *prev,
181 const void *scomp_shtval)
182{
183 struct isp_device *isp = to_isp_device(prev);
184 const u32 *shtval = scomp_shtval;
185
186 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
187 ISPPRV_PCR_SCOMP_SFT_MASK,
188 *shtval << ISPPRV_PCR_SCOMP_SFT_SHIFT);
189}
190
191/*
192 * preview_enable_hmed - Enables/Disables of the Horizontal Median Filter.
193 * @enable: 1 - Enables Horizontal Median Filter.
194 */
195static void
196preview_enable_hmed(struct isp_prev_device *prev, u8 enable)
197{
198 struct isp_device *isp = to_isp_device(prev);
199
200 if (enable)
201 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
202 ISPPRV_PCR_HMEDEN);
203 else
204 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
205 ISPPRV_PCR_HMEDEN);
206}
207
208/*
209 * preview_config_hmed - Configures the Horizontal Median Filter.
210 * @prev_hmed: Structure containing the odd and even distance between the
211 * pixels in the image along with the filter threshold.
212 */
213static void
214preview_config_hmed(struct isp_prev_device *prev, const void *prev_hmed)
215{
216 struct isp_device *isp = to_isp_device(prev);
217 const struct omap3isp_prev_hmed *hmed = prev_hmed;
218
219 isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) |
220 (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) |
221 (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT),
222 OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
223}
224
225/*
226 * preview_config_noisefilter - Configures the Noise Filter.
227 * @prev_nf: Structure containing the noisefilter table, strength to be used
228 * for the noise filter and the defect correction enable flag.
229 */
230static void
231preview_config_noisefilter(struct isp_prev_device *prev, const void *prev_nf)
232{
233 struct isp_device *isp = to_isp_device(prev);
234 const struct omap3isp_prev_nf *nf = prev_nf;
235 unsigned int i;
236
237 isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
238 isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR,
239 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
240 for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) {
241 isp_reg_writel(isp, nf->table[i],
242 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
243 }
244}
245
246/*
247 * preview_config_dcor - Configures the defect correction
248 * @prev_dcor: Structure containing the defect correct thresholds
249 */
250static void
251preview_config_dcor(struct isp_prev_device *prev, const void *prev_dcor)
252{
253 struct isp_device *isp = to_isp_device(prev);
254 const struct omap3isp_prev_dcor *dcor = prev_dcor;
255
256 isp_reg_writel(isp, dcor->detect_correct[0],
257 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
258 isp_reg_writel(isp, dcor->detect_correct[1],
259 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
260 isp_reg_writel(isp, dcor->detect_correct[2],
261 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
262 isp_reg_writel(isp, dcor->detect_correct[3],
263 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
264 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
265 ISPPRV_PCR_DCCOUP,
266 dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0);
267}
268
269/*
270 * preview_config_cfa - Configures the CFA Interpolation parameters.
271 * @prev_cfa: Structure containing the CFA interpolation table, CFA format
272 * in the image, vertical and horizontal gradient threshold.
273 */
274static void
275preview_config_cfa(struct isp_prev_device *prev, const void *prev_cfa)
276{
277 struct isp_device *isp = to_isp_device(prev);
278 const struct omap3isp_prev_cfa *cfa = prev_cfa;
279 unsigned int i;
280
281 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
282 ISPPRV_PCR_CFAFMT_MASK,
283 cfa->format << ISPPRV_PCR_CFAFMT_SHIFT);
284
285 isp_reg_writel(isp,
286 (cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
287 (cfa->gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
288 OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
289
290 isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR,
291 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
292
293 for (i = 0; i < OMAP3ISP_PREV_CFA_TBL_SIZE; i++) {
294 isp_reg_writel(isp, cfa->table[i],
295 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
296 }
297}
298
299/*
300 * preview_config_gammacorrn - Configures the Gamma Correction table values
301 * @gtable: Structure containing the table for red, blue, green gamma table.
302 */
303static void
304preview_config_gammacorrn(struct isp_prev_device *prev, const void *gtable)
305{
306 struct isp_device *isp = to_isp_device(prev);
307 const struct omap3isp_prev_gtables *gt = gtable;
308 unsigned int i;
309
310 isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR,
311 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
312 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
313 isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV,
314 ISPPRV_SET_TBL_DATA);
315
316 isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR,
317 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
318 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
319 isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV,
320 ISPPRV_SET_TBL_DATA);
321
322 isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR,
323 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
324 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
325 isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV,
326 ISPPRV_SET_TBL_DATA);
327}
328
329/*
330 * preview_config_luma_enhancement - Sets the Luminance Enhancement table.
331 * @ytable: Structure containing the table for Luminance Enhancement table.
332 */
333static void
334preview_config_luma_enhancement(struct isp_prev_device *prev,
335 const void *ytable)
336{
337 struct isp_device *isp = to_isp_device(prev);
338 const struct omap3isp_prev_luma *yt = ytable;
339 unsigned int i;
340
341 isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR,
342 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
343 for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) {
344 isp_reg_writel(isp, yt->table[i],
345 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
346 }
347}
348
349/*
350 * preview_config_chroma_suppression - Configures the Chroma Suppression.
351 * @csup: Structure containing the threshold value for suppression
352 * and the hypass filter enable flag.
353 */
354static void
355preview_config_chroma_suppression(struct isp_prev_device *prev,
356 const void *csup)
357{
358 struct isp_device *isp = to_isp_device(prev);
359 const struct omap3isp_prev_csup *cs = csup;
360
361 isp_reg_writel(isp,
362 cs->gain | (cs->thres << ISPPRV_CSUP_THRES_SHIFT) |
363 (cs->hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
364 OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
365}
366
367/*
368 * preview_enable_noisefilter - Enables/Disables the Noise Filter.
369 * @enable: 1 - Enables the Noise Filter.
370 */
371static void
372preview_enable_noisefilter(struct isp_prev_device *prev, u8 enable)
373{
374 struct isp_device *isp = to_isp_device(prev);
375
376 if (enable)
377 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
378 ISPPRV_PCR_NFEN);
379 else
380 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
381 ISPPRV_PCR_NFEN);
382}
383
384/*
385 * preview_enable_dcor - Enables/Disables the defect correction.
386 * @enable: 1 - Enables the defect correction.
387 */
388static void
389preview_enable_dcor(struct isp_prev_device *prev, u8 enable)
390{
391 struct isp_device *isp = to_isp_device(prev);
392
393 if (enable)
394 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
395 ISPPRV_PCR_DCOREN);
396 else
397 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
398 ISPPRV_PCR_DCOREN);
399}
400
401/*
402 * preview_enable_cfa - Enable/Disable the CFA Interpolation.
403 * @enable: 1 - Enables the CFA.
404 */
405static void
406preview_enable_cfa(struct isp_prev_device *prev, u8 enable)
407{
408 struct isp_device *isp = to_isp_device(prev);
409
410 if (enable)
411 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
412 ISPPRV_PCR_CFAEN);
413 else
414 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
415 ISPPRV_PCR_CFAEN);
416}
417
418/*
419 * preview_enable_gammabypass - Enables/Disables the GammaByPass
420 * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB.
421 * 0 - Goes through Gamma Correction. input and output is 10bit.
422 */
423static void
424preview_enable_gammabypass(struct isp_prev_device *prev, u8 enable)
425{
426 struct isp_device *isp = to_isp_device(prev);
427
428 if (enable)
429 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
430 ISPPRV_PCR_GAMMA_BYPASS);
431 else
432 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
433 ISPPRV_PCR_GAMMA_BYPASS);
434}
435
436/*
437 * preview_enable_luma_enhancement - Enables/Disables Luminance Enhancement
438 * @enable: 1 - Enable the Luminance Enhancement.
439 */
440static void
441preview_enable_luma_enhancement(struct isp_prev_device *prev, u8 enable)
442{
443 struct isp_device *isp = to_isp_device(prev);
444
445 if (enable)
446 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
447 ISPPRV_PCR_YNENHEN);
448 else
449 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
450 ISPPRV_PCR_YNENHEN);
451}
452
453/*
454 * preview_enable_chroma_suppression - Enables/Disables Chrominance Suppr.
455 * @enable: 1 - Enable the Chrominance Suppression.
456 */
457static void
458preview_enable_chroma_suppression(struct isp_prev_device *prev, u8 enable)
459{
460 struct isp_device *isp = to_isp_device(prev);
461
462 if (enable)
463 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
464 ISPPRV_PCR_SUPEN);
465 else
466 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
467 ISPPRV_PCR_SUPEN);
468}
469
470/*
471 * preview_config_whitebalance - Configures the White Balance parameters.
472 * @prev_wbal: Structure containing the digital gain and white balance
473 * coefficient.
474 *
475 * Coefficient matrix always with default values.
476 */
477static void
478preview_config_whitebalance(struct isp_prev_device *prev, const void *prev_wbal)
479{
480 struct isp_device *isp = to_isp_device(prev);
481 const struct omap3isp_prev_wbal *wbal = prev_wbal;
482 u32 val;
483
484 isp_reg_writel(isp, wbal->dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
485
486 val = wbal->coef0 << ISPPRV_WBGAIN_COEF0_SHIFT;
487 val |= wbal->coef1 << ISPPRV_WBGAIN_COEF1_SHIFT;
488 val |= wbal->coef2 << ISPPRV_WBGAIN_COEF2_SHIFT;
489 val |= wbal->coef3 << ISPPRV_WBGAIN_COEF3_SHIFT;
490 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
491
492 isp_reg_writel(isp,
493 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT |
494 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT |
495 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT |
496 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT |
497 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT |
498 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT |
499 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT |
500 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT |
501 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT |
502 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT |
503 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT |
504 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT |
505 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT |
506 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT |
507 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT |
508 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT,
509 OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
510}
511
512/*
513 * preview_config_blkadj - Configures the Black Adjustment parameters.
514 * @prev_blkadj: Structure containing the black adjustment towards red, green,
515 * blue.
516 */
517static void
518preview_config_blkadj(struct isp_prev_device *prev, const void *prev_blkadj)
519{
520 struct isp_device *isp = to_isp_device(prev);
521 const struct omap3isp_prev_blkadj *blkadj = prev_blkadj;
522
523 isp_reg_writel(isp, (blkadj->blue << ISPPRV_BLKADJOFF_B_SHIFT) |
524 (blkadj->green << ISPPRV_BLKADJOFF_G_SHIFT) |
525 (blkadj->red << ISPPRV_BLKADJOFF_R_SHIFT),
526 OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
527}
528
529/*
530 * preview_config_rgb_blending - Configures the RGB-RGB Blending matrix.
531 * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb
532 * offset.
533 */
534static void
535preview_config_rgb_blending(struct isp_prev_device *prev, const void *rgb2rgb)
536{
537 struct isp_device *isp = to_isp_device(prev);
538 const struct omap3isp_prev_rgbtorgb *rgbrgb = rgb2rgb;
539 u32 val;
540
541 val = (rgbrgb->matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
542 val |= (rgbrgb->matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
543 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1);
544
545 val = (rgbrgb->matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
546 val |= (rgbrgb->matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
547 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2);
548
549 val = (rgbrgb->matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
550 val |= (rgbrgb->matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
551 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3);
552
553 val = (rgbrgb->matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
554 val |= (rgbrgb->matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
555 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4);
556
557 val = (rgbrgb->matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
558 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5);
559
560 val = (rgbrgb->offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
561 val |= (rgbrgb->offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
562 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1);
563
564 val = (rgbrgb->offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
565 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2);
566}
567
568/*
569 * Configures the RGB-YCbYCr conversion matrix
570 * @prev_csc: Structure containing the RGB to YCbYCr matrix and the
571 * YCbCr offset.
572 */
573static void
574preview_config_rgb_to_ycbcr(struct isp_prev_device *prev, const void *prev_csc)
575{
576 struct isp_device *isp = to_isp_device(prev);
577 const struct omap3isp_prev_csc *csc = prev_csc;
578 u32 val;
579
580 val = (csc->matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
581 val |= (csc->matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
582 val |= (csc->matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
583 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
584
585 val = (csc->matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
586 val |= (csc->matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
587 val |= (csc->matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
588 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
589
590 val = (csc->matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
591 val |= (csc->matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
592 val |= (csc->matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
593 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
594
595 val = (csc->offset[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
596 val |= (csc->offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
597 val |= (csc->offset[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
598 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
599}
600
601/*
602 * preview_update_contrast - Updates the contrast.
603 * @contrast: Pointer to hold the current programmed contrast value.
604 *
605 * Value should be programmed before enabling the module.
606 */
607static void
608preview_update_contrast(struct isp_prev_device *prev, u8 contrast)
609{
610 struct prev_params *params = &prev->params;
611
612 if (params->contrast != (contrast * ISPPRV_CONTRAST_UNITS)) {
613 params->contrast = contrast * ISPPRV_CONTRAST_UNITS;
614 prev->update |= PREV_CONTRAST;
615 }
616}
617
618/*
619 * preview_config_contrast - Configures the Contrast.
620 * @params: Contrast value (u8 pointer, U8Q0 format).
621 *
622 * Value should be programmed before enabling the module.
623 */
624static void
625preview_config_contrast(struct isp_prev_device *prev, const void *params)
626{
627 struct isp_device *isp = to_isp_device(prev);
628
629 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
630 0xff << ISPPRV_CNT_BRT_CNT_SHIFT,
631 *(u8 *)params << ISPPRV_CNT_BRT_CNT_SHIFT);
632}
633
634/*
635 * preview_update_brightness - Updates the brightness in preview module.
636 * @brightness: Pointer to hold the current programmed brightness value.
637 *
638 */
639static void
640preview_update_brightness(struct isp_prev_device *prev, u8 brightness)
641{
642 struct prev_params *params = &prev->params;
643
644 if (params->brightness != (brightness * ISPPRV_BRIGHT_UNITS)) {
645 params->brightness = brightness * ISPPRV_BRIGHT_UNITS;
646 prev->update |= PREV_BRIGHTNESS;
647 }
648}
649
650/*
651 * preview_config_brightness - Configures the brightness.
652 * @params: Brightness value (u8 pointer, U8Q0 format).
653 */
654static void
655preview_config_brightness(struct isp_prev_device *prev, const void *params)
656{
657 struct isp_device *isp = to_isp_device(prev);
658
659 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
660 0xff << ISPPRV_CNT_BRT_BRT_SHIFT,
661 *(u8 *)params << ISPPRV_CNT_BRT_BRT_SHIFT);
662}
663
664/*
665 * preview_config_yc_range - Configures the max and min Y and C values.
666 * @yclimit: Structure containing the range of Y and C values.
667 */
668static void
669preview_config_yc_range(struct isp_prev_device *prev, const void *yclimit)
670{
671 struct isp_device *isp = to_isp_device(prev);
672 const struct omap3isp_prev_yclimit *yc = yclimit;
673
674 isp_reg_writel(isp,
675 yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
676 yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
677 yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT |
678 yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT,
679 OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
680}
681
682/* preview parameters update structure */
683struct preview_update {
684 int cfg_bit;
685 int feature_bit;
686 void (*config)(struct isp_prev_device *, const void *);
687 void (*enable)(struct isp_prev_device *, u8);
688};
689
690static struct preview_update update_attrs[] = {
691 {OMAP3ISP_PREV_LUMAENH, PREV_LUMA_ENHANCE,
692 preview_config_luma_enhancement,
693 preview_enable_luma_enhancement},
694 {OMAP3ISP_PREV_INVALAW, PREV_INVERSE_ALAW,
695 NULL,
696 preview_enable_invalaw},
697 {OMAP3ISP_PREV_HRZ_MED, PREV_HORZ_MEDIAN_FILTER,
698 preview_config_hmed,
699 preview_enable_hmed},
700 {OMAP3ISP_PREV_CFA, PREV_CFA,
701 preview_config_cfa,
702 preview_enable_cfa},
703 {OMAP3ISP_PREV_CHROMA_SUPP, PREV_CHROMA_SUPPRESS,
704 preview_config_chroma_suppression,
705 preview_enable_chroma_suppression},
706 {OMAP3ISP_PREV_WB, PREV_WB,
707 preview_config_whitebalance,
708 NULL},
709 {OMAP3ISP_PREV_BLKADJ, PREV_BLKADJ,
710 preview_config_blkadj,
711 NULL},
712 {OMAP3ISP_PREV_RGB2RGB, PREV_RGB2RGB,
713 preview_config_rgb_blending,
714 NULL},
715 {OMAP3ISP_PREV_COLOR_CONV, PREV_COLOR_CONV,
716 preview_config_rgb_to_ycbcr,
717 NULL},
718 {OMAP3ISP_PREV_YC_LIMIT, PREV_YCLIMITS,
719 preview_config_yc_range,
720 NULL},
721 {OMAP3ISP_PREV_DEFECT_COR, PREV_DEFECT_COR,
722 preview_config_dcor,
723 preview_enable_dcor},
724 {OMAP3ISP_PREV_GAMMABYPASS, PREV_GAMMA_BYPASS,
725 NULL,
726 preview_enable_gammabypass},
727 {OMAP3ISP_PREV_DRK_FRM_CAPTURE, PREV_DARK_FRAME_CAPTURE,
728 NULL,
729 preview_enable_drkframe_capture},
730 {OMAP3ISP_PREV_DRK_FRM_SUBTRACT, PREV_DARK_FRAME_SUBTRACT,
731 NULL,
732 preview_enable_drkframe},
733 {OMAP3ISP_PREV_LENS_SHADING, PREV_LENS_SHADING,
734 preview_config_drkf_shadcomp,
735 preview_enable_drkframe},
736 {OMAP3ISP_PREV_NF, PREV_NOISE_FILTER,
737 preview_config_noisefilter,
738 preview_enable_noisefilter},
739 {OMAP3ISP_PREV_GAMMA, PREV_GAMMA,
740 preview_config_gammacorrn,
741 NULL},
742 {-1, PREV_CONTRAST,
743 preview_config_contrast,
744 NULL},
745 {-1, PREV_BRIGHTNESS,
746 preview_config_brightness,
747 NULL},
748};
749
750/*
751 * __preview_get_ptrs - helper function which return pointers to members
752 * of params and config structures.
753 * @params - pointer to preview_params structure.
754 * @param - return pointer to appropriate structure field.
755 * @configs - pointer to update config structure.
756 * @config - return pointer to appropriate structure field.
757 * @bit - for which feature to return pointers.
758 * Return size of corresponding prev_params member
759 */
760static u32
761__preview_get_ptrs(struct prev_params *params, void **param,
762 struct omap3isp_prev_update_config *configs,
763 void __user **config, u32 bit)
764{
765#define CHKARG(cfgs, cfg, field) \
766 if (cfgs && cfg) { \
767 *(cfg) = (cfgs)->field; \
768 }
769
770 switch (bit) {
771 case PREV_HORZ_MEDIAN_FILTER:
772 *param = &params->hmed;
773 CHKARG(configs, config, hmed)
774 return sizeof(params->hmed);
775 case PREV_NOISE_FILTER:
776 *param = &params->nf;
777 CHKARG(configs, config, nf)
778 return sizeof(params->nf);
779 break;
780 case PREV_CFA:
781 *param = &params->cfa;
782 CHKARG(configs, config, cfa)
783 return sizeof(params->cfa);
784 case PREV_LUMA_ENHANCE:
785 *param = &params->luma;
786 CHKARG(configs, config, luma)
787 return sizeof(params->luma);
788 case PREV_CHROMA_SUPPRESS:
789 *param = &params->csup;
790 CHKARG(configs, config, csup)
791 return sizeof(params->csup);
792 case PREV_DEFECT_COR:
793 *param = &params->dcor;
794 CHKARG(configs, config, dcor)
795 return sizeof(params->dcor);
796 case PREV_BLKADJ:
797 *param = &params->blk_adj;
798 CHKARG(configs, config, blkadj)
799 return sizeof(params->blk_adj);
800 case PREV_YCLIMITS:
801 *param = &params->yclimit;
802 CHKARG(configs, config, yclimit)
803 return sizeof(params->yclimit);
804 case PREV_RGB2RGB:
805 *param = &params->rgb2rgb;
806 CHKARG(configs, config, rgb2rgb)
807 return sizeof(params->rgb2rgb);
808 case PREV_COLOR_CONV:
809 *param = &params->rgb2ycbcr;
810 CHKARG(configs, config, csc)
811 return sizeof(params->rgb2ycbcr);
812 case PREV_WB:
813 *param = &params->wbal;
814 CHKARG(configs, config, wbal)
815 return sizeof(params->wbal);
816 case PREV_GAMMA:
817 *param = &params->gamma;
818 CHKARG(configs, config, gamma)
819 return sizeof(params->gamma);
820 case PREV_CONTRAST:
821 *param = &params->contrast;
822 return 0;
823 case PREV_BRIGHTNESS:
824 *param = &params->brightness;
825 return 0;
826 default:
827 *param = NULL;
828 *config = NULL;
829 break;
830 }
831 return 0;
832}
833
834/*
835 * preview_config - Copy and update local structure with userspace preview
836 * configuration.
837 * @prev: ISP preview engine
838 * @cfg: Configuration
839 *
840 * Return zero if success or -EFAULT if the configuration can't be copied from
841 * userspace.
842 */
843static int preview_config(struct isp_prev_device *prev,
844 struct omap3isp_prev_update_config *cfg)
845{
846 struct prev_params *params;
847 struct preview_update *attr;
848 int i, bit, rval = 0;
849
850 params = &prev->params;
851
852 if (prev->state != ISP_PIPELINE_STREAM_STOPPED) {
853 unsigned long flags;
854
855 spin_lock_irqsave(&prev->lock, flags);
856 prev->shadow_update = 1;
857 spin_unlock_irqrestore(&prev->lock, flags);
858 }
859
860 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
861 attr = &update_attrs[i];
862 bit = 0;
863
864 if (!(cfg->update & attr->cfg_bit))
865 continue;
866
867 bit = cfg->flag & attr->cfg_bit;
868 if (bit) {
869 void *to = NULL, __user *from = NULL;
870 unsigned long sz = 0;
871
872 sz = __preview_get_ptrs(params, &to, cfg, &from,
873 bit);
874 if (to && from && sz) {
875 if (copy_from_user(to, from, sz)) {
876 rval = -EFAULT;
877 break;
878 }
879 }
880 params->features |= attr->feature_bit;
881 } else {
882 params->features &= ~attr->feature_bit;
883 }
884
885 prev->update |= attr->feature_bit;
886 }
887
888 prev->shadow_update = 0;
889 return rval;
890}
891
892/*
893 * preview_setup_hw - Setup preview registers and/or internal memory
894 * @prev: pointer to preview private structure
895 * Note: can be called from interrupt context
896 * Return none
897 */
898static void preview_setup_hw(struct isp_prev_device *prev)
899{
900 struct prev_params *params = &prev->params;
901 struct preview_update *attr;
902 int i, bit;
903 void *param_ptr;
904
905 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
906 attr = &update_attrs[i];
907
908 if (!(prev->update & attr->feature_bit))
909 continue;
910 bit = params->features & attr->feature_bit;
911 if (bit) {
912 if (attr->config) {
913 __preview_get_ptrs(params, &param_ptr, NULL,
914 NULL, bit);
915 attr->config(prev, param_ptr);
916 }
917 if (attr->enable)
918 attr->enable(prev, 1);
919 } else
920 if (attr->enable)
921 attr->enable(prev, 0);
922
923 prev->update &= ~attr->feature_bit;
924 }
925}
926
927/*
928 * preview_config_ycpos - Configure byte layout of YUV image.
929 * @mode: Indicates the required byte layout.
930 */
931static void
932preview_config_ycpos(struct isp_prev_device *prev,
933 enum v4l2_mbus_pixelcode pixelcode)
934{
935 struct isp_device *isp = to_isp_device(prev);
936 enum preview_ycpos_mode mode;
937
938 switch (pixelcode) {
939 case V4L2_MBUS_FMT_YUYV8_1X16:
940 mode = YCPOS_CrYCbY;
941 break;
942 case V4L2_MBUS_FMT_UYVY8_1X16:
943 mode = YCPOS_YCrYCb;
944 break;
945 default:
946 return;
947 }
948
949 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
950 ISPPRV_PCR_YCPOS_CrYCbY,
951 mode << ISPPRV_PCR_YCPOS_SHIFT);
952}
953
954/*
955 * preview_config_averager - Enable / disable / configure averager
956 * @average: Average value to be configured.
957 */
958static void preview_config_averager(struct isp_prev_device *prev, u8 average)
959{
960 struct isp_device *isp = to_isp_device(prev);
961 int reg = 0;
962
963 if (prev->params.cfa.format == OMAP3ISP_CFAFMT_BAYER)
964 reg = ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
965 ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
966 average;
967 else if (prev->params.cfa.format == OMAP3ISP_CFAFMT_RGBFOVEON)
968 reg = ISPPRV_AVE_EVENDIST_3 << ISPPRV_AVE_EVENDIST_SHIFT |
969 ISPPRV_AVE_ODDDIST_3 << ISPPRV_AVE_ODDDIST_SHIFT |
970 average;
971 isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
972}
973
974/*
975 * preview_config_input_size - Configure the input frame size
976 *
977 * The preview engine crops several rows and columns internally depending on
978 * which processing blocks are enabled. The driver assumes all those blocks are
979 * enabled when reporting source pad formats to userspace. If this assumption is
980 * not true, rows and columns must be manually cropped at the preview engine
981 * input to avoid overflows at the end of lines and frames.
982 */
983static void preview_config_input_size(struct isp_prev_device *prev)
984{
985 struct isp_device *isp = to_isp_device(prev);
986 struct prev_params *params = &prev->params;
987 struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK];
988 unsigned int sph = 0;
989 unsigned int eph = format->width - 1;
990 unsigned int slv = 0;
991 unsigned int elv = format->height - 1;
992
993 if (prev->input == PREVIEW_INPUT_CCDC) {
994 sph += 2;
995 eph -= 2;
996 }
997
998 /*
999 * Median filter 4 pixels
1000 * Noise filter 4 pixels, 4 lines
1001 * or faulty pixels correction
1002 * CFA filter 4 pixels, 4 lines in Bayer mode
1003 * 2 lines in other modes
1004 * Color suppression 2 pixels
1005 * or luma enhancement
1006 * -------------------------------------------------------------
1007 * Maximum total 14 pixels, 8 lines
1008 */
1009
1010 if (!(params->features & PREV_CFA)) {
1011 sph += 2;
1012 eph -= 2;
1013 slv += 2;
1014 elv -= 2;
1015 }
1016 if (!(params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER))) {
1017 sph += 2;
1018 eph -= 2;
1019 slv += 2;
1020 elv -= 2;
1021 }
1022 if (!(params->features & PREV_HORZ_MEDIAN_FILTER)) {
1023 sph += 2;
1024 eph -= 2;
1025 }
1026 if (!(params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE)))
1027 sph += 2;
1028
1029 isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
1030 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
1031 isp_reg_writel(isp, (slv << ISPPRV_VERT_INFO_SLV_SHIFT) | elv,
1032 OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
1033}
1034
1035/*
1036 * preview_config_inlineoffset - Configures the Read address line offset.
1037 * @prev: Preview module
1038 * @offset: Line offset
1039 *
1040 * According to the TRM, the line offset must be aligned on a 32 bytes boundary.
1041 * However, a hardware bug requires the memory start address to be aligned on a
1042 * 64 bytes boundary, so the offset probably should be aligned on 64 bytes as
1043 * well.
1044 */
1045static void
1046preview_config_inlineoffset(struct isp_prev_device *prev, u32 offset)
1047{
1048 struct isp_device *isp = to_isp_device(prev);
1049
1050 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1051 ISPPRV_RADR_OFFSET);
1052}
1053
1054/*
1055 * preview_set_inaddr - Sets memory address of input frame.
1056 * @addr: 32bit memory address aligned on 32byte boundary.
1057 *
1058 * Configures the memory address from which the input frame is to be read.
1059 */
1060static void preview_set_inaddr(struct isp_prev_device *prev, u32 addr)
1061{
1062 struct isp_device *isp = to_isp_device(prev);
1063
1064 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
1065}
1066
1067/*
1068 * preview_config_outlineoffset - Configures the Write address line offset.
1069 * @offset: Line Offset for the preview output.
1070 *
1071 * The offset must be a multiple of 32 bytes.
1072 */
1073static void preview_config_outlineoffset(struct isp_prev_device *prev,
1074 u32 offset)
1075{
1076 struct isp_device *isp = to_isp_device(prev);
1077
1078 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1079 ISPPRV_WADD_OFFSET);
1080}
1081
1082/*
1083 * preview_set_outaddr - Sets the memory address to store output frame
1084 * @addr: 32bit memory address aligned on 32byte boundary.
1085 *
1086 * Configures the memory address to which the output frame is written.
1087 */
1088static void preview_set_outaddr(struct isp_prev_device *prev, u32 addr)
1089{
1090 struct isp_device *isp = to_isp_device(prev);
1091
1092 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR);
1093}
1094
1095static void preview_adjust_bandwidth(struct isp_prev_device *prev)
1096{
1097 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
1098 struct isp_device *isp = to_isp_device(prev);
1099 const struct v4l2_mbus_framefmt *ifmt = &prev->formats[PREV_PAD_SINK];
1100 unsigned long l3_ick = pipe->l3_ick;
1101 struct v4l2_fract *timeperframe;
1102 unsigned int cycles_per_frame;
1103 unsigned int requests_per_frame;
1104 unsigned int cycles_per_request;
1105 unsigned int minimum;
1106 unsigned int maximum;
1107 unsigned int value;
1108
1109 if (prev->input != PREVIEW_INPUT_MEMORY) {
1110 isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
1111 ISPSBL_SDR_REQ_PRV_EXP_MASK);
1112 return;
1113 }
1114
1115 /* Compute the minimum number of cycles per request, based on the
1116 * pipeline maximum data rate. This is an absolute lower bound if we
1117 * don't want SBL overflows, so round the value up.
1118 */
1119 cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1,
1120 pipe->max_rate);
1121 minimum = DIV_ROUND_UP(cycles_per_request, 32);
1122
1123 /* Compute the maximum number of cycles per request, based on the
1124 * requested frame rate. This is a soft upper bound to achieve a frame
1125 * rate equal or higher than the requested value, so round the value
1126 * down.
1127 */
1128 timeperframe = &pipe->max_timeperframe;
1129
1130 requests_per_frame = DIV_ROUND_UP(ifmt->width * 2, 256) * ifmt->height;
1131 cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator,
1132 timeperframe->denominator);
1133 cycles_per_request = cycles_per_frame / requests_per_frame;
1134
1135 maximum = cycles_per_request / 32;
1136
1137 value = max(minimum, maximum);
1138
1139 dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value);
1140 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
1141 ISPSBL_SDR_REQ_PRV_EXP_MASK,
1142 value << ISPSBL_SDR_REQ_PRV_EXP_SHIFT);
1143}
1144
1145/*
1146 * omap3isp_preview_busy - Gets busy state of preview module.
1147 */
1148int omap3isp_preview_busy(struct isp_prev_device *prev)
1149{
1150 struct isp_device *isp = to_isp_device(prev);
1151
1152 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR)
1153 & ISPPRV_PCR_BUSY;
1154}
1155
1156/*
1157 * omap3isp_preview_restore_context - Restores the values of preview registers
1158 */
1159void omap3isp_preview_restore_context(struct isp_device *isp)
1160{
1161 isp->isp_prev.update = PREV_FEATURES_END - 1;
1162 preview_setup_hw(&isp->isp_prev);
1163}
1164
1165/*
1166 * preview_print_status - Dump preview module registers to the kernel log
1167 */
1168#define PREV_PRINT_REGISTER(isp, name)\
1169 dev_dbg(isp->dev, "###PRV " #name "=0x%08x\n", \
1170 isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_##name))
1171
1172static void preview_print_status(struct isp_prev_device *prev)
1173{
1174 struct isp_device *isp = to_isp_device(prev);
1175
1176 dev_dbg(isp->dev, "-------------Preview Register dump----------\n");
1177
1178 PREV_PRINT_REGISTER(isp, PCR);
1179 PREV_PRINT_REGISTER(isp, HORZ_INFO);
1180 PREV_PRINT_REGISTER(isp, VERT_INFO);
1181 PREV_PRINT_REGISTER(isp, RSDR_ADDR);
1182 PREV_PRINT_REGISTER(isp, RADR_OFFSET);
1183 PREV_PRINT_REGISTER(isp, DSDR_ADDR);
1184 PREV_PRINT_REGISTER(isp, DRKF_OFFSET);
1185 PREV_PRINT_REGISTER(isp, WSDR_ADDR);
1186 PREV_PRINT_REGISTER(isp, WADD_OFFSET);
1187 PREV_PRINT_REGISTER(isp, AVE);
1188 PREV_PRINT_REGISTER(isp, HMED);
1189 PREV_PRINT_REGISTER(isp, NF);
1190 PREV_PRINT_REGISTER(isp, WB_DGAIN);
1191 PREV_PRINT_REGISTER(isp, WBGAIN);
1192 PREV_PRINT_REGISTER(isp, WBSEL);
1193 PREV_PRINT_REGISTER(isp, CFA);
1194 PREV_PRINT_REGISTER(isp, BLKADJOFF);
1195 PREV_PRINT_REGISTER(isp, RGB_MAT1);
1196 PREV_PRINT_REGISTER(isp, RGB_MAT2);
1197 PREV_PRINT_REGISTER(isp, RGB_MAT3);
1198 PREV_PRINT_REGISTER(isp, RGB_MAT4);
1199 PREV_PRINT_REGISTER(isp, RGB_MAT5);
1200 PREV_PRINT_REGISTER(isp, RGB_OFF1);
1201 PREV_PRINT_REGISTER(isp, RGB_OFF2);
1202 PREV_PRINT_REGISTER(isp, CSC0);
1203 PREV_PRINT_REGISTER(isp, CSC1);
1204 PREV_PRINT_REGISTER(isp, CSC2);
1205 PREV_PRINT_REGISTER(isp, CSC_OFFSET);
1206 PREV_PRINT_REGISTER(isp, CNT_BRT);
1207 PREV_PRINT_REGISTER(isp, CSUP);
1208 PREV_PRINT_REGISTER(isp, SETUP_YC);
1209 PREV_PRINT_REGISTER(isp, SET_TBL_ADDR);
1210 PREV_PRINT_REGISTER(isp, CDC_THR0);
1211 PREV_PRINT_REGISTER(isp, CDC_THR1);
1212 PREV_PRINT_REGISTER(isp, CDC_THR2);
1213 PREV_PRINT_REGISTER(isp, CDC_THR3);
1214
1215 dev_dbg(isp->dev, "--------------------------------------------\n");
1216}
1217
1218/*
1219 * preview_init_params - init image processing parameters.
1220 * @prev: pointer to previewer private structure
1221 * return none
1222 */
1223static void preview_init_params(struct isp_prev_device *prev)
1224{
1225 struct prev_params *params = &prev->params;
1226 int i = 0;
1227
1228 /* Init values */
1229 params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS;
1230 params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS;
1231 params->average = NO_AVE;
1232 params->cfa.format = OMAP3ISP_CFAFMT_BAYER;
1233 memcpy(params->cfa.table, cfa_coef_table,
1234 sizeof(params->cfa.table));
1235 params->cfa.gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
1236 params->cfa.gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
1237 params->csup.gain = FLR_CSUP_GAIN;
1238 params->csup.thres = FLR_CSUP_THRES;
1239 params->csup.hypf_en = 0;
1240 memcpy(params->luma.table, luma_enhance_table,
1241 sizeof(params->luma.table));
1242 params->nf.spread = FLR_NF_STRGTH;
1243 memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
1244 params->dcor.couplet_mode_en = 1;
1245 for (i = 0; i < OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS; i++)
1246 params->dcor.detect_correct[i] = DEF_DETECT_CORRECT_VAL;
1247 memcpy(params->gamma.blue, gamma_table, sizeof(params->gamma.blue));
1248 memcpy(params->gamma.green, gamma_table, sizeof(params->gamma.green));
1249 memcpy(params->gamma.red, gamma_table, sizeof(params->gamma.red));
1250 params->wbal.dgain = FLR_WBAL_DGAIN;
1251 params->wbal.coef0 = FLR_WBAL_COEF;
1252 params->wbal.coef1 = FLR_WBAL_COEF;
1253 params->wbal.coef2 = FLR_WBAL_COEF;
1254 params->wbal.coef3 = FLR_WBAL_COEF;
1255 params->blk_adj.red = FLR_BLKADJ_RED;
1256 params->blk_adj.green = FLR_BLKADJ_GREEN;
1257 params->blk_adj.blue = FLR_BLKADJ_BLUE;
1258 params->rgb2rgb = flr_rgb2rgb;
1259 params->rgb2ycbcr = flr_prev_csc;
1260 params->yclimit.minC = ISPPRV_YC_MIN;
1261 params->yclimit.maxC = ISPPRV_YC_MAX;
1262 params->yclimit.minY = ISPPRV_YC_MIN;
1263 params->yclimit.maxY = ISPPRV_YC_MAX;
1264
1265 params->features = PREV_CFA | PREV_DEFECT_COR | PREV_NOISE_FILTER
1266 | PREV_GAMMA | PREV_BLKADJ | PREV_YCLIMITS
1267 | PREV_RGB2RGB | PREV_COLOR_CONV | PREV_WB
1268 | PREV_BRIGHTNESS | PREV_CONTRAST;
1269
1270 prev->update = PREV_FEATURES_END - 1;
1271}
1272
1273/*
1274 * preview_max_out_width - Handle previewer hardware ouput limitations
1275 * @isp_revision : ISP revision
1276 * returns maximum width output for current isp revision
1277 */
1278static unsigned int preview_max_out_width(struct isp_prev_device *prev)
1279{
1280 struct isp_device *isp = to_isp_device(prev);
1281
1282 switch (isp->revision) {
1283 case ISP_REVISION_1_0:
1284 return ISPPRV_MAXOUTPUT_WIDTH;
1285
1286 case ISP_REVISION_2_0:
1287 default:
1288 return ISPPRV_MAXOUTPUT_WIDTH_ES2;
1289
1290 case ISP_REVISION_15_0:
1291 return ISPPRV_MAXOUTPUT_WIDTH_3630;
1292 }
1293}
1294
1295static void preview_configure(struct isp_prev_device *prev)
1296{
1297 struct isp_device *isp = to_isp_device(prev);
1298 struct v4l2_mbus_framefmt *format;
1299 unsigned int max_out_width;
1300 unsigned int format_avg;
1301
1302 preview_setup_hw(prev);
1303
1304 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1305 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1306 ISPPRV_PCR_SDRPORT);
1307 else
1308 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1309 ISPPRV_PCR_SDRPORT);
1310
1311 if (prev->output & PREVIEW_OUTPUT_RESIZER)
1312 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1313 ISPPRV_PCR_RSZPORT);
1314 else
1315 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1316 ISPPRV_PCR_RSZPORT);
1317
1318 /* PREV_PAD_SINK */
1319 format = &prev->formats[PREV_PAD_SINK];
1320
1321 preview_adjust_bandwidth(prev);
1322
1323 preview_config_input_size(prev);
1324
1325 if (prev->input == PREVIEW_INPUT_CCDC)
1326 preview_config_inlineoffset(prev, 0);
1327 else
1328 preview_config_inlineoffset(prev,
1329 ALIGN(format->width, 0x20) * 2);
1330
1331 /* PREV_PAD_SOURCE */
1332 format = &prev->formats[PREV_PAD_SOURCE];
1333
1334 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1335 preview_config_outlineoffset(prev,
1336 ALIGN(format->width, 0x10) * 2);
1337
1338 max_out_width = preview_max_out_width(prev);
1339
1340 format_avg = fls(DIV_ROUND_UP(format->width, max_out_width) - 1);
1341 preview_config_averager(prev, format_avg);
1342 preview_config_ycpos(prev, format->code);
1343}
1344
1345/* -----------------------------------------------------------------------------
1346 * Interrupt handling
1347 */
1348
1349static void preview_enable_oneshot(struct isp_prev_device *prev)
1350{
1351 struct isp_device *isp = to_isp_device(prev);
1352
1353 /* The PCR.SOURCE bit is automatically reset to 0 when the PCR.ENABLE
1354 * bit is set. As the preview engine is used in single-shot mode, we
1355 * need to set PCR.SOURCE before enabling the preview engine.
1356 */
1357 if (prev->input == PREVIEW_INPUT_MEMORY)
1358 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1359 ISPPRV_PCR_SOURCE);
1360
1361 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1362 ISPPRV_PCR_EN | ISPPRV_PCR_ONESHOT);
1363}
1364
1365void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev)
1366{
1367 /*
1368 * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun
1369 * condition, the module was paused and now we have a buffer queued
1370 * on the output again. Restart the pipeline if running in continuous
1371 * mode.
1372 */
1373 if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
1374 prev->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
1375 preview_enable_oneshot(prev);
1376 isp_video_dmaqueue_flags_clr(&prev->video_out);
1377 }
1378}
1379
1380static void preview_isr_buffer(struct isp_prev_device *prev)
1381{
1382 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
1383 struct isp_buffer *buffer;
1384 int restart = 0;
1385
1386 if (prev->input == PREVIEW_INPUT_MEMORY) {
1387 buffer = omap3isp_video_buffer_next(&prev->video_in,
1388 prev->error);
1389 if (buffer != NULL)
1390 preview_set_inaddr(prev, buffer->isp_addr);
1391 pipe->state |= ISP_PIPELINE_IDLE_INPUT;
1392 }
1393
1394 if (prev->output & PREVIEW_OUTPUT_MEMORY) {
1395 buffer = omap3isp_video_buffer_next(&prev->video_out,
1396 prev->error);
1397 if (buffer != NULL) {
1398 preview_set_outaddr(prev, buffer->isp_addr);
1399 restart = 1;
1400 }
1401 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
1402 }
1403
1404 switch (prev->state) {
1405 case ISP_PIPELINE_STREAM_SINGLESHOT:
1406 if (isp_pipeline_ready(pipe))
1407 omap3isp_pipeline_set_stream(pipe,
1408 ISP_PIPELINE_STREAM_SINGLESHOT);
1409 break;
1410
1411 case ISP_PIPELINE_STREAM_CONTINUOUS:
1412 /* If an underrun occurs, the video queue operation handler will
1413 * restart the preview engine. Otherwise restart it immediately.
1414 */
1415 if (restart)
1416 preview_enable_oneshot(prev);
1417 break;
1418
1419 case ISP_PIPELINE_STREAM_STOPPED:
1420 default:
1421 return;
1422 }
1423
1424 prev->error = 0;
1425}
1426
1427/*
1428 * omap3isp_preview_isr - ISP preview engine interrupt handler
1429 *
1430 * Manage the preview engine video buffers and configure shadowed registers.
1431 */
1432void omap3isp_preview_isr(struct isp_prev_device *prev)
1433{
1434 unsigned long flags;
1435
1436 if (omap3isp_module_sync_is_stopping(&prev->wait, &prev->stopping))
1437 return;
1438
1439 spin_lock_irqsave(&prev->lock, flags);
1440 if (prev->shadow_update)
1441 goto done;
1442
1443 preview_setup_hw(prev);
1444 preview_config_input_size(prev);
1445
1446done:
1447 spin_unlock_irqrestore(&prev->lock, flags);
1448
1449 if (prev->input == PREVIEW_INPUT_MEMORY ||
1450 prev->output & PREVIEW_OUTPUT_MEMORY)
1451 preview_isr_buffer(prev);
1452 else if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS)
1453 preview_enable_oneshot(prev);
1454}
1455
1456/* -----------------------------------------------------------------------------
1457 * ISP video operations
1458 */
1459
1460static int preview_video_queue(struct isp_video *video,
1461 struct isp_buffer *buffer)
1462{
1463 struct isp_prev_device *prev = &video->isp->isp_prev;
1464
1465 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1466 preview_set_inaddr(prev, buffer->isp_addr);
1467
1468 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1469 preview_set_outaddr(prev, buffer->isp_addr);
1470
1471 return 0;
1472}
1473
1474static const struct isp_video_operations preview_video_ops = {
1475 .queue = preview_video_queue,
1476};
1477
1478/* -----------------------------------------------------------------------------
1479 * V4L2 subdev operations
1480 */
1481
1482/*
1483 * preview_s_ctrl - Handle set control subdev method
1484 * @ctrl: pointer to v4l2 control structure
1485 */
1486static int preview_s_ctrl(struct v4l2_ctrl *ctrl)
1487{
1488 struct isp_prev_device *prev =
1489 container_of(ctrl->handler, struct isp_prev_device, ctrls);
1490
1491 switch (ctrl->id) {
1492 case V4L2_CID_BRIGHTNESS:
1493 preview_update_brightness(prev, ctrl->val);
1494 break;
1495 case V4L2_CID_CONTRAST:
1496 preview_update_contrast(prev, ctrl->val);
1497 break;
1498 }
1499
1500 return 0;
1501}
1502
1503static const struct v4l2_ctrl_ops preview_ctrl_ops = {
1504 .s_ctrl = preview_s_ctrl,
1505};
1506
1507/*
1508 * preview_ioctl - Handle preview module private ioctl's
1509 * @prev: pointer to preview context structure
1510 * @cmd: configuration command
1511 * @arg: configuration argument
1512 * return -EINVAL or zero on success
1513 */
1514static long preview_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1515{
1516 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1517
1518 switch (cmd) {
1519 case VIDIOC_OMAP3ISP_PRV_CFG:
1520 return preview_config(prev, arg);
1521
1522 default:
1523 return -ENOIOCTLCMD;
1524 }
1525}
1526
1527/*
1528 * preview_set_stream - Enable/Disable streaming on preview subdev
1529 * @sd : pointer to v4l2 subdev structure
1530 * @enable: 1 == Enable, 0 == Disable
1531 * return -EINVAL or zero on success
1532 */
1533static int preview_set_stream(struct v4l2_subdev *sd, int enable)
1534{
1535 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1536 struct isp_video *video_out = &prev->video_out;
1537 struct isp_device *isp = to_isp_device(prev);
1538 struct device *dev = to_device(prev);
1539 unsigned long flags;
1540
1541 if (prev->state == ISP_PIPELINE_STREAM_STOPPED) {
1542 if (enable == ISP_PIPELINE_STREAM_STOPPED)
1543 return 0;
1544
1545 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1546 preview_configure(prev);
1547 atomic_set(&prev->stopping, 0);
1548 prev->error = 0;
1549 preview_print_status(prev);
1550 }
1551
1552 switch (enable) {
1553 case ISP_PIPELINE_STREAM_CONTINUOUS:
1554 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1555 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1556
1557 if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED ||
1558 !(prev->output & PREVIEW_OUTPUT_MEMORY))
1559 preview_enable_oneshot(prev);
1560
1561 isp_video_dmaqueue_flags_clr(video_out);
1562 break;
1563
1564 case ISP_PIPELINE_STREAM_SINGLESHOT:
1565 if (prev->input == PREVIEW_INPUT_MEMORY)
1566 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
1567 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1568 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1569
1570 preview_enable_oneshot(prev);
1571 break;
1572
1573 case ISP_PIPELINE_STREAM_STOPPED:
1574 if (omap3isp_module_sync_idle(&sd->entity, &prev->wait,
1575 &prev->stopping))
1576 dev_dbg(dev, "%s: stop timeout.\n", sd->name);
1577 spin_lock_irqsave(&prev->lock, flags);
1578 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
1579 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1580 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1581 spin_unlock_irqrestore(&prev->lock, flags);
1582 isp_video_dmaqueue_flags_clr(video_out);
1583 break;
1584 }
1585
1586 prev->state = enable;
1587 return 0;
1588}
1589
1590static struct v4l2_mbus_framefmt *
1591__preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
1592 unsigned int pad, enum v4l2_subdev_format_whence which)
1593{
1594 if (which == V4L2_SUBDEV_FORMAT_TRY)
1595 return v4l2_subdev_get_try_format(fh, pad);
1596 else
1597 return &prev->formats[pad];
1598}
1599
1600/* previewer format descriptions */
1601static const unsigned int preview_input_fmts[] = {
1602 V4L2_MBUS_FMT_SGRBG10_1X10,
1603 V4L2_MBUS_FMT_SRGGB10_1X10,
1604 V4L2_MBUS_FMT_SBGGR10_1X10,
1605 V4L2_MBUS_FMT_SGBRG10_1X10,
1606};
1607
1608static const unsigned int preview_output_fmts[] = {
1609 V4L2_MBUS_FMT_UYVY8_1X16,
1610 V4L2_MBUS_FMT_YUYV8_1X16,
1611};
1612
1613/*
1614 * preview_try_format - Handle try format by pad subdev method
1615 * @prev: ISP preview device
1616 * @fh : V4L2 subdev file handle
1617 * @pad: pad num
1618 * @fmt: pointer to v4l2 format structure
1619 */
1620static void preview_try_format(struct isp_prev_device *prev,
1621 struct v4l2_subdev_fh *fh, unsigned int pad,
1622 struct v4l2_mbus_framefmt *fmt,
1623 enum v4l2_subdev_format_whence which)
1624{
1625 struct v4l2_mbus_framefmt *format;
1626 unsigned int max_out_width;
1627 enum v4l2_mbus_pixelcode pixelcode;
1628 unsigned int i;
1629
1630 max_out_width = preview_max_out_width(prev);
1631
1632 switch (pad) {
1633 case PREV_PAD_SINK:
1634 /* When reading data from the CCDC, the input size has already
1635 * been mangled by the CCDC output pad so it can be accepted
1636 * as-is.
1637 *
1638 * When reading data from memory, clamp the requested width and
1639 * height. The TRM doesn't specify a minimum input height, make
1640 * sure we got enough lines to enable the noise filter and color
1641 * filter array interpolation.
1642 */
1643 if (prev->input == PREVIEW_INPUT_MEMORY) {
1644 fmt->width = clamp_t(u32, fmt->width, PREV_MIN_WIDTH,
1645 max_out_width * 8);
1646 fmt->height = clamp_t(u32, fmt->height, PREV_MIN_HEIGHT,
1647 PREV_MAX_HEIGHT);
1648 }
1649
1650 fmt->colorspace = V4L2_COLORSPACE_SRGB;
1651
1652 for (i = 0; i < ARRAY_SIZE(preview_input_fmts); i++) {
1653 if (fmt->code == preview_input_fmts[i])
1654 break;
1655 }
1656
1657 /* If not found, use SGRBG10 as default */
1658 if (i >= ARRAY_SIZE(preview_input_fmts))
1659 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
1660 break;
1661
1662 case PREV_PAD_SOURCE:
1663 pixelcode = fmt->code;
1664 format = __preview_get_format(prev, fh, PREV_PAD_SINK, which);
1665 memcpy(fmt, format, sizeof(*fmt));
1666
1667 /* The preview module output size is configurable through the
1668 * input interface (horizontal and vertical cropping) and the
1669 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). In
1670 * spite of this, hardcode the output size to the biggest
1671 * possible value for simplicity reasons.
1672 */
1673 switch (pixelcode) {
1674 case V4L2_MBUS_FMT_YUYV8_1X16:
1675 case V4L2_MBUS_FMT_UYVY8_1X16:
1676 fmt->code = pixelcode;
1677 break;
1678
1679 default:
1680 fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
1681 break;
1682 }
1683
1684 /* The TRM states (12.1.4.7.1.2) that 2 pixels must be cropped
1685 * from the left and right sides when the input source is the
1686 * CCDC. This seems not to be needed in practice, investigation
1687 * is required.
1688 */
1689 if (prev->input == PREVIEW_INPUT_CCDC)
1690 fmt->width -= 4;
1691
1692 /* The preview module can output a maximum of 3312 pixels
1693 * horizontally due to fixed memory-line sizes. Compute the
1694 * horizontal averaging factor accordingly. Note that the limit
1695 * applies to the noise filter and CFA interpolation blocks, so
1696 * it doesn't take cropping by further blocks into account.
1697 *
1698 * ES 1.0 hardware revision is limited to 1280 pixels
1699 * horizontally.
1700 */
1701 fmt->width >>= fls(DIV_ROUND_UP(fmt->width, max_out_width) - 1);
1702
1703 /* Assume that all blocks are enabled and crop pixels and lines
1704 * accordingly. See preview_config_input_size() for more
1705 * information.
1706 */
1707 fmt->width -= 14;
1708 fmt->height -= 8;
1709
1710 fmt->colorspace = V4L2_COLORSPACE_JPEG;
1711 break;
1712 }
1713
1714 fmt->field = V4L2_FIELD_NONE;
1715}
1716
1717/*
1718 * preview_enum_mbus_code - Handle pixel format enumeration
1719 * @sd : pointer to v4l2 subdev structure
1720 * @fh : V4L2 subdev file handle
1721 * @code : pointer to v4l2_subdev_mbus_code_enum structure
1722 * return -EINVAL or zero on success
1723 */
1724static int preview_enum_mbus_code(struct v4l2_subdev *sd,
1725 struct v4l2_subdev_fh *fh,
1726 struct v4l2_subdev_mbus_code_enum *code)
1727{
1728 switch (code->pad) {
1729 case PREV_PAD_SINK:
1730 if (code->index >= ARRAY_SIZE(preview_input_fmts))
1731 return -EINVAL;
1732
1733 code->code = preview_input_fmts[code->index];
1734 break;
1735 case PREV_PAD_SOURCE:
1736 if (code->index >= ARRAY_SIZE(preview_output_fmts))
1737 return -EINVAL;
1738
1739 code->code = preview_output_fmts[code->index];
1740 break;
1741 default:
1742 return -EINVAL;
1743 }
1744
1745 return 0;
1746}
1747
1748static int preview_enum_frame_size(struct v4l2_subdev *sd,
1749 struct v4l2_subdev_fh *fh,
1750 struct v4l2_subdev_frame_size_enum *fse)
1751{
1752 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1753 struct v4l2_mbus_framefmt format;
1754
1755 if (fse->index != 0)
1756 return -EINVAL;
1757
1758 format.code = fse->code;
1759 format.width = 1;
1760 format.height = 1;
1761 preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1762 fse->min_width = format.width;
1763 fse->min_height = format.height;
1764
1765 if (format.code != fse->code)
1766 return -EINVAL;
1767
1768 format.code = fse->code;
1769 format.width = -1;
1770 format.height = -1;
1771 preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1772 fse->max_width = format.width;
1773 fse->max_height = format.height;
1774
1775 return 0;
1776}
1777
1778/*
1779 * preview_get_format - Handle get format by pads subdev method
1780 * @sd : pointer to v4l2 subdev structure
1781 * @fh : V4L2 subdev file handle
1782 * @fmt: pointer to v4l2 subdev format structure
1783 * return -EINVAL or zero on success
1784 */
1785static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1786 struct v4l2_subdev_format *fmt)
1787{
1788 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1789 struct v4l2_mbus_framefmt *format;
1790
1791 format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
1792 if (format == NULL)
1793 return -EINVAL;
1794
1795 fmt->format = *format;
1796 return 0;
1797}
1798
1799/*
1800 * preview_set_format - Handle set format by pads subdev method
1801 * @sd : pointer to v4l2 subdev structure
1802 * @fh : V4L2 subdev file handle
1803 * @fmt: pointer to v4l2 subdev format structure
1804 * return -EINVAL or zero on success
1805 */
1806static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1807 struct v4l2_subdev_format *fmt)
1808{
1809 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1810 struct v4l2_mbus_framefmt *format;
1811
1812 format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
1813 if (format == NULL)
1814 return -EINVAL;
1815
1816 preview_try_format(prev, fh, fmt->pad, &fmt->format, fmt->which);
1817 *format = fmt->format;
1818
1819 /* Propagate the format from sink to source */
1820 if (fmt->pad == PREV_PAD_SINK) {
1821 format = __preview_get_format(prev, fh, PREV_PAD_SOURCE,
1822 fmt->which);
1823 *format = fmt->format;
1824 preview_try_format(prev, fh, PREV_PAD_SOURCE, format,
1825 fmt->which);
1826 }
1827
1828 return 0;
1829}
1830
1831/*
1832 * preview_init_formats - Initialize formats on all pads
1833 * @sd: ISP preview V4L2 subdevice
1834 * @fh: V4L2 subdev file handle
1835 *
1836 * Initialize all pad formats with default values. If fh is not NULL, try
1837 * formats are initialized on the file handle. Otherwise active formats are
1838 * initialized on the device.
1839 */
1840static int preview_init_formats(struct v4l2_subdev *sd,
1841 struct v4l2_subdev_fh *fh)
1842{
1843 struct v4l2_subdev_format format;
1844
1845 memset(&format, 0, sizeof(format));
1846 format.pad = PREV_PAD_SINK;
1847 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1848 format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
1849 format.format.width = 4096;
1850 format.format.height = 4096;
1851 preview_set_format(sd, fh, &format);
1852
1853 return 0;
1854}
1855
1856/* subdev core operations */
1857static const struct v4l2_subdev_core_ops preview_v4l2_core_ops = {
1858 .ioctl = preview_ioctl,
1859};
1860
1861/* subdev video operations */
1862static const struct v4l2_subdev_video_ops preview_v4l2_video_ops = {
1863 .s_stream = preview_set_stream,
1864};
1865
1866/* subdev pad operations */
1867static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
1868 .enum_mbus_code = preview_enum_mbus_code,
1869 .enum_frame_size = preview_enum_frame_size,
1870 .get_fmt = preview_get_format,
1871 .set_fmt = preview_set_format,
1872};
1873
1874/* subdev operations */
1875static const struct v4l2_subdev_ops preview_v4l2_ops = {
1876 .core = &preview_v4l2_core_ops,
1877 .video = &preview_v4l2_video_ops,
1878 .pad = &preview_v4l2_pad_ops,
1879};
1880
1881/* subdev internal operations */
1882static const struct v4l2_subdev_internal_ops preview_v4l2_internal_ops = {
1883 .open = preview_init_formats,
1884};
1885
1886/* -----------------------------------------------------------------------------
1887 * Media entity operations
1888 */
1889
1890/*
1891 * preview_link_setup - Setup previewer connections.
1892 * @entity : Pointer to media entity structure
1893 * @local : Pointer to local pad array
1894 * @remote : Pointer to remote pad array
1895 * @flags : Link flags
1896 * return -EINVAL or zero on success
1897 */
1898static int preview_link_setup(struct media_entity *entity,
1899 const struct media_pad *local,
1900 const struct media_pad *remote, u32 flags)
1901{
1902 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1903 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1904
1905 switch (local->index | media_entity_type(remote->entity)) {
1906 case PREV_PAD_SINK | MEDIA_ENT_T_DEVNODE:
1907 /* read from memory */
1908 if (flags & MEDIA_LNK_FL_ENABLED) {
1909 if (prev->input == PREVIEW_INPUT_CCDC)
1910 return -EBUSY;
1911 prev->input = PREVIEW_INPUT_MEMORY;
1912 } else {
1913 if (prev->input == PREVIEW_INPUT_MEMORY)
1914 prev->input = PREVIEW_INPUT_NONE;
1915 }
1916 break;
1917
1918 case PREV_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
1919 /* read from ccdc */
1920 if (flags & MEDIA_LNK_FL_ENABLED) {
1921 if (prev->input == PREVIEW_INPUT_MEMORY)
1922 return -EBUSY;
1923 prev->input = PREVIEW_INPUT_CCDC;
1924 } else {
1925 if (prev->input == PREVIEW_INPUT_CCDC)
1926 prev->input = PREVIEW_INPUT_NONE;
1927 }
1928 break;
1929
1930 /*
1931 * The ISP core doesn't support pipelines with multiple video outputs.
1932 * Revisit this when it will be implemented, and return -EBUSY for now.
1933 */
1934
1935 case PREV_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
1936 /* write to memory */
1937 if (flags & MEDIA_LNK_FL_ENABLED) {
1938 if (prev->output & ~PREVIEW_OUTPUT_MEMORY)
1939 return -EBUSY;
1940 prev->output |= PREVIEW_OUTPUT_MEMORY;
1941 } else {
1942 prev->output &= ~PREVIEW_OUTPUT_MEMORY;
1943 }
1944 break;
1945
1946 case PREV_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
1947 /* write to resizer */
1948 if (flags & MEDIA_LNK_FL_ENABLED) {
1949 if (prev->output & ~PREVIEW_OUTPUT_RESIZER)
1950 return -EBUSY;
1951 prev->output |= PREVIEW_OUTPUT_RESIZER;
1952 } else {
1953 prev->output &= ~PREVIEW_OUTPUT_RESIZER;
1954 }
1955 break;
1956
1957 default:
1958 return -EINVAL;
1959 }
1960
1961 return 0;
1962}
1963
1964/* media operations */
1965static const struct media_entity_operations preview_media_ops = {
1966 .link_setup = preview_link_setup,
1967};
1968
1969/*
1970 * review_init_entities - Initialize subdev and media entity.
1971 * @prev : Pointer to preview structure
1972 * return -ENOMEM or zero on success
1973 */
1974static int preview_init_entities(struct isp_prev_device *prev)
1975{
1976 struct v4l2_subdev *sd = &prev->subdev;
1977 struct media_pad *pads = prev->pads;
1978 struct media_entity *me = &sd->entity;
1979 int ret;
1980
1981 prev->input = PREVIEW_INPUT_NONE;
1982
1983 v4l2_subdev_init(sd, &preview_v4l2_ops);
1984 sd->internal_ops = &preview_v4l2_internal_ops;
1985 strlcpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name));
1986 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
1987 v4l2_set_subdevdata(sd, prev);
1988 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1989
1990 v4l2_ctrl_handler_init(&prev->ctrls, 2);
1991 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_BRIGHTNESS,
1992 ISPPRV_BRIGHT_LOW, ISPPRV_BRIGHT_HIGH,
1993 ISPPRV_BRIGHT_STEP, ISPPRV_BRIGHT_DEF);
1994 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_CONTRAST,
1995 ISPPRV_CONTRAST_LOW, ISPPRV_CONTRAST_HIGH,
1996 ISPPRV_CONTRAST_STEP, ISPPRV_CONTRAST_DEF);
1997 v4l2_ctrl_handler_setup(&prev->ctrls);
1998 sd->ctrl_handler = &prev->ctrls;
1999
2000 pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
2001 pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
2002
2003 me->ops = &preview_media_ops;
2004 ret = media_entity_init(me, PREV_PADS_NUM, pads, 0);
2005 if (ret < 0)
2006 return ret;
2007
2008 preview_init_formats(sd, NULL);
2009
2010 /* According to the OMAP34xx TRM, video buffers need to be aligned on a
2011 * 32 bytes boundary. However, an undocumented hardware bug requires a
2012 * 64 bytes boundary at the preview engine input.
2013 */
2014 prev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2015 prev->video_in.ops = &preview_video_ops;
2016 prev->video_in.isp = to_isp_device(prev);
2017 prev->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2018 prev->video_in.bpl_alignment = 64;
2019 prev->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2020 prev->video_out.ops = &preview_video_ops;
2021 prev->video_out.isp = to_isp_device(prev);
2022 prev->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2023 prev->video_out.bpl_alignment = 32;
2024
2025 ret = omap3isp_video_init(&prev->video_in, "preview");
2026 if (ret < 0)
2027 return ret;
2028
2029 ret = omap3isp_video_init(&prev->video_out, "preview");
2030 if (ret < 0)
2031 return ret;
2032
2033 /* Connect the video nodes to the previewer subdev. */
2034 ret = media_entity_create_link(&prev->video_in.video.entity, 0,
2035 &prev->subdev.entity, PREV_PAD_SINK, 0);
2036 if (ret < 0)
2037 return ret;
2038
2039 ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
2040 &prev->video_out.video.entity, 0, 0);
2041 if (ret < 0)
2042 return ret;
2043
2044 return 0;
2045}
2046
2047void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
2048{
2049 media_entity_cleanup(&prev->subdev.entity);
2050
2051 v4l2_device_unregister_subdev(&prev->subdev);
2052 v4l2_ctrl_handler_free(&prev->ctrls);
2053 omap3isp_video_unregister(&prev->video_in);
2054 omap3isp_video_unregister(&prev->video_out);
2055}
2056
2057int omap3isp_preview_register_entities(struct isp_prev_device *prev,
2058 struct v4l2_device *vdev)
2059{
2060 int ret;
2061
2062 /* Register the subdev and video nodes. */
2063 ret = v4l2_device_register_subdev(vdev, &prev->subdev);
2064 if (ret < 0)
2065 goto error;
2066
2067 ret = omap3isp_video_register(&prev->video_in, vdev);
2068 if (ret < 0)
2069 goto error;
2070
2071 ret = omap3isp_video_register(&prev->video_out, vdev);
2072 if (ret < 0)
2073 goto error;
2074
2075 return 0;
2076
2077error:
2078 omap3isp_preview_unregister_entities(prev);
2079 return ret;
2080}
2081
2082/* -----------------------------------------------------------------------------
2083 * ISP previewer initialisation and cleanup
2084 */
2085
2086void omap3isp_preview_cleanup(struct isp_device *isp)
2087{
2088}
2089
2090/*
2091 * isp_preview_init - Previewer initialization.
2092 * @dev : Pointer to ISP device
2093 * return -ENOMEM or zero on success
2094 */
2095int omap3isp_preview_init(struct isp_device *isp)
2096{
2097 struct isp_prev_device *prev = &isp->isp_prev;
2098 int ret;
2099
2100 spin_lock_init(&prev->lock);
2101 init_waitqueue_head(&prev->wait);
2102 preview_init_params(prev);
2103
2104 ret = preview_init_entities(prev);
2105 if (ret < 0)
2106 goto out;
2107
2108out:
2109 if (ret)
2110 omap3isp_preview_cleanup(isp);
2111
2112 return ret;
2113}
diff --git a/drivers/media/video/omap3isp/isppreview.h b/drivers/media/video/omap3isp/isppreview.h
new file mode 100644
index 00000000000..fa943bd05c7
--- /dev/null
+++ b/drivers/media/video/omap3isp/isppreview.h
@@ -0,0 +1,214 @@
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#define NO_AVE 0x0
49#define AVE_2_PIX 0x1
50#define AVE_4_PIX 0x2
51#define AVE_8_PIX 0x3
52
53/* Features list */
54#define PREV_LUMA_ENHANCE OMAP3ISP_PREV_LUMAENH
55#define PREV_INVERSE_ALAW OMAP3ISP_PREV_INVALAW
56#define PREV_HORZ_MEDIAN_FILTER OMAP3ISP_PREV_HRZ_MED
57#define PREV_CFA OMAP3ISP_PREV_CFA
58#define PREV_CHROMA_SUPPRESS OMAP3ISP_PREV_CHROMA_SUPP
59#define PREV_WB OMAP3ISP_PREV_WB
60#define PREV_BLKADJ OMAP3ISP_PREV_BLKADJ
61#define PREV_RGB2RGB OMAP3ISP_PREV_RGB2RGB
62#define PREV_COLOR_CONV OMAP3ISP_PREV_COLOR_CONV
63#define PREV_YCLIMITS OMAP3ISP_PREV_YC_LIMIT
64#define PREV_DEFECT_COR OMAP3ISP_PREV_DEFECT_COR
65#define PREV_GAMMA_BYPASS OMAP3ISP_PREV_GAMMABYPASS
66#define PREV_DARK_FRAME_CAPTURE OMAP3ISP_PREV_DRK_FRM_CAPTURE
67#define PREV_DARK_FRAME_SUBTRACT OMAP3ISP_PREV_DRK_FRM_SUBTRACT
68#define PREV_LENS_SHADING OMAP3ISP_PREV_LENS_SHADING
69#define PREV_NOISE_FILTER OMAP3ISP_PREV_NF
70#define PREV_GAMMA OMAP3ISP_PREV_GAMMA
71
72#define PREV_CONTRAST (1 << 17)
73#define PREV_BRIGHTNESS (1 << 18)
74#define PREV_AVERAGER (1 << 19)
75#define PREV_FEATURES_END (1 << 20)
76
77enum preview_input_entity {
78 PREVIEW_INPUT_NONE,
79 PREVIEW_INPUT_CCDC,
80 PREVIEW_INPUT_MEMORY,
81};
82
83#define PREVIEW_OUTPUT_RESIZER (1 << 1)
84#define PREVIEW_OUTPUT_MEMORY (1 << 2)
85
86/* Configure byte layout of YUV image */
87enum preview_ycpos_mode {
88 YCPOS_YCrYCb = 0,
89 YCPOS_YCbYCr = 1,
90 YCPOS_CbYCrY = 2,
91 YCPOS_CrYCbY = 3
92};
93
94/*
95 * struct prev_params - Structure for all configuration
96 * @features: Set of features enabled.
97 * @cfa: CFA coefficients.
98 * @csup: Chroma suppression coefficients.
99 * @luma: Luma enhancement coefficients.
100 * @nf: Noise filter coefficients.
101 * @dcor: Noise filter coefficients.
102 * @gamma: Gamma coefficients.
103 * @wbal: White Balance parameters.
104 * @blk_adj: Black adjustment parameters.
105 * @rgb2rgb: RGB blending parameters.
106 * @rgb2ycbcr: RGB to ycbcr parameters.
107 * @hmed: Horizontal median filter.
108 * @yclimit: YC limits parameters.
109 * @average: Downsampling rate for averager.
110 * @contrast: Contrast.
111 * @brightness: Brightness.
112 */
113struct prev_params {
114 u32 features;
115 struct omap3isp_prev_cfa cfa;
116 struct omap3isp_prev_csup csup;
117 struct omap3isp_prev_luma luma;
118 struct omap3isp_prev_nf nf;
119 struct omap3isp_prev_dcor dcor;
120 struct omap3isp_prev_gtables gamma;
121 struct omap3isp_prev_wbal wbal;
122 struct omap3isp_prev_blkadj blk_adj;
123 struct omap3isp_prev_rgbtorgb rgb2rgb;
124 struct omap3isp_prev_csc rgb2ycbcr;
125 struct omap3isp_prev_hmed hmed;
126 struct omap3isp_prev_yclimit yclimit;
127 u8 average;
128 u8 contrast;
129 u8 brightness;
130};
131
132/*
133 * struct isptables_update - Structure for Table Configuration.
134 * @update: Specifies which tables should be updated.
135 * @flag: Specifies which tables should be enabled.
136 * @nf: Pointer to structure for Noise Filter
137 * @lsc: Pointer to LSC gain table. (currently not used)
138 * @gamma: Pointer to gamma correction tables.
139 * @cfa: Pointer to color filter array configuration.
140 * @wbal: Pointer to colour and digital gain configuration.
141 */
142struct isptables_update {
143 u32 update;
144 u32 flag;
145 struct omap3isp_prev_nf *nf;
146 u32 *lsc;
147 struct omap3isp_prev_gtables *gamma;
148 struct omap3isp_prev_cfa *cfa;
149 struct omap3isp_prev_wbal *wbal;
150};
151
152/* Sink and source previewer pads */
153#define PREV_PAD_SINK 0
154#define PREV_PAD_SOURCE 1
155#define PREV_PADS_NUM 2
156
157/*
158 * struct isp_prev_device - Structure for storing ISP Preview module information
159 * @subdev: V4L2 subdevice
160 * @pads: Media entity pads
161 * @formats: Active formats at the subdev pad
162 * @input: Module currently connected to the input pad
163 * @output: Bitmask of the active output
164 * @video_in: Input video entity
165 * @video_out: Output video entity
166 * @error: A hardware error occurred during capture
167 * @params: Module configuration data
168 * @shadow_update: If set, update the hardware configured in the next interrupt
169 * @underrun: Whether the preview entity has queued buffers on the output
170 * @state: Current preview pipeline state
171 * @lock: Shadow update lock
172 * @update: Bitmask of the parameters to be updated
173 *
174 * This structure is used to store the OMAP ISP Preview module Information.
175 */
176struct isp_prev_device {
177 struct v4l2_subdev subdev;
178 struct media_pad pads[PREV_PADS_NUM];
179 struct v4l2_mbus_framefmt formats[PREV_PADS_NUM];
180
181 struct v4l2_ctrl_handler ctrls;
182
183 enum preview_input_entity input;
184 unsigned int output;
185 struct isp_video video_in;
186 struct isp_video video_out;
187 unsigned int error;
188
189 struct prev_params params;
190 unsigned int shadow_update:1;
191 enum isp_pipeline_stream_state state;
192 wait_queue_head_t wait;
193 atomic_t stopping;
194 spinlock_t lock;
195 u32 update;
196};
197
198struct isp_device;
199
200int omap3isp_preview_init(struct isp_device *isp);
201void omap3isp_preview_cleanup(struct isp_device *isp);
202
203int omap3isp_preview_register_entities(struct isp_prev_device *prv,
204 struct v4l2_device *vdev);
205void omap3isp_preview_unregister_entities(struct isp_prev_device *prv);
206
207void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev);
208void omap3isp_preview_isr(struct isp_prev_device *prev);
209
210int omap3isp_preview_busy(struct isp_prev_device *isp_prev);
211
212void omap3isp_preview_restore_context(struct isp_device *isp);
213
214#endif /* OMAP3_ISP_PREVIEW_H */
diff --git a/drivers/media/video/omap3isp/ispqueue.c b/drivers/media/video/omap3isp/ispqueue.c
new file mode 100644
index 00000000000..9c317148205
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispqueue.c
@@ -0,0 +1,1153 @@
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 of 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->m.userptr != buf->vbuf.m.userptr) {
872 isp_video_buffer_cleanup(buf);
873 buf->vbuf.m.userptr = vbuf->m.userptr;
874 buf->prepared = 0;
875 }
876
877 if (!buf->prepared) {
878 ret = isp_video_buffer_prepare(buf);
879 if (ret < 0)
880 goto done;
881 buf->prepared = 1;
882 }
883
884 isp_video_buffer_cache_sync(buf);
885
886 buf->state = ISP_BUF_STATE_QUEUED;
887 list_add_tail(&buf->stream, &queue->queue);
888
889 if (queue->streaming) {
890 spin_lock_irqsave(&queue->irqlock, flags);
891 queue->ops->buffer_queue(buf);
892 spin_unlock_irqrestore(&queue->irqlock, flags);
893 }
894
895 ret = 0;
896
897done:
898 mutex_unlock(&queue->lock);
899 return ret;
900}
901
902/**
903 * omap3isp_video_queue_dqbuf - Dequeue a buffer
904 *
905 * This function is intended to be used as a VIDIOC_DQBUF ioctl handler.
906 *
907 * The v4l2_buffer structure passed from userspace is first sanity tested. If
908 * sane, the buffer is then processed and added to the main queue and, if the
909 * queue is streaming, to the IRQ queue.
910 *
911 * Before being enqueued, USERPTR buffers are checked for address changes. If
912 * the buffer has a different userspace address, the old memory area is unlocked
913 * and the new memory area is locked.
914 */
915int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
916 struct v4l2_buffer *vbuf, int nonblocking)
917{
918 struct isp_video_buffer *buf;
919 int ret;
920
921 if (vbuf->type != queue->type)
922 return -EINVAL;
923
924 mutex_lock(&queue->lock);
925
926 if (list_empty(&queue->queue)) {
927 ret = -EINVAL;
928 goto done;
929 }
930
931 buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
932 ret = isp_video_buffer_wait(buf, nonblocking);
933 if (ret < 0)
934 goto done;
935
936 list_del(&buf->stream);
937
938 isp_video_buffer_query(buf, vbuf);
939 buf->state = ISP_BUF_STATE_IDLE;
940 vbuf->flags &= ~V4L2_BUF_FLAG_QUEUED;
941
942done:
943 mutex_unlock(&queue->lock);
944 return ret;
945}
946
947/**
948 * omap3isp_video_queue_streamon - Start streaming
949 *
950 * This function is intended to be used as a VIDIOC_STREAMON ioctl handler. It
951 * starts streaming on the queue and calls the buffer_queue operation for all
952 * queued buffers.
953 *
954 * Return 0 on success.
955 */
956int omap3isp_video_queue_streamon(struct isp_video_queue *queue)
957{
958 struct isp_video_buffer *buf;
959 unsigned long flags;
960
961 mutex_lock(&queue->lock);
962
963 if (queue->streaming)
964 goto done;
965
966 queue->streaming = 1;
967
968 spin_lock_irqsave(&queue->irqlock, flags);
969 list_for_each_entry(buf, &queue->queue, stream)
970 queue->ops->buffer_queue(buf);
971 spin_unlock_irqrestore(&queue->irqlock, flags);
972
973done:
974 mutex_unlock(&queue->lock);
975 return 0;
976}
977
978/**
979 * omap3isp_video_queue_streamoff - Stop streaming
980 *
981 * This function is intended to be used as a VIDIOC_STREAMOFF ioctl handler. It
982 * stops streaming on the queue and wakes up all the buffers.
983 *
984 * Drivers must stop the hardware and synchronize with interrupt handlers and/or
985 * delayed works before calling this function to make sure no buffer will be
986 * touched by the driver and/or hardware.
987 */
988void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
989{
990 struct isp_video_buffer *buf;
991 unsigned long flags;
992 unsigned int i;
993
994 mutex_lock(&queue->lock);
995
996 if (!queue->streaming)
997 goto done;
998
999 queue->streaming = 0;
1000
1001 spin_lock_irqsave(&queue->irqlock, flags);
1002 for (i = 0; i < queue->count; ++i) {
1003 buf = queue->buffers[i];
1004
1005 if (buf->state == ISP_BUF_STATE_ACTIVE)
1006 wake_up(&buf->wait);
1007
1008 buf->state = ISP_BUF_STATE_IDLE;
1009 }
1010 spin_unlock_irqrestore(&queue->irqlock, flags);
1011
1012 INIT_LIST_HEAD(&queue->queue);
1013
1014done:
1015 mutex_unlock(&queue->lock);
1016}
1017
1018/**
1019 * omap3isp_video_queue_discard_done - Discard all buffers marked as DONE
1020 *
1021 * This function is intended to be used with suspend/resume operations. It
1022 * discards all 'done' buffers as they would be too old to be requested after
1023 * resume.
1024 *
1025 * Drivers must stop the hardware and synchronize with interrupt handlers and/or
1026 * delayed works before calling this function to make sure no buffer will be
1027 * touched by the driver and/or hardware.
1028 */
1029void omap3isp_video_queue_discard_done(struct isp_video_queue *queue)
1030{
1031 struct isp_video_buffer *buf;
1032 unsigned int i;
1033
1034 mutex_lock(&queue->lock);
1035
1036 if (!queue->streaming)
1037 goto done;
1038
1039 for (i = 0; i < queue->count; ++i) {
1040 buf = queue->buffers[i];
1041
1042 if (buf->state == ISP_BUF_STATE_DONE)
1043 buf->state = ISP_BUF_STATE_ERROR;
1044 }
1045
1046done:
1047 mutex_unlock(&queue->lock);
1048}
1049
1050static void isp_video_queue_vm_open(struct vm_area_struct *vma)
1051{
1052 struct isp_video_buffer *buf = vma->vm_private_data;
1053
1054 buf->vma_use_count++;
1055}
1056
1057static void isp_video_queue_vm_close(struct vm_area_struct *vma)
1058{
1059 struct isp_video_buffer *buf = vma->vm_private_data;
1060
1061 buf->vma_use_count--;
1062}
1063
1064static const struct vm_operations_struct isp_video_queue_vm_ops = {
1065 .open = isp_video_queue_vm_open,
1066 .close = isp_video_queue_vm_close,
1067};
1068
1069/**
1070 * omap3isp_video_queue_mmap - Map buffers to userspace
1071 *
1072 * This function is intended to be used as an mmap() file operation handler. It
1073 * maps a buffer to userspace based on the VMA offset.
1074 *
1075 * Only buffers of memory type MMAP are supported.
1076 */
1077int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
1078 struct vm_area_struct *vma)
1079{
1080 struct isp_video_buffer *uninitialized_var(buf);
1081 unsigned long size;
1082 unsigned int i;
1083 int ret = 0;
1084
1085 mutex_lock(&queue->lock);
1086
1087 for (i = 0; i < queue->count; ++i) {
1088 buf = queue->buffers[i];
1089 if ((buf->vbuf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
1090 break;
1091 }
1092
1093 if (i == queue->count) {
1094 ret = -EINVAL;
1095 goto done;
1096 }
1097
1098 size = vma->vm_end - vma->vm_start;
1099
1100 if (buf->vbuf.memory != V4L2_MEMORY_MMAP ||
1101 size != PAGE_ALIGN(buf->vbuf.length)) {
1102 ret = -EINVAL;
1103 goto done;
1104 }
1105
1106 ret = remap_vmalloc_range(vma, buf->vaddr, 0);
1107 if (ret < 0)
1108 goto done;
1109
1110 vma->vm_ops = &isp_video_queue_vm_ops;
1111 vma->vm_private_data = buf;
1112 isp_video_queue_vm_open(vma);
1113
1114done:
1115 mutex_unlock(&queue->lock);
1116 return ret;
1117}
1118
1119/**
1120 * omap3isp_video_queue_poll - Poll video queue state
1121 *
1122 * This function is intended to be used as a poll() file operation handler. It
1123 * polls the state of the video buffer at the front of the queue and returns an
1124 * events mask.
1125 *
1126 * If no buffer is present at the front of the queue, POLLERR is returned.
1127 */
1128unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
1129 struct file *file, poll_table *wait)
1130{
1131 struct isp_video_buffer *buf;
1132 unsigned int mask = 0;
1133
1134 mutex_lock(&queue->lock);
1135 if (list_empty(&queue->queue)) {
1136 mask |= POLLERR;
1137 goto done;
1138 }
1139 buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
1140
1141 poll_wait(file, &buf->wait, wait);
1142 if (buf->state == ISP_BUF_STATE_DONE ||
1143 buf->state == ISP_BUF_STATE_ERROR) {
1144 if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1145 mask |= POLLIN | POLLRDNORM;
1146 else
1147 mask |= POLLOUT | POLLWRNORM;
1148 }
1149
1150done:
1151 mutex_unlock(&queue->lock);
1152 return mask;
1153}
diff --git a/drivers/media/video/omap3isp/ispqueue.h b/drivers/media/video/omap3isp/ispqueue.h
new file mode 100644
index 00000000000..92c5a12157d
--- /dev/null
+++ b/drivers/media/video/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 unsigned long 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/video/omap3isp/ispreg.h b/drivers/media/video/omap3isp/ispreg.h
new file mode 100644
index 00000000000..69f6af6f6b9
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispreg.h
@@ -0,0 +1,1589 @@
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 ISPPRV_MAXOUTPUT_WIDTH 1280
406#define ISPPRV_MAXOUTPUT_WIDTH_ES2 3300
407#define ISPPRV_MAXOUTPUT_WIDTH_3630 4096
408#define ISPRSZ_MIN_OUTPUT 64
409#define ISPRSZ_MAX_OUTPUT 3312
410
411/* Resizer module register offset */
412#define ISPRSZ_PID (0x000)
413#define ISPRSZ_PCR (0x004)
414#define ISPRSZ_CNT (0x008)
415#define ISPRSZ_OUT_SIZE (0x00C)
416#define ISPRSZ_IN_START (0x010)
417#define ISPRSZ_IN_SIZE (0x014)
418#define ISPRSZ_SDR_INADD (0x018)
419#define ISPRSZ_SDR_INOFF (0x01C)
420#define ISPRSZ_SDR_OUTADD (0x020)
421#define ISPRSZ_SDR_OUTOFF (0x024)
422#define ISPRSZ_HFILT10 (0x028)
423#define ISPRSZ_HFILT32 (0x02C)
424#define ISPRSZ_HFILT54 (0x030)
425#define ISPRSZ_HFILT76 (0x034)
426#define ISPRSZ_HFILT98 (0x038)
427#define ISPRSZ_HFILT1110 (0x03C)
428#define ISPRSZ_HFILT1312 (0x040)
429#define ISPRSZ_HFILT1514 (0x044)
430#define ISPRSZ_HFILT1716 (0x048)
431#define ISPRSZ_HFILT1918 (0x04C)
432#define ISPRSZ_HFILT2120 (0x050)
433#define ISPRSZ_HFILT2322 (0x054)
434#define ISPRSZ_HFILT2524 (0x058)
435#define ISPRSZ_HFILT2726 (0x05C)
436#define ISPRSZ_HFILT2928 (0x060)
437#define ISPRSZ_HFILT3130 (0x064)
438#define ISPRSZ_VFILT10 (0x068)
439#define ISPRSZ_VFILT32 (0x06C)
440#define ISPRSZ_VFILT54 (0x070)
441#define ISPRSZ_VFILT76 (0x074)
442#define ISPRSZ_VFILT98 (0x078)
443#define ISPRSZ_VFILT1110 (0x07C)
444#define ISPRSZ_VFILT1312 (0x080)
445#define ISPRSZ_VFILT1514 (0x084)
446#define ISPRSZ_VFILT1716 (0x088)
447#define ISPRSZ_VFILT1918 (0x08C)
448#define ISPRSZ_VFILT2120 (0x090)
449#define ISPRSZ_VFILT2322 (0x094)
450#define ISPRSZ_VFILT2524 (0x098)
451#define ISPRSZ_VFILT2726 (0x09C)
452#define ISPRSZ_VFILT2928 (0x0A0)
453#define ISPRSZ_VFILT3130 (0x0A4)
454#define ISPRSZ_YENH (0x0A8)
455
456#define ISP_INT_CLR 0xFF113F11
457#define ISPPRV_PCR_EN 1
458#define ISPPRV_PCR_BUSY (1 << 1)
459#define ISPPRV_PCR_SOURCE (1 << 2)
460#define ISPPRV_PCR_ONESHOT (1 << 3)
461#define ISPPRV_PCR_WIDTH (1 << 4)
462#define ISPPRV_PCR_INVALAW (1 << 5)
463#define ISPPRV_PCR_DRKFEN (1 << 6)
464#define ISPPRV_PCR_DRKFCAP (1 << 7)
465#define ISPPRV_PCR_HMEDEN (1 << 8)
466#define ISPPRV_PCR_NFEN (1 << 9)
467#define ISPPRV_PCR_CFAEN (1 << 10)
468#define ISPPRV_PCR_CFAFMT_SHIFT 11
469#define ISPPRV_PCR_CFAFMT_MASK 0x7800
470#define ISPPRV_PCR_CFAFMT_BAYER (0 << 11)
471#define ISPPRV_PCR_CFAFMT_SONYVGA (1 << 11)
472#define ISPPRV_PCR_CFAFMT_RGBFOVEON (2 << 11)
473#define ISPPRV_PCR_CFAFMT_DNSPL (3 << 11)
474#define ISPPRV_PCR_CFAFMT_HONEYCOMB (4 << 11)
475#define ISPPRV_PCR_CFAFMT_RRGGBBFOVEON (5 << 11)
476#define ISPPRV_PCR_YNENHEN (1 << 15)
477#define ISPPRV_PCR_SUPEN (1 << 16)
478#define ISPPRV_PCR_YCPOS_SHIFT 17
479#define ISPPRV_PCR_YCPOS_YCrYCb (0 << 17)
480#define ISPPRV_PCR_YCPOS_YCbYCr (1 << 17)
481#define ISPPRV_PCR_YCPOS_CbYCrY (2 << 17)
482#define ISPPRV_PCR_YCPOS_CrYCbY (3 << 17)
483#define ISPPRV_PCR_RSZPORT (1 << 19)
484#define ISPPRV_PCR_SDRPORT (1 << 20)
485#define ISPPRV_PCR_SCOMP_EN (1 << 21)
486#define ISPPRV_PCR_SCOMP_SFT_SHIFT (22)
487#define ISPPRV_PCR_SCOMP_SFT_MASK (7 << 22)
488#define ISPPRV_PCR_GAMMA_BYPASS (1 << 26)
489#define ISPPRV_PCR_DCOREN (1 << 27)
490#define ISPPRV_PCR_DCCOUP (1 << 28)
491#define ISPPRV_PCR_DRK_FAIL (1 << 31)
492
493#define ISPPRV_HORZ_INFO_EPH_SHIFT 0
494#define ISPPRV_HORZ_INFO_EPH_MASK 0x3fff
495#define ISPPRV_HORZ_INFO_SPH_SHIFT 16
496#define ISPPRV_HORZ_INFO_SPH_MASK 0x3fff0
497
498#define ISPPRV_VERT_INFO_ELV_SHIFT 0
499#define ISPPRV_VERT_INFO_ELV_MASK 0x3fff
500#define ISPPRV_VERT_INFO_SLV_SHIFT 16
501#define ISPPRV_VERT_INFO_SLV_MASK 0x3fff0
502
503#define ISPPRV_AVE_EVENDIST_SHIFT 2
504#define ISPPRV_AVE_EVENDIST_1 0x0
505#define ISPPRV_AVE_EVENDIST_2 0x1
506#define ISPPRV_AVE_EVENDIST_3 0x2
507#define ISPPRV_AVE_EVENDIST_4 0x3
508#define ISPPRV_AVE_ODDDIST_SHIFT 4
509#define ISPPRV_AVE_ODDDIST_1 0x0
510#define ISPPRV_AVE_ODDDIST_2 0x1
511#define ISPPRV_AVE_ODDDIST_3 0x2
512#define ISPPRV_AVE_ODDDIST_4 0x3
513
514#define ISPPRV_HMED_THRESHOLD_SHIFT 0
515#define ISPPRV_HMED_EVENDIST (1 << 8)
516#define ISPPRV_HMED_ODDDIST (1 << 9)
517
518#define ISPPRV_WBGAIN_COEF0_SHIFT 0
519#define ISPPRV_WBGAIN_COEF1_SHIFT 8
520#define ISPPRV_WBGAIN_COEF2_SHIFT 16
521#define ISPPRV_WBGAIN_COEF3_SHIFT 24
522
523#define ISPPRV_WBSEL_COEF0 0x0
524#define ISPPRV_WBSEL_COEF1 0x1
525#define ISPPRV_WBSEL_COEF2 0x2
526#define ISPPRV_WBSEL_COEF3 0x3
527
528#define ISPPRV_WBSEL_N0_0_SHIFT 0
529#define ISPPRV_WBSEL_N0_1_SHIFT 2
530#define ISPPRV_WBSEL_N0_2_SHIFT 4
531#define ISPPRV_WBSEL_N0_3_SHIFT 6
532#define ISPPRV_WBSEL_N1_0_SHIFT 8
533#define ISPPRV_WBSEL_N1_1_SHIFT 10
534#define ISPPRV_WBSEL_N1_2_SHIFT 12
535#define ISPPRV_WBSEL_N1_3_SHIFT 14
536#define ISPPRV_WBSEL_N2_0_SHIFT 16
537#define ISPPRV_WBSEL_N2_1_SHIFT 18
538#define ISPPRV_WBSEL_N2_2_SHIFT 20
539#define ISPPRV_WBSEL_N2_3_SHIFT 22
540#define ISPPRV_WBSEL_N3_0_SHIFT 24
541#define ISPPRV_WBSEL_N3_1_SHIFT 26
542#define ISPPRV_WBSEL_N3_2_SHIFT 28
543#define ISPPRV_WBSEL_N3_3_SHIFT 30
544
545#define ISPPRV_CFA_GRADTH_HOR_SHIFT 0
546#define ISPPRV_CFA_GRADTH_VER_SHIFT 8
547
548#define ISPPRV_BLKADJOFF_B_SHIFT 0
549#define ISPPRV_BLKADJOFF_G_SHIFT 8
550#define ISPPRV_BLKADJOFF_R_SHIFT 16
551
552#define ISPPRV_RGB_MAT1_MTX_RR_SHIFT 0
553#define ISPPRV_RGB_MAT1_MTX_GR_SHIFT 16
554
555#define ISPPRV_RGB_MAT2_MTX_BR_SHIFT 0
556#define ISPPRV_RGB_MAT2_MTX_RG_SHIFT 16
557
558#define ISPPRV_RGB_MAT3_MTX_GG_SHIFT 0
559#define ISPPRV_RGB_MAT3_MTX_BG_SHIFT 16
560
561#define ISPPRV_RGB_MAT4_MTX_RB_SHIFT 0
562#define ISPPRV_RGB_MAT4_MTX_GB_SHIFT 16
563
564#define ISPPRV_RGB_MAT5_MTX_BB_SHIFT 0
565
566#define ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT 0
567#define ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT 16
568
569#define ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT 0
570
571#define ISPPRV_CSC0_RY_SHIFT 0
572#define ISPPRV_CSC0_GY_SHIFT 10
573#define ISPPRV_CSC0_BY_SHIFT 20
574
575#define ISPPRV_CSC1_RCB_SHIFT 0
576#define ISPPRV_CSC1_GCB_SHIFT 10
577#define ISPPRV_CSC1_BCB_SHIFT 20
578
579#define ISPPRV_CSC2_RCR_SHIFT 0
580#define ISPPRV_CSC2_GCR_SHIFT 10
581#define ISPPRV_CSC2_BCR_SHIFT 20
582
583#define ISPPRV_CSC_OFFSET_CR_SHIFT 0
584#define ISPPRV_CSC_OFFSET_CB_SHIFT 8
585#define ISPPRV_CSC_OFFSET_Y_SHIFT 16
586
587#define ISPPRV_CNT_BRT_BRT_SHIFT 0
588#define ISPPRV_CNT_BRT_CNT_SHIFT 8
589
590#define ISPPRV_CONTRAST_MAX 0x10
591#define ISPPRV_CONTRAST_MIN 0xFF
592#define ISPPRV_BRIGHT_MIN 0x00
593#define ISPPRV_BRIGHT_MAX 0xFF
594
595#define ISPPRV_CSUP_CSUPG_SHIFT 0
596#define ISPPRV_CSUP_THRES_SHIFT 8
597#define ISPPRV_CSUP_HPYF_SHIFT 16
598
599#define ISPPRV_SETUP_YC_MINC_SHIFT 0
600#define ISPPRV_SETUP_YC_MAXC_SHIFT 8
601#define ISPPRV_SETUP_YC_MINY_SHIFT 16
602#define ISPPRV_SETUP_YC_MAXY_SHIFT 24
603#define ISPPRV_YC_MAX 0xFF
604#define ISPPRV_YC_MIN 0x0
605
606/* Define bit fields within selected registers */
607#define ISP_REVISION_SHIFT 0
608
609#define ISP_SYSCONFIG_AUTOIDLE (1 << 0)
610#define ISP_SYSCONFIG_SOFTRESET (1 << 1)
611#define ISP_SYSCONFIG_MIDLEMODE_SHIFT 12
612#define ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY 0x0
613#define ISP_SYSCONFIG_MIDLEMODE_NOSTANBY 0x1
614#define ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY 0x2
615
616#define ISP_SYSSTATUS_RESETDONE 0
617
618#define IRQ0ENABLE_CSIA_IRQ (1 << 0)
619#define IRQ0ENABLE_CSIC_IRQ (1 << 1)
620#define IRQ0ENABLE_CCP2_LCM_IRQ (1 << 3)
621#define IRQ0ENABLE_CCP2_LC0_IRQ (1 << 4)
622#define IRQ0ENABLE_CCP2_LC1_IRQ (1 << 5)
623#define IRQ0ENABLE_CCP2_LC2_IRQ (1 << 6)
624#define IRQ0ENABLE_CCP2_LC3_IRQ (1 << 7)
625#define IRQ0ENABLE_CSIB_IRQ (IRQ0ENABLE_CCP2_LCM_IRQ | \
626 IRQ0ENABLE_CCP2_LC0_IRQ | \
627 IRQ0ENABLE_CCP2_LC1_IRQ | \
628 IRQ0ENABLE_CCP2_LC2_IRQ | \
629 IRQ0ENABLE_CCP2_LC3_IRQ)
630
631#define IRQ0ENABLE_CCDC_VD0_IRQ (1 << 8)
632#define IRQ0ENABLE_CCDC_VD1_IRQ (1 << 9)
633#define IRQ0ENABLE_CCDC_VD2_IRQ (1 << 10)
634#define IRQ0ENABLE_CCDC_ERR_IRQ (1 << 11)
635#define IRQ0ENABLE_H3A_AF_DONE_IRQ (1 << 12)
636#define IRQ0ENABLE_H3A_AWB_DONE_IRQ (1 << 13)
637#define IRQ0ENABLE_HIST_DONE_IRQ (1 << 16)
638#define IRQ0ENABLE_CCDC_LSC_DONE_IRQ (1 << 17)
639#define IRQ0ENABLE_CCDC_LSC_PREF_COMP_IRQ (1 << 18)
640#define IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ (1 << 19)
641#define IRQ0ENABLE_PRV_DONE_IRQ (1 << 20)
642#define IRQ0ENABLE_RSZ_DONE_IRQ (1 << 24)
643#define IRQ0ENABLE_OVF_IRQ (1 << 25)
644#define IRQ0ENABLE_PING_IRQ (1 << 26)
645#define IRQ0ENABLE_PONG_IRQ (1 << 27)
646#define IRQ0ENABLE_MMU_ERR_IRQ (1 << 28)
647#define IRQ0ENABLE_OCP_ERR_IRQ (1 << 29)
648#define IRQ0ENABLE_SEC_ERR_IRQ (1 << 30)
649#define IRQ0ENABLE_HS_VS_IRQ (1 << 31)
650
651#define IRQ0STATUS_CSIA_IRQ (1 << 0)
652#define IRQ0STATUS_CSI2C_IRQ (1 << 1)
653#define IRQ0STATUS_CCP2_LCM_IRQ (1 << 3)
654#define IRQ0STATUS_CCP2_LC0_IRQ (1 << 4)
655#define IRQ0STATUS_CSIB_IRQ (IRQ0STATUS_CCP2_LCM_IRQ | \
656 IRQ0STATUS_CCP2_LC0_IRQ)
657
658#define IRQ0STATUS_CSIB_LC1_IRQ (1 << 5)
659#define IRQ0STATUS_CSIB_LC2_IRQ (1 << 6)
660#define IRQ0STATUS_CSIB_LC3_IRQ (1 << 7)
661#define IRQ0STATUS_CCDC_VD0_IRQ (1 << 8)
662#define IRQ0STATUS_CCDC_VD1_IRQ (1 << 9)
663#define IRQ0STATUS_CCDC_VD2_IRQ (1 << 10)
664#define IRQ0STATUS_CCDC_ERR_IRQ (1 << 11)
665#define IRQ0STATUS_H3A_AF_DONE_IRQ (1 << 12)
666#define IRQ0STATUS_H3A_AWB_DONE_IRQ (1 << 13)
667#define IRQ0STATUS_HIST_DONE_IRQ (1 << 16)
668#define IRQ0STATUS_CCDC_LSC_DONE_IRQ (1 << 17)
669#define IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ (1 << 18)
670#define IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ (1 << 19)
671#define IRQ0STATUS_PRV_DONE_IRQ (1 << 20)
672#define IRQ0STATUS_RSZ_DONE_IRQ (1 << 24)
673#define IRQ0STATUS_OVF_IRQ (1 << 25)
674#define IRQ0STATUS_PING_IRQ (1 << 26)
675#define IRQ0STATUS_PONG_IRQ (1 << 27)
676#define IRQ0STATUS_MMU_ERR_IRQ (1 << 28)
677#define IRQ0STATUS_OCP_ERR_IRQ (1 << 29)
678#define IRQ0STATUS_SEC_ERR_IRQ (1 << 30)
679#define IRQ0STATUS_HS_VS_IRQ (1 << 31)
680
681#define TCTRL_GRESET_LEN 0
682
683#define TCTRL_PSTRB_REPLAY_DELAY 0
684#define TCTRL_PSTRB_REPLAY_COUNTER_SHIFT 25
685
686#define ISPCTRL_PAR_SER_CLK_SEL_PARALLEL 0x0
687#define ISPCTRL_PAR_SER_CLK_SEL_CSIA 0x1
688#define ISPCTRL_PAR_SER_CLK_SEL_CSIB 0x2
689#define ISPCTRL_PAR_SER_CLK_SEL_CSIC 0x3
690#define ISPCTRL_PAR_SER_CLK_SEL_MASK 0x3
691
692#define ISPCTRL_PAR_BRIDGE_SHIFT 2
693#define ISPCTRL_PAR_BRIDGE_DISABLE (0x0 << 2)
694#define ISPCTRL_PAR_BRIDGE_LENDIAN (0x2 << 2)
695#define ISPCTRL_PAR_BRIDGE_BENDIAN (0x3 << 2)
696#define ISPCTRL_PAR_BRIDGE_MASK (0x3 << 2)
697
698#define ISPCTRL_PAR_CLK_POL_SHIFT 4
699#define ISPCTRL_PAR_CLK_POL_INV (1 << 4)
700#define ISPCTRL_PING_PONG_EN (1 << 5)
701#define ISPCTRL_SHIFT_SHIFT 6
702#define ISPCTRL_SHIFT_0 (0x0 << 6)
703#define ISPCTRL_SHIFT_2 (0x1 << 6)
704#define ISPCTRL_SHIFT_4 (0x2 << 6)
705#define ISPCTRL_SHIFT_MASK (0x3 << 6)
706
707#define ISPCTRL_CCDC_CLK_EN (1 << 8)
708#define ISPCTRL_SCMP_CLK_EN (1 << 9)
709#define ISPCTRL_H3A_CLK_EN (1 << 10)
710#define ISPCTRL_HIST_CLK_EN (1 << 11)
711#define ISPCTRL_PREV_CLK_EN (1 << 12)
712#define ISPCTRL_RSZ_CLK_EN (1 << 13)
713#define ISPCTRL_SYNC_DETECT_SHIFT 14
714#define ISPCTRL_SYNC_DETECT_HSFALL (0x0 << ISPCTRL_SYNC_DETECT_SHIFT)
715#define ISPCTRL_SYNC_DETECT_HSRISE (0x1 << ISPCTRL_SYNC_DETECT_SHIFT)
716#define ISPCTRL_SYNC_DETECT_VSFALL (0x2 << ISPCTRL_SYNC_DETECT_SHIFT)
717#define ISPCTRL_SYNC_DETECT_VSRISE (0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
718#define ISPCTRL_SYNC_DETECT_MASK (0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
719
720#define ISPCTRL_CCDC_RAM_EN (1 << 16)
721#define ISPCTRL_PREV_RAM_EN (1 << 17)
722#define ISPCTRL_SBL_RD_RAM_EN (1 << 18)
723#define ISPCTRL_SBL_WR1_RAM_EN (1 << 19)
724#define ISPCTRL_SBL_WR0_RAM_EN (1 << 20)
725#define ISPCTRL_SBL_AUTOIDLE (1 << 21)
726#define ISPCTRL_SBL_SHARED_WPORTC (1 << 26)
727#define ISPCTRL_SBL_SHARED_RPORTA (1 << 27)
728#define ISPCTRL_SBL_SHARED_RPORTB (1 << 28)
729#define ISPCTRL_JPEG_FLUSH (1 << 30)
730#define ISPCTRL_CCDC_FLUSH (1 << 31)
731
732#define ISPSECURE_SECUREMODE 0
733
734#define ISPTCTRL_CTRL_DIV_LOW 0x0
735#define ISPTCTRL_CTRL_DIV_HIGH 0x1
736#define ISPTCTRL_CTRL_DIV_BYPASS 0x1F
737
738#define ISPTCTRL_CTRL_DIVA_SHIFT 0
739#define ISPTCTRL_CTRL_DIVA_MASK (0x1F << ISPTCTRL_CTRL_DIVA_SHIFT)
740
741#define ISPTCTRL_CTRL_DIVB_SHIFT 5
742#define ISPTCTRL_CTRL_DIVB_MASK (0x1F << ISPTCTRL_CTRL_DIVB_SHIFT)
743
744#define ISPTCTRL_CTRL_DIVC_SHIFT 10
745#define ISPTCTRL_CTRL_DIVC_NOCLOCK (0x0 << 10)
746
747#define ISPTCTRL_CTRL_SHUTEN (1 << 21)
748#define ISPTCTRL_CTRL_PSTRBEN (1 << 22)
749#define ISPTCTRL_CTRL_STRBEN (1 << 23)
750#define ISPTCTRL_CTRL_SHUTPOL (1 << 24)
751#define ISPTCTRL_CTRL_STRBPSTRBPOL (1 << 26)
752
753#define ISPTCTRL_CTRL_INSEL_SHIFT 27
754#define ISPTCTRL_CTRL_INSEL_PARALLEL (0x0 << 27)
755#define ISPTCTRL_CTRL_INSEL_CSIA (0x1 << 27)
756#define ISPTCTRL_CTRL_INSEL_CSIB (0x2 << 27)
757
758#define ISPTCTRL_CTRL_GRESETEn (1 << 29)
759#define ISPTCTRL_CTRL_GRESETPOL (1 << 30)
760#define ISPTCTRL_CTRL_GRESETDIR (1 << 31)
761
762#define ISPTCTRL_FRAME_SHUT_SHIFT 0
763#define ISPTCTRL_FRAME_PSTRB_SHIFT 6
764#define ISPTCTRL_FRAME_STRB_SHIFT 12
765
766#define ISPCCDC_PID_PREV_SHIFT 0
767#define ISPCCDC_PID_CID_SHIFT 8
768#define ISPCCDC_PID_TID_SHIFT 16
769
770#define ISPCCDC_PCR_EN 1
771#define ISPCCDC_PCR_BUSY (1 << 1)
772
773#define ISPCCDC_SYN_MODE_VDHDOUT 0x1
774#define ISPCCDC_SYN_MODE_FLDOUT (1 << 1)
775#define ISPCCDC_SYN_MODE_VDPOL (1 << 2)
776#define ISPCCDC_SYN_MODE_HDPOL (1 << 3)
777#define ISPCCDC_SYN_MODE_FLDPOL (1 << 4)
778#define ISPCCDC_SYN_MODE_EXWEN (1 << 5)
779#define ISPCCDC_SYN_MODE_DATAPOL (1 << 6)
780#define ISPCCDC_SYN_MODE_FLDMODE (1 << 7)
781#define ISPCCDC_SYN_MODE_DATSIZ_MASK (0x7 << 8)
782#define ISPCCDC_SYN_MODE_DATSIZ_8_16 (0x0 << 8)
783#define ISPCCDC_SYN_MODE_DATSIZ_12 (0x4 << 8)
784#define ISPCCDC_SYN_MODE_DATSIZ_11 (0x5 << 8)
785#define ISPCCDC_SYN_MODE_DATSIZ_10 (0x6 << 8)
786#define ISPCCDC_SYN_MODE_DATSIZ_8 (0x7 << 8)
787#define ISPCCDC_SYN_MODE_PACK8 (1 << 11)
788#define ISPCCDC_SYN_MODE_INPMOD_MASK (3 << 12)
789#define ISPCCDC_SYN_MODE_INPMOD_RAW (0 << 12)
790#define ISPCCDC_SYN_MODE_INPMOD_YCBCR16 (1 << 12)
791#define ISPCCDC_SYN_MODE_INPMOD_YCBCR8 (2 << 12)
792#define ISPCCDC_SYN_MODE_LPF (1 << 14)
793#define ISPCCDC_SYN_MODE_FLDSTAT (1 << 15)
794#define ISPCCDC_SYN_MODE_VDHDEN (1 << 16)
795#define ISPCCDC_SYN_MODE_WEN (1 << 17)
796#define ISPCCDC_SYN_MODE_VP2SDR (1 << 18)
797#define ISPCCDC_SYN_MODE_SDR2RSZ (1 << 19)
798
799#define ISPCCDC_HD_VD_WID_VDW_SHIFT 0
800#define ISPCCDC_HD_VD_WID_HDW_SHIFT 16
801
802#define ISPCCDC_PIX_LINES_HLPRF_SHIFT 0
803#define ISPCCDC_PIX_LINES_PPLN_SHIFT 16
804
805#define ISPCCDC_HORZ_INFO_NPH_SHIFT 0
806#define ISPCCDC_HORZ_INFO_NPH_MASK 0x00007fff
807#define ISPCCDC_HORZ_INFO_SPH_SHIFT 16
808#define ISPCCDC_HORZ_INFO_SPH_MASK 0x7fff0000
809
810#define ISPCCDC_VERT_START_SLV1_SHIFT 0
811#define ISPCCDC_VERT_START_SLV0_SHIFT 16
812#define ISPCCDC_VERT_START_SLV0_MASK 0x7fff0000
813
814#define ISPCCDC_VERT_LINES_NLV_SHIFT 0
815#define ISPCCDC_VERT_LINES_NLV_MASK 0x00007fff
816
817#define ISPCCDC_CULLING_CULV_SHIFT 0
818#define ISPCCDC_CULLING_CULHODD_SHIFT 16
819#define ISPCCDC_CULLING_CULHEVN_SHIFT 24
820
821#define ISPCCDC_HSIZE_OFF_SHIFT 0
822
823#define ISPCCDC_SDOFST_FINV (1 << 14)
824#define ISPCCDC_SDOFST_FOFST_1L 0
825#define ISPCCDC_SDOFST_FOFST_4L (3 << 12)
826#define ISPCCDC_SDOFST_LOFST3_SHIFT 0
827#define ISPCCDC_SDOFST_LOFST2_SHIFT 3
828#define ISPCCDC_SDOFST_LOFST1_SHIFT 6
829#define ISPCCDC_SDOFST_LOFST0_SHIFT 9
830#define EVENEVEN 1
831#define ODDEVEN 2
832#define EVENODD 3
833#define ODDODD 4
834
835#define ISPCCDC_CLAMP_OBGAIN_SHIFT 0
836#define ISPCCDC_CLAMP_OBST_SHIFT 10
837#define ISPCCDC_CLAMP_OBSLN_SHIFT 25
838#define ISPCCDC_CLAMP_OBSLEN_SHIFT 28
839#define ISPCCDC_CLAMP_CLAMPEN (1 << 31)
840
841#define ISPCCDC_COLPTN_R_Ye 0x0
842#define ISPCCDC_COLPTN_Gr_Cy 0x1
843#define ISPCCDC_COLPTN_Gb_G 0x2
844#define ISPCCDC_COLPTN_B_Mg 0x3
845#define ISPCCDC_COLPTN_CP0PLC0_SHIFT 0
846#define ISPCCDC_COLPTN_CP0PLC1_SHIFT 2
847#define ISPCCDC_COLPTN_CP0PLC2_SHIFT 4
848#define ISPCCDC_COLPTN_CP0PLC3_SHIFT 6
849#define ISPCCDC_COLPTN_CP1PLC0_SHIFT 8
850#define ISPCCDC_COLPTN_CP1PLC1_SHIFT 10
851#define ISPCCDC_COLPTN_CP1PLC2_SHIFT 12
852#define ISPCCDC_COLPTN_CP1PLC3_SHIFT 14
853#define ISPCCDC_COLPTN_CP2PLC0_SHIFT 16
854#define ISPCCDC_COLPTN_CP2PLC1_SHIFT 18
855#define ISPCCDC_COLPTN_CP2PLC2_SHIFT 20
856#define ISPCCDC_COLPTN_CP2PLC3_SHIFT 22
857#define ISPCCDC_COLPTN_CP3PLC0_SHIFT 24
858#define ISPCCDC_COLPTN_CP3PLC1_SHIFT 26
859#define ISPCCDC_COLPTN_CP3PLC2_SHIFT 28
860#define ISPCCDC_COLPTN_CP3PLC3_SHIFT 30
861
862#define ISPCCDC_BLKCMP_B_MG_SHIFT 0
863#define ISPCCDC_BLKCMP_GB_G_SHIFT 8
864#define ISPCCDC_BLKCMP_GR_CY_SHIFT 16
865#define ISPCCDC_BLKCMP_R_YE_SHIFT 24
866
867#define ISPCCDC_FPC_FPNUM_SHIFT 0
868#define ISPCCDC_FPC_FPCEN (1 << 15)
869#define ISPCCDC_FPC_FPERR (1 << 16)
870
871#define ISPCCDC_VDINT_1_SHIFT 0
872#define ISPCCDC_VDINT_1_MASK 0x00007fff
873#define ISPCCDC_VDINT_0_SHIFT 16
874#define ISPCCDC_VDINT_0_MASK 0x7fff0000
875
876#define ISPCCDC_ALAW_GWDI_12_3 (0x3 << 0)
877#define ISPCCDC_ALAW_GWDI_11_2 (0x4 << 0)
878#define ISPCCDC_ALAW_GWDI_10_1 (0x5 << 0)
879#define ISPCCDC_ALAW_GWDI_9_0 (0x6 << 0)
880#define ISPCCDC_ALAW_CCDTBL (1 << 3)
881
882#define ISPCCDC_REC656IF_R656ON 1
883#define ISPCCDC_REC656IF_ECCFVH (1 << 1)
884
885#define ISPCCDC_CFG_BW656 (1 << 5)
886#define ISPCCDC_CFG_FIDMD_SHIFT 6
887#define ISPCCDC_CFG_WENLOG (1 << 8)
888#define ISPCCDC_CFG_WENLOG_AND (0 << 8)
889#define ISPCCDC_CFG_WENLOG_OR (1 << 8)
890#define ISPCCDC_CFG_Y8POS (1 << 11)
891#define ISPCCDC_CFG_BSWD (1 << 12)
892#define ISPCCDC_CFG_MSBINVI (1 << 13)
893#define ISPCCDC_CFG_VDLC (1 << 15)
894
895#define ISPCCDC_FMTCFG_FMTEN 0x1
896#define ISPCCDC_FMTCFG_LNALT (1 << 1)
897#define ISPCCDC_FMTCFG_LNUM_SHIFT 2
898#define ISPCCDC_FMTCFG_PLEN_ODD_SHIFT 4
899#define ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT 8
900#define ISPCCDC_FMTCFG_VPIN_MASK 0x00007000
901#define ISPCCDC_FMTCFG_VPIN_12_3 (0x3 << 12)
902#define ISPCCDC_FMTCFG_VPIN_11_2 (0x4 << 12)
903#define ISPCCDC_FMTCFG_VPIN_10_1 (0x5 << 12)
904#define ISPCCDC_FMTCFG_VPIN_9_0 (0x6 << 12)
905#define ISPCCDC_FMTCFG_VPEN (1 << 15)
906
907#define ISPCCDC_FMTCFG_VPIF_FRQ_MASK 0x003f0000
908#define ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT 16
909#define ISPCCDC_FMTCFG_VPIF_FRQ_BY2 (0x0 << 16)
910#define ISPCCDC_FMTCFG_VPIF_FRQ_BY3 (0x1 << 16)
911#define ISPCCDC_FMTCFG_VPIF_FRQ_BY4 (0x2 << 16)
912#define ISPCCDC_FMTCFG_VPIF_FRQ_BY5 (0x3 << 16)
913#define ISPCCDC_FMTCFG_VPIF_FRQ_BY6 (0x4 << 16)
914
915#define ISPCCDC_FMT_HORZ_FMTLNH_SHIFT 0
916#define ISPCCDC_FMT_HORZ_FMTSPH_SHIFT 16
917
918#define ISPCCDC_FMT_VERT_FMTLNV_SHIFT 0
919#define ISPCCDC_FMT_VERT_FMTSLV_SHIFT 16
920
921#define ISPCCDC_FMT_HORZ_FMTSPH_MASK 0x1fff0000
922#define ISPCCDC_FMT_HORZ_FMTLNH_MASK 0x00001fff
923
924#define ISPCCDC_FMT_VERT_FMTSLV_MASK 0x1fff0000
925#define ISPCCDC_FMT_VERT_FMTLNV_MASK 0x00001fff
926
927#define ISPCCDC_VP_OUT_HORZ_ST_SHIFT 0
928#define ISPCCDC_VP_OUT_HORZ_NUM_SHIFT 4
929#define ISPCCDC_VP_OUT_VERT_NUM_SHIFT 17
930
931#define ISPRSZ_PID_PREV_SHIFT 0
932#define ISPRSZ_PID_CID_SHIFT 8
933#define ISPRSZ_PID_TID_SHIFT 16
934
935#define ISPRSZ_PCR_ENABLE (1 << 0)
936#define ISPRSZ_PCR_BUSY (1 << 1)
937#define ISPRSZ_PCR_ONESHOT (1 << 2)
938
939#define ISPRSZ_CNT_HRSZ_SHIFT 0
940#define ISPRSZ_CNT_HRSZ_MASK \
941 (0x3FF << ISPRSZ_CNT_HRSZ_SHIFT)
942#define ISPRSZ_CNT_VRSZ_SHIFT 10
943#define ISPRSZ_CNT_VRSZ_MASK \
944 (0x3FF << ISPRSZ_CNT_VRSZ_SHIFT)
945#define ISPRSZ_CNT_HSTPH_SHIFT 20
946#define ISPRSZ_CNT_HSTPH_MASK (0x7 << ISPRSZ_CNT_HSTPH_SHIFT)
947#define ISPRSZ_CNT_VSTPH_SHIFT 23
948#define ISPRSZ_CNT_VSTPH_MASK (0x7 << ISPRSZ_CNT_VSTPH_SHIFT)
949#define ISPRSZ_CNT_YCPOS (1 << 26)
950#define ISPRSZ_CNT_INPTYP (1 << 27)
951#define ISPRSZ_CNT_INPSRC (1 << 28)
952#define ISPRSZ_CNT_CBILIN (1 << 29)
953
954#define ISPRSZ_OUT_SIZE_HORZ_SHIFT 0
955#define ISPRSZ_OUT_SIZE_HORZ_MASK \
956 (0xFFF << ISPRSZ_OUT_SIZE_HORZ_SHIFT)
957#define ISPRSZ_OUT_SIZE_VERT_SHIFT 16
958#define ISPRSZ_OUT_SIZE_VERT_MASK \
959 (0xFFF << ISPRSZ_OUT_SIZE_VERT_SHIFT)
960
961#define ISPRSZ_IN_START_HORZ_ST_SHIFT 0
962#define ISPRSZ_IN_START_HORZ_ST_MASK \
963 (0x1FFF << ISPRSZ_IN_START_HORZ_ST_SHIFT)
964#define ISPRSZ_IN_START_VERT_ST_SHIFT 16
965#define ISPRSZ_IN_START_VERT_ST_MASK \
966 (0x1FFF << ISPRSZ_IN_START_VERT_ST_SHIFT)
967
968#define ISPRSZ_IN_SIZE_HORZ_SHIFT 0
969#define ISPRSZ_IN_SIZE_HORZ_MASK \
970 (0x1FFF << ISPRSZ_IN_SIZE_HORZ_SHIFT)
971#define ISPRSZ_IN_SIZE_VERT_SHIFT 16
972#define ISPRSZ_IN_SIZE_VERT_MASK \
973 (0x1FFF << ISPRSZ_IN_SIZE_VERT_SHIFT)
974
975#define ISPRSZ_SDR_INADD_ADDR_SHIFT 0
976#define ISPRSZ_SDR_INADD_ADDR_MASK 0xFFFFFFFF
977
978#define ISPRSZ_SDR_INOFF_OFFSET_SHIFT 0
979#define ISPRSZ_SDR_INOFF_OFFSET_MASK \
980 (0xFFFF << ISPRSZ_SDR_INOFF_OFFSET_SHIFT)
981
982#define ISPRSZ_SDR_OUTADD_ADDR_SHIFT 0
983#define ISPRSZ_SDR_OUTADD_ADDR_MASK 0xFFFFFFFF
984
985
986#define ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT 0
987#define ISPRSZ_SDR_OUTOFF_OFFSET_MASK \
988 (0xFFFF << ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT)
989
990#define ISPRSZ_HFILT_COEF0_SHIFT 0
991#define ISPRSZ_HFILT_COEF0_MASK \
992 (0x3FF << ISPRSZ_HFILT_COEF0_SHIFT)
993#define ISPRSZ_HFILT_COEF1_SHIFT 16
994#define ISPRSZ_HFILT_COEF1_MASK \
995 (0x3FF << ISPRSZ_HFILT_COEF1_SHIFT)
996
997#define ISPRSZ_HFILT32_COEF2_SHIFT 0
998#define ISPRSZ_HFILT32_COEF2_MASK 0x3FF
999#define ISPRSZ_HFILT32_COEF3_SHIFT 16
1000#define ISPRSZ_HFILT32_COEF3_MASK 0x3FF0000
1001
1002#define ISPRSZ_HFILT54_COEF4_SHIFT 0
1003#define ISPRSZ_HFILT54_COEF4_MASK 0x3FF
1004#define ISPRSZ_HFILT54_COEF5_SHIFT 16
1005#define ISPRSZ_HFILT54_COEF5_MASK 0x3FF0000
1006
1007#define ISPRSZ_HFILT76_COEFF6_SHIFT 0
1008#define ISPRSZ_HFILT76_COEFF6_MASK 0x3FF
1009#define ISPRSZ_HFILT76_COEFF7_SHIFT 16
1010#define ISPRSZ_HFILT76_COEFF7_MASK 0x3FF0000
1011
1012#define ISPRSZ_HFILT98_COEFF8_SHIFT 0
1013#define ISPRSZ_HFILT98_COEFF8_MASK 0x3FF
1014#define ISPRSZ_HFILT98_COEFF9_SHIFT 16
1015#define ISPRSZ_HFILT98_COEFF9_MASK 0x3FF0000
1016
1017#define ISPRSZ_HFILT1110_COEF10_SHIFT 0
1018#define ISPRSZ_HFILT1110_COEF10_MASK 0x3FF
1019#define ISPRSZ_HFILT1110_COEF11_SHIFT 16
1020#define ISPRSZ_HFILT1110_COEF11_MASK 0x3FF0000
1021
1022#define ISPRSZ_HFILT1312_COEFF12_SHIFT 0
1023#define ISPRSZ_HFILT1312_COEFF12_MASK 0x3FF
1024#define ISPRSZ_HFILT1312_COEFF13_SHIFT 16
1025#define ISPRSZ_HFILT1312_COEFF13_MASK 0x3FF0000
1026
1027#define ISPRSZ_HFILT1514_COEFF14_SHIFT 0
1028#define ISPRSZ_HFILT1514_COEFF14_MASK 0x3FF
1029#define ISPRSZ_HFILT1514_COEFF15_SHIFT 16
1030#define ISPRSZ_HFILT1514_COEFF15_MASK 0x3FF0000
1031
1032#define ISPRSZ_HFILT1716_COEF16_SHIFT 0
1033#define ISPRSZ_HFILT1716_COEF16_MASK 0x3FF
1034#define ISPRSZ_HFILT1716_COEF17_SHIFT 16
1035#define ISPRSZ_HFILT1716_COEF17_MASK 0x3FF0000
1036
1037#define ISPRSZ_HFILT1918_COEF18_SHIFT 0
1038#define ISPRSZ_HFILT1918_COEF18_MASK 0x3FF
1039#define ISPRSZ_HFILT1918_COEF19_SHIFT 16
1040#define ISPRSZ_HFILT1918_COEF19_MASK 0x3FF0000
1041
1042#define ISPRSZ_HFILT2120_COEF20_SHIFT 0
1043#define ISPRSZ_HFILT2120_COEF20_MASK 0x3FF
1044#define ISPRSZ_HFILT2120_COEF21_SHIFT 16
1045#define ISPRSZ_HFILT2120_COEF21_MASK 0x3FF0000
1046
1047#define ISPRSZ_HFILT2322_COEF22_SHIFT 0
1048#define ISPRSZ_HFILT2322_COEF22_MASK 0x3FF
1049#define ISPRSZ_HFILT2322_COEF23_SHIFT 16
1050#define ISPRSZ_HFILT2322_COEF23_MASK 0x3FF0000
1051
1052#define ISPRSZ_HFILT2524_COEF24_SHIFT 0
1053#define ISPRSZ_HFILT2524_COEF24_MASK 0x3FF
1054#define ISPRSZ_HFILT2524_COEF25_SHIFT 16
1055#define ISPRSZ_HFILT2524_COEF25_MASK 0x3FF0000
1056
1057#define ISPRSZ_HFILT2726_COEF26_SHIFT 0
1058#define ISPRSZ_HFILT2726_COEF26_MASK 0x3FF
1059#define ISPRSZ_HFILT2726_COEF27_SHIFT 16
1060#define ISPRSZ_HFILT2726_COEF27_MASK 0x3FF0000
1061
1062#define ISPRSZ_HFILT2928_COEF28_SHIFT 0
1063#define ISPRSZ_HFILT2928_COEF28_MASK 0x3FF
1064#define ISPRSZ_HFILT2928_COEF29_SHIFT 16
1065#define ISPRSZ_HFILT2928_COEF29_MASK 0x3FF0000
1066
1067#define ISPRSZ_HFILT3130_COEF30_SHIFT 0
1068#define ISPRSZ_HFILT3130_COEF30_MASK 0x3FF
1069#define ISPRSZ_HFILT3130_COEF31_SHIFT 16
1070#define ISPRSZ_HFILT3130_COEF31_MASK 0x3FF0000
1071
1072#define ISPRSZ_VFILT_COEF0_SHIFT 0
1073#define ISPRSZ_VFILT_COEF0_MASK \
1074 (0x3FF << ISPRSZ_VFILT_COEF0_SHIFT)
1075#define ISPRSZ_VFILT_COEF1_SHIFT 16
1076#define ISPRSZ_VFILT_COEF1_MASK \
1077 (0x3FF << ISPRSZ_VFILT_COEF1_SHIFT)
1078
1079#define ISPRSZ_VFILT10_COEF0_SHIFT 0
1080#define ISPRSZ_VFILT10_COEF0_MASK 0x3FF
1081#define ISPRSZ_VFILT10_COEF1_SHIFT 16
1082#define ISPRSZ_VFILT10_COEF1_MASK 0x3FF0000
1083
1084#define ISPRSZ_VFILT32_COEF2_SHIFT 0
1085#define ISPRSZ_VFILT32_COEF2_MASK 0x3FF
1086#define ISPRSZ_VFILT32_COEF3_SHIFT 16
1087#define ISPRSZ_VFILT32_COEF3_MASK 0x3FF0000
1088
1089#define ISPRSZ_VFILT54_COEF4_SHIFT 0
1090#define ISPRSZ_VFILT54_COEF4_MASK 0x3FF
1091#define ISPRSZ_VFILT54_COEF5_SHIFT 16
1092#define ISPRSZ_VFILT54_COEF5_MASK 0x3FF0000
1093
1094#define ISPRSZ_VFILT76_COEFF6_SHIFT 0
1095#define ISPRSZ_VFILT76_COEFF6_MASK 0x3FF
1096#define ISPRSZ_VFILT76_COEFF7_SHIFT 16
1097#define ISPRSZ_VFILT76_COEFF7_MASK 0x3FF0000
1098
1099#define ISPRSZ_VFILT98_COEFF8_SHIFT 0
1100#define ISPRSZ_VFILT98_COEFF8_MASK 0x3FF
1101#define ISPRSZ_VFILT98_COEFF9_SHIFT 16
1102#define ISPRSZ_VFILT98_COEFF9_MASK 0x3FF0000
1103
1104#define ISPRSZ_VFILT1110_COEF10_SHIFT 0
1105#define ISPRSZ_VFILT1110_COEF10_MASK 0x3FF
1106#define ISPRSZ_VFILT1110_COEF11_SHIFT 16
1107#define ISPRSZ_VFILT1110_COEF11_MASK 0x3FF0000
1108
1109#define ISPRSZ_VFILT1312_COEFF12_SHIFT 0
1110#define ISPRSZ_VFILT1312_COEFF12_MASK 0x3FF
1111#define ISPRSZ_VFILT1312_COEFF13_SHIFT 16
1112#define ISPRSZ_VFILT1312_COEFF13_MASK 0x3FF0000
1113
1114#define ISPRSZ_VFILT1514_COEFF14_SHIFT 0
1115#define ISPRSZ_VFILT1514_COEFF14_MASK 0x3FF
1116#define ISPRSZ_VFILT1514_COEFF15_SHIFT 16
1117#define ISPRSZ_VFILT1514_COEFF15_MASK 0x3FF0000
1118
1119#define ISPRSZ_VFILT1716_COEF16_SHIFT 0
1120#define ISPRSZ_VFILT1716_COEF16_MASK 0x3FF
1121#define ISPRSZ_VFILT1716_COEF17_SHIFT 16
1122#define ISPRSZ_VFILT1716_COEF17_MASK 0x3FF0000
1123
1124#define ISPRSZ_VFILT1918_COEF18_SHIFT 0
1125#define ISPRSZ_VFILT1918_COEF18_MASK 0x3FF
1126#define ISPRSZ_VFILT1918_COEF19_SHIFT 16
1127#define ISPRSZ_VFILT1918_COEF19_MASK 0x3FF0000
1128
1129#define ISPRSZ_VFILT2120_COEF20_SHIFT 0
1130#define ISPRSZ_VFILT2120_COEF20_MASK 0x3FF
1131#define ISPRSZ_VFILT2120_COEF21_SHIFT 16
1132#define ISPRSZ_VFILT2120_COEF21_MASK 0x3FF0000
1133
1134#define ISPRSZ_VFILT2322_COEF22_SHIFT 0
1135#define ISPRSZ_VFILT2322_COEF22_MASK 0x3FF
1136#define ISPRSZ_VFILT2322_COEF23_SHIFT 16
1137#define ISPRSZ_VFILT2322_COEF23_MASK 0x3FF0000
1138
1139#define ISPRSZ_VFILT2524_COEF24_SHIFT 0
1140#define ISPRSZ_VFILT2524_COEF24_MASK 0x3FF
1141#define ISPRSZ_VFILT2524_COEF25_SHIFT 16
1142#define ISPRSZ_VFILT2524_COEF25_MASK 0x3FF0000
1143
1144#define ISPRSZ_VFILT2726_COEF26_SHIFT 0
1145#define ISPRSZ_VFILT2726_COEF26_MASK 0x3FF
1146#define ISPRSZ_VFILT2726_COEF27_SHIFT 16
1147#define ISPRSZ_VFILT2726_COEF27_MASK 0x3FF0000
1148
1149#define ISPRSZ_VFILT2928_COEF28_SHIFT 0
1150#define ISPRSZ_VFILT2928_COEF28_MASK 0x3FF
1151#define ISPRSZ_VFILT2928_COEF29_SHIFT 16
1152#define ISPRSZ_VFILT2928_COEF29_MASK 0x3FF0000
1153
1154#define ISPRSZ_VFILT3130_COEF30_SHIFT 0
1155#define ISPRSZ_VFILT3130_COEF30_MASK 0x3FF
1156#define ISPRSZ_VFILT3130_COEF31_SHIFT 16
1157#define ISPRSZ_VFILT3130_COEF31_MASK 0x3FF0000
1158
1159#define ISPRSZ_YENH_CORE_SHIFT 0
1160#define ISPRSZ_YENH_CORE_MASK \
1161 (0xFF << ISPRSZ_YENH_CORE_SHIFT)
1162#define ISPRSZ_YENH_SLOP_SHIFT 8
1163#define ISPRSZ_YENH_SLOP_MASK \
1164 (0xF << ISPRSZ_YENH_SLOP_SHIFT)
1165#define ISPRSZ_YENH_GAIN_SHIFT 12
1166#define ISPRSZ_YENH_GAIN_MASK \
1167 (0xF << ISPRSZ_YENH_GAIN_SHIFT)
1168#define ISPRSZ_YENH_ALGO_SHIFT 16
1169#define ISPRSZ_YENH_ALGO_MASK \
1170 (0x3 << ISPRSZ_YENH_ALGO_SHIFT)
1171
1172#define ISPH3A_PCR_AEW_ALAW_EN_SHIFT 1
1173#define ISPH3A_PCR_AF_MED_TH_SHIFT 3
1174#define ISPH3A_PCR_AF_RGBPOS_SHIFT 11
1175#define ISPH3A_PCR_AEW_AVE2LMT_SHIFT 22
1176#define ISPH3A_PCR_AEW_AVE2LMT_MASK 0xFFC00000
1177#define ISPH3A_PCR_BUSYAF (1 << 15)
1178#define ISPH3A_PCR_BUSYAEAWB (1 << 18)
1179
1180#define ISPH3A_AEWWIN1_WINHC_SHIFT 0
1181#define ISPH3A_AEWWIN1_WINHC_MASK 0x3F
1182#define ISPH3A_AEWWIN1_WINVC_SHIFT 6
1183#define ISPH3A_AEWWIN1_WINVC_MASK 0x1FC0
1184#define ISPH3A_AEWWIN1_WINW_SHIFT 13
1185#define ISPH3A_AEWWIN1_WINW_MASK 0xFE000
1186#define ISPH3A_AEWWIN1_WINH_SHIFT 24
1187#define ISPH3A_AEWWIN1_WINH_MASK 0x7F000000
1188
1189#define ISPH3A_AEWINSTART_WINSH_SHIFT 0
1190#define ISPH3A_AEWINSTART_WINSH_MASK 0x0FFF
1191#define ISPH3A_AEWINSTART_WINSV_SHIFT 16
1192#define ISPH3A_AEWINSTART_WINSV_MASK 0x0FFF0000
1193
1194#define ISPH3A_AEWINBLK_WINH_SHIFT 0
1195#define ISPH3A_AEWINBLK_WINH_MASK 0x7F
1196#define ISPH3A_AEWINBLK_WINSV_SHIFT 16
1197#define ISPH3A_AEWINBLK_WINSV_MASK 0x0FFF0000
1198
1199#define ISPH3A_AEWSUBWIN_AEWINCH_SHIFT 0
1200#define ISPH3A_AEWSUBWIN_AEWINCH_MASK 0x0F
1201#define ISPH3A_AEWSUBWIN_AEWINCV_SHIFT 8
1202#define ISPH3A_AEWSUBWIN_AEWINCV_MASK 0x0F00
1203
1204#define ISPHIST_PCR_ENABLE_SHIFT 0
1205#define ISPHIST_PCR_ENABLE_MASK 0x01
1206#define ISPHIST_PCR_ENABLE (1 << ISPHIST_PCR_ENABLE_SHIFT)
1207#define ISPHIST_PCR_BUSY 0x02
1208
1209#define ISPHIST_CNT_DATASIZE_SHIFT 8
1210#define ISPHIST_CNT_DATASIZE_MASK 0x0100
1211#define ISPHIST_CNT_CLEAR_SHIFT 7
1212#define ISPHIST_CNT_CLEAR_MASK 0x080
1213#define ISPHIST_CNT_CLEAR (1 << ISPHIST_CNT_CLEAR_SHIFT)
1214#define ISPHIST_CNT_CFA_SHIFT 6
1215#define ISPHIST_CNT_CFA_MASK 0x040
1216#define ISPHIST_CNT_BINS_SHIFT 4
1217#define ISPHIST_CNT_BINS_MASK 0x030
1218#define ISPHIST_CNT_SOURCE_SHIFT 3
1219#define ISPHIST_CNT_SOURCE_MASK 0x08
1220#define ISPHIST_CNT_SHIFT_SHIFT 0
1221#define ISPHIST_CNT_SHIFT_MASK 0x07
1222
1223#define ISPHIST_WB_GAIN_WG00_SHIFT 24
1224#define ISPHIST_WB_GAIN_WG00_MASK 0xFF000000
1225#define ISPHIST_WB_GAIN_WG01_SHIFT 16
1226#define ISPHIST_WB_GAIN_WG01_MASK 0xFF0000
1227#define ISPHIST_WB_GAIN_WG02_SHIFT 8
1228#define ISPHIST_WB_GAIN_WG02_MASK 0xFF00
1229#define ISPHIST_WB_GAIN_WG03_SHIFT 0
1230#define ISPHIST_WB_GAIN_WG03_MASK 0xFF
1231
1232#define ISPHIST_REG_START_END_MASK 0x3FFF
1233#define ISPHIST_REG_START_SHIFT 16
1234#define ISPHIST_REG_END_SHIFT 0
1235#define ISPHIST_REG_START_MASK (ISPHIST_REG_START_END_MASK << \
1236 ISPHIST_REG_START_SHIFT)
1237#define ISPHIST_REG_END_MASK (ISPHIST_REG_START_END_MASK << \
1238 ISPHIST_REG_END_SHIFT)
1239
1240#define ISPHIST_REG_MASK (ISPHIST_REG_START_MASK | \
1241 ISPHIST_REG_END_MASK)
1242
1243#define ISPHIST_ADDR_SHIFT 0
1244#define ISPHIST_ADDR_MASK 0x3FF
1245
1246#define ISPHIST_DATA_SHIFT 0
1247#define ISPHIST_DATA_MASK 0xFFFFF
1248
1249#define ISPHIST_RADD_SHIFT 0
1250#define ISPHIST_RADD_MASK 0xFFFFFFFF
1251
1252#define ISPHIST_RADD_OFF_SHIFT 0
1253#define ISPHIST_RADD_OFF_MASK 0xFFFF
1254
1255#define ISPHIST_HV_INFO_HSIZE_SHIFT 16
1256#define ISPHIST_HV_INFO_HSIZE_MASK 0x3FFF0000
1257#define ISPHIST_HV_INFO_VSIZE_SHIFT 0
1258#define ISPHIST_HV_INFO_VSIZE_MASK 0x3FFF
1259
1260#define ISPHIST_HV_INFO_MASK 0x3FFF3FFF
1261
1262#define ISPCCDC_LSC_ENABLE 1
1263#define ISPCCDC_LSC_BUSY (1 << 7)
1264#define ISPCCDC_LSC_GAIN_MODE_N_MASK 0x700
1265#define ISPCCDC_LSC_GAIN_MODE_N_SHIFT 8
1266#define ISPCCDC_LSC_GAIN_MODE_M_MASK 0x3800
1267#define ISPCCDC_LSC_GAIN_MODE_M_SHIFT 12
1268#define ISPCCDC_LSC_GAIN_FORMAT_MASK 0xE
1269#define ISPCCDC_LSC_GAIN_FORMAT_SHIFT 1
1270#define ISPCCDC_LSC_AFTER_REFORMATTER_MASK (1<<6)
1271
1272#define ISPCCDC_LSC_INITIAL_X_MASK 0x3F
1273#define ISPCCDC_LSC_INITIAL_X_SHIFT 0
1274#define ISPCCDC_LSC_INITIAL_Y_MASK 0x3F0000
1275#define ISPCCDC_LSC_INITIAL_Y_SHIFT 16
1276
1277/* -----------------------------------------------------------------------------
1278 * CSI2 receiver registers (ES2.0)
1279 */
1280
1281#define ISPCSI2_REVISION (0x000)
1282#define ISPCSI2_SYSCONFIG (0x010)
1283#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT 12
1284#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK \
1285 (0x3 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
1286#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_FORCE \
1287 (0x0 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
1288#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO \
1289 (0x1 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
1290#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART \
1291 (0x2 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
1292#define ISPCSI2_SYSCONFIG_SOFT_RESET (1 << 1)
1293#define ISPCSI2_SYSCONFIG_AUTO_IDLE (1 << 0)
1294
1295#define ISPCSI2_SYSSTATUS (0x014)
1296#define ISPCSI2_SYSSTATUS_RESET_DONE (1 << 0)
1297
1298#define ISPCSI2_IRQSTATUS (0x018)
1299#define ISPCSI2_IRQSTATUS_OCP_ERR_IRQ (1 << 14)
1300#define ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ (1 << 13)
1301#define ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ (1 << 12)
1302#define ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ (1 << 11)
1303#define ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ (1 << 10)
1304#define ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ (1 << 9)
1305#define ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ (1 << 8)
1306#define ISPCSI2_IRQSTATUS_CONTEXT(n) (1 << (n))
1307
1308#define ISPCSI2_IRQENABLE (0x01c)
1309#define ISPCSI2_CTRL (0x040)
1310#define ISPCSI2_CTRL_VP_CLK_EN (1 << 15)
1311#define ISPCSI2_CTRL_VP_ONLY_EN (1 << 11)
1312#define ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT 8
1313#define ISPCSI2_CTRL_VP_OUT_CTRL_MASK \
1314 (3 << ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
1315#define ISPCSI2_CTRL_DBG_EN (1 << 7)
1316#define ISPCSI2_CTRL_BURST_SIZE_SHIFT 5
1317#define ISPCSI2_CTRL_BURST_SIZE_MASK \
1318 (3 << ISPCSI2_CTRL_BURST_SIZE_SHIFT)
1319#define ISPCSI2_CTRL_FRAME (1 << 3)
1320#define ISPCSI2_CTRL_ECC_EN (1 << 2)
1321#define ISPCSI2_CTRL_SECURE (1 << 1)
1322#define ISPCSI2_CTRL_IF_EN (1 << 0)
1323
1324#define ISPCSI2_DBG_H (0x044)
1325#define ISPCSI2_GNQ (0x048)
1326#define ISPCSI2_PHY_CFG (0x050)
1327#define ISPCSI2_PHY_CFG_RESET_CTRL (1 << 30)
1328#define ISPCSI2_PHY_CFG_RESET_DONE (1 << 29)
1329#define ISPCSI2_PHY_CFG_PWR_CMD_SHIFT 27
1330#define ISPCSI2_PHY_CFG_PWR_CMD_MASK \
1331 (0x3 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
1332#define ISPCSI2_PHY_CFG_PWR_CMD_OFF \
1333 (0x0 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
1334#define ISPCSI2_PHY_CFG_PWR_CMD_ON \
1335 (0x1 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
1336#define ISPCSI2_PHY_CFG_PWR_CMD_ULPW \
1337 (0x2 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
1338#define ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT 25
1339#define ISPCSI2_PHY_CFG_PWR_STATUS_MASK \
1340 (0x3 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
1341#define ISPCSI2_PHY_CFG_PWR_STATUS_OFF \
1342 (0x0 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
1343#define ISPCSI2_PHY_CFG_PWR_STATUS_ON \
1344 (0x1 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
1345#define ISPCSI2_PHY_CFG_PWR_STATUS_ULPW \
1346 (0x2 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
1347#define ISPCSI2_PHY_CFG_PWR_AUTO (1 << 24)
1348
1349#define ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n) (3 + ((n) * 4))
1350#define ISPCSI2_PHY_CFG_DATA_POL_MASK(n) \
1351 (0x1 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
1352#define ISPCSI2_PHY_CFG_DATA_POL_PN(n) \
1353 (0x0 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
1354#define ISPCSI2_PHY_CFG_DATA_POL_NP(n) \
1355 (0x1 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
1356
1357#define ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n) ((n) * 4)
1358#define ISPCSI2_PHY_CFG_DATA_POSITION_MASK(n) \
1359 (0x7 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1360#define ISPCSI2_PHY_CFG_DATA_POSITION_NC(n) \
1361 (0x0 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1362#define ISPCSI2_PHY_CFG_DATA_POSITION_1(n) \
1363 (0x1 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1364#define ISPCSI2_PHY_CFG_DATA_POSITION_2(n) \
1365 (0x2 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1366#define ISPCSI2_PHY_CFG_DATA_POSITION_3(n) \
1367 (0x3 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1368#define ISPCSI2_PHY_CFG_DATA_POSITION_4(n) \
1369 (0x4 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1370#define ISPCSI2_PHY_CFG_DATA_POSITION_5(n) \
1371 (0x5 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
1372
1373#define ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT 3
1374#define ISPCSI2_PHY_CFG_CLOCK_POL_MASK \
1375 (0x1 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
1376#define ISPCSI2_PHY_CFG_CLOCK_POL_PN \
1377 (0x0 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
1378#define ISPCSI2_PHY_CFG_CLOCK_POL_NP \
1379 (0x1 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
1380
1381#define ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT 0
1382#define ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK \
1383 (0x7 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1384#define ISPCSI2_PHY_CFG_CLOCK_POSITION_1 \
1385 (0x1 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1386#define ISPCSI2_PHY_CFG_CLOCK_POSITION_2 \
1387 (0x2 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1388#define ISPCSI2_PHY_CFG_CLOCK_POSITION_3 \
1389 (0x3 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1390#define ISPCSI2_PHY_CFG_CLOCK_POSITION_4 \
1391 (0x4 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1392#define ISPCSI2_PHY_CFG_CLOCK_POSITION_5 \
1393 (0x5 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
1394
1395#define ISPCSI2_PHY_IRQSTATUS (0x054)
1396#define ISPCSI2_PHY_IRQSTATUS_STATEALLULPMEXIT (1 << 26)
1397#define ISPCSI2_PHY_IRQSTATUS_STATEALLULPMENTER (1 << 25)
1398#define ISPCSI2_PHY_IRQSTATUS_STATEULPM5 (1 << 24)
1399#define ISPCSI2_PHY_IRQSTATUS_STATEULPM4 (1 << 23)
1400#define ISPCSI2_PHY_IRQSTATUS_STATEULPM3 (1 << 22)
1401#define ISPCSI2_PHY_IRQSTATUS_STATEULPM2 (1 << 21)
1402#define ISPCSI2_PHY_IRQSTATUS_STATEULPM1 (1 << 20)
1403#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL5 (1 << 19)
1404#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL4 (1 << 18)
1405#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL3 (1 << 17)
1406#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL2 (1 << 16)
1407#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL1 (1 << 15)
1408#define ISPCSI2_PHY_IRQSTATUS_ERRESC5 (1 << 14)
1409#define ISPCSI2_PHY_IRQSTATUS_ERRESC4 (1 << 13)
1410#define ISPCSI2_PHY_IRQSTATUS_ERRESC3 (1 << 12)
1411#define ISPCSI2_PHY_IRQSTATUS_ERRESC2 (1 << 11)
1412#define ISPCSI2_PHY_IRQSTATUS_ERRESC1 (1 << 10)
1413#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS5 (1 << 9)
1414#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS4 (1 << 8)
1415#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS3 (1 << 7)
1416#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS2 (1 << 6)
1417#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS1 (1 << 5)
1418#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS5 (1 << 4)
1419#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS4 (1 << 3)
1420#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS3 (1 << 2)
1421#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS2 (1 << 1)
1422#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS1 1
1423
1424#define ISPCSI2_SHORT_PACKET (0x05c)
1425#define ISPCSI2_PHY_IRQENABLE (0x060)
1426#define ISPCSI2_PHY_IRQENABLE_STATEALLULPMEXIT (1 << 26)
1427#define ISPCSI2_PHY_IRQENABLE_STATEALLULPMENTER (1 << 25)
1428#define ISPCSI2_PHY_IRQENABLE_STATEULPM5 (1 << 24)
1429#define ISPCSI2_PHY_IRQENABLE_STATEULPM4 (1 << 23)
1430#define ISPCSI2_PHY_IRQENABLE_STATEULPM3 (1 << 22)
1431#define ISPCSI2_PHY_IRQENABLE_STATEULPM2 (1 << 21)
1432#define ISPCSI2_PHY_IRQENABLE_STATEULPM1 (1 << 20)
1433#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL5 (1 << 19)
1434#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL4 (1 << 18)
1435#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL3 (1 << 17)
1436#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL2 (1 << 16)
1437#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL1 (1 << 15)
1438#define ISPCSI2_PHY_IRQENABLE_ERRESC5 (1 << 14)
1439#define ISPCSI2_PHY_IRQENABLE_ERRESC4 (1 << 13)
1440#define ISPCSI2_PHY_IRQENABLE_ERRESC3 (1 << 12)
1441#define ISPCSI2_PHY_IRQENABLE_ERRESC2 (1 << 11)
1442#define ISPCSI2_PHY_IRQENABLE_ERRESC1 (1 << 10)
1443#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS5 (1 << 9)
1444#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS4 (1 << 8)
1445#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS3 (1 << 7)
1446#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS2 (1 << 6)
1447#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS1 (1 << 5)
1448#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS5 (1 << 4)
1449#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS4 (1 << 3)
1450#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS3 (1 << 2)
1451#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS2 (1 << 1)
1452#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS1 (1 << 0)
1453
1454#define ISPCSI2_DBG_P (0x068)
1455#define ISPCSI2_TIMING (0x06c)
1456#define ISPCSI2_TIMING_FORCE_RX_MODE_IO(n) (1 << ((16 * ((n) - 1)) + 15))
1457#define ISPCSI2_TIMING_STOP_STATE_X16_IO(n) (1 << ((16 * ((n) - 1)) + 14))
1458#define ISPCSI2_TIMING_STOP_STATE_X4_IO(n) (1 << ((16 * ((n) - 1)) + 13))
1459#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n) (16 * ((n) - 1))
1460#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(n) \
1461 (0x1fff << ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n))
1462
1463#define ISPCSI2_CTX_CTRL1(n) ((0x070) + 0x20 * (n))
1464#define ISPCSI2_CTX_CTRL1_COUNT_SHIFT 8
1465#define ISPCSI2_CTX_CTRL1_COUNT_MASK \
1466 (0xff << ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
1467#define ISPCSI2_CTX_CTRL1_EOF_EN (1 << 7)
1468#define ISPCSI2_CTX_CTRL1_EOL_EN (1 << 6)
1469#define ISPCSI2_CTX_CTRL1_CS_EN (1 << 5)
1470#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK (1 << 4)
1471#define ISPCSI2_CTX_CTRL1_PING_PONG (1 << 3)
1472#define ISPCSI2_CTX_CTRL1_CTX_EN (1 << 0)
1473
1474#define ISPCSI2_CTX_CTRL2(n) ((0x074) + 0x20 * (n))
1475#define ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT 13
1476#define ISPCSI2_CTX_CTRL2_USER_DEF_MAP_MASK \
1477 (0x3 << ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT)
1478#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT 11
1479#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK \
1480 (0x3 << ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT)
1481#define ISPCSI2_CTX_CTRL2_DPCM_PRED (1 << 10)
1482#define ISPCSI2_CTX_CTRL2_FORMAT_SHIFT 0
1483#define ISPCSI2_CTX_CTRL2_FORMAT_MASK \
1484 (0x3ff << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT)
1485#define ISPCSI2_CTX_CTRL2_FRAME_SHIFT 16
1486#define ISPCSI2_CTX_CTRL2_FRAME_MASK \
1487 (0xffff << ISPCSI2_CTX_CTRL2_FRAME_SHIFT)
1488
1489#define ISPCSI2_CTX_DAT_OFST(n) ((0x078) + 0x20 * (n))
1490#define ISPCSI2_CTX_DAT_OFST_OFST_SHIFT 0
1491#define ISPCSI2_CTX_DAT_OFST_OFST_MASK \
1492 (0x1ffe0 << ISPCSI2_CTX_DAT_OFST_OFST_SHIFT)
1493
1494#define ISPCSI2_CTX_DAT_PING_ADDR(n) ((0x07c) + 0x20 * (n))
1495#define ISPCSI2_CTX_DAT_PONG_ADDR(n) ((0x080) + 0x20 * (n))
1496#define ISPCSI2_CTX_IRQENABLE(n) ((0x084) + 0x20 * (n))
1497#define ISPCSI2_CTX_IRQENABLE_ECC_CORRECTION_IRQ (1 << 8)
1498#define ISPCSI2_CTX_IRQENABLE_LINE_NUMBER_IRQ (1 << 7)
1499#define ISPCSI2_CTX_IRQENABLE_FRAME_NUMBER_IRQ (1 << 6)
1500#define ISPCSI2_CTX_IRQENABLE_CS_IRQ (1 << 5)
1501#define ISPCSI2_CTX_IRQENABLE_LE_IRQ (1 << 3)
1502#define ISPCSI2_CTX_IRQENABLE_LS_IRQ (1 << 2)
1503#define ISPCSI2_CTX_IRQENABLE_FE_IRQ (1 << 1)
1504#define ISPCSI2_CTX_IRQENABLE_FS_IRQ (1 << 0)
1505
1506#define ISPCSI2_CTX_IRQSTATUS(n) ((0x088) + 0x20 * (n))
1507#define ISPCSI2_CTX_IRQSTATUS_ECC_CORRECTION_IRQ (1 << 8)
1508#define ISPCSI2_CTX_IRQSTATUS_LINE_NUMBER_IRQ (1 << 7)
1509#define ISPCSI2_CTX_IRQSTATUS_FRAME_NUMBER_IRQ (1 << 6)
1510#define ISPCSI2_CTX_IRQSTATUS_CS_IRQ (1 << 5)
1511#define ISPCSI2_CTX_IRQSTATUS_LE_IRQ (1 << 3)
1512#define ISPCSI2_CTX_IRQSTATUS_LS_IRQ (1 << 2)
1513#define ISPCSI2_CTX_IRQSTATUS_FE_IRQ (1 << 1)
1514#define ISPCSI2_CTX_IRQSTATUS_FS_IRQ (1 << 0)
1515
1516#define ISPCSI2_CTX_CTRL3(n) ((0x08c) + 0x20 * (n))
1517#define ISPCSI2_CTX_CTRL3_ALPHA_SHIFT 5
1518#define ISPCSI2_CTX_CTRL3_ALPHA_MASK \
1519 (0x3fff << ISPCSI2_CTX_CTRL3_ALPHA_SHIFT)
1520
1521/* This instance is for OMAP3630 only */
1522#define ISPCSI2_CTX_TRANSCODEH(n) (0x000 + 0x8 * (n))
1523#define ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT 16
1524#define ISPCSI2_CTX_TRANSCODEH_HCOUNT_MASK \
1525 (0x1fff << ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT)
1526#define ISPCSI2_CTX_TRANSCODEH_HSKIP_SHIFT 0
1527#define ISPCSI2_CTX_TRANSCODEH_HSKIP_MASK \
1528 (0x1fff << ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT)
1529#define ISPCSI2_CTX_TRANSCODEV(n) (0x004 + 0x8 * (n))
1530#define ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT 16
1531#define ISPCSI2_CTX_TRANSCODEV_VCOUNT_MASK \
1532 (0x1fff << ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT)
1533#define ISPCSI2_CTX_TRANSCODEV_VSKIP_SHIFT 0
1534#define ISPCSI2_CTX_TRANSCODEV_VSKIP_MASK \
1535 (0x1fff << ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT)
1536
1537/* -----------------------------------------------------------------------------
1538 * CSI PHY registers
1539 */
1540
1541#define ISPCSIPHY_REG0 (0x000)
1542#define ISPCSIPHY_REG0_THS_TERM_SHIFT 8
1543#define ISPCSIPHY_REG0_THS_TERM_MASK \
1544 (0xff << ISPCSIPHY_REG0_THS_TERM_SHIFT)
1545#define ISPCSIPHY_REG0_THS_SETTLE_SHIFT 0
1546#define ISPCSIPHY_REG0_THS_SETTLE_MASK \
1547 (0xff << ISPCSIPHY_REG0_THS_SETTLE_SHIFT)
1548
1549#define ISPCSIPHY_REG1 (0x004)
1550#define ISPCSIPHY_REG1_RESET_DONE_CTRLCLK (1 << 29)
1551/* This field is for OMAP3630 only */
1552#define ISPCSIPHY_REG1_CLOCK_MISS_DETECTOR_STATUS (1 << 25)
1553#define ISPCSIPHY_REG1_TCLK_TERM_SHIFT 18
1554#define ISPCSIPHY_REG1_TCLK_TERM_MASK \
1555 (0x7f << ISPCSIPHY_REG1_TCLK_TERM_SHIFT)
1556#define ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN_SHIFT 10
1557#define ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN_MASK \
1558 (0xff << ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN)
1559/* This field is for OMAP3430 only */
1560#define ISPCSIPHY_REG1_TCLK_MISS_SHIFT 8
1561#define ISPCSIPHY_REG1_TCLK_MISS_MASK \
1562 (0x3 << ISPCSIPHY_REG1_TCLK_MISS_SHIFT)
1563/* This field is for OMAP3630 only */
1564#define ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_SHIFT 8
1565#define ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_MASK \
1566 (0x3 << ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_SHIFT)
1567#define ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT 0
1568#define ISPCSIPHY_REG1_TCLK_SETTLE_MASK \
1569 (0xff << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT)
1570
1571/* This register is for OMAP3630 only */
1572#define ISPCSIPHY_REG2 (0x008)
1573#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_SHIFT 30
1574#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_MASK \
1575 (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_SHIFT)
1576#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_SHIFT 28
1577#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_MASK \
1578 (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_SHIFT)
1579#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_SHIFT 26
1580#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_MASK \
1581 (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_SHIFT)
1582#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_SHIFT 24
1583#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_MASK \
1584 (0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_SHIFT)
1585#define ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_SHIFT 0
1586#define ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_MASK \
1587 (0x7fffff << ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_SHIFT)
1588
1589#endif /* OMAP3_ISP_REG_H */
diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/video/omap3isp/ispresizer.c
new file mode 100644
index 00000000000..0bb0f8cd36f
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispresizer.c
@@ -0,0 +1,1738 @@
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 calculate 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 the 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 capabilitie 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, res->error);
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, 0);
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 res->error = 0;
1069}
1070
1071/*
1072 * omap3isp_resizer_isr - ISP resizer interrupt handler
1073 *
1074 * Manage the resizer video buffers and configure shadowed and busy-locked
1075 * registers.
1076 */
1077void omap3isp_resizer_isr(struct isp_res_device *res)
1078{
1079 struct v4l2_mbus_framefmt *informat, *outformat;
1080
1081 if (omap3isp_module_sync_is_stopping(&res->wait, &res->stopping))
1082 return;
1083
1084 if (res->applycrop) {
1085 outformat = __resizer_get_format(res, NULL, RESZ_PAD_SOURCE,
1086 V4L2_SUBDEV_FORMAT_ACTIVE);
1087 informat = __resizer_get_format(res, NULL, RESZ_PAD_SINK,
1088 V4L2_SUBDEV_FORMAT_ACTIVE);
1089 resizer_set_crop_params(res, informat, outformat);
1090 res->applycrop = 0;
1091 }
1092
1093 resizer_isr_buffer(res);
1094}
1095
1096/* -----------------------------------------------------------------------------
1097 * ISP video operations
1098 */
1099
1100static int resizer_video_queue(struct isp_video *video,
1101 struct isp_buffer *buffer)
1102{
1103 struct isp_res_device *res = &video->isp->isp_res;
1104
1105 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1106 resizer_set_inaddr(res, buffer->isp_addr);
1107
1108 /*
1109 * We now have a buffer queued on the output. Despite what the
1110 * TRM says, the resizer can't be restarted immediately.
1111 * Enabling it in one shot mode in the middle of a frame (or at
1112 * least asynchronously to the frame) results in the output
1113 * being shifted randomly left/right and up/down, as if the
1114 * hardware didn't synchronize itself to the beginning of the
1115 * frame correctly.
1116 *
1117 * Restart the resizer on the next sync interrupt if running in
1118 * continuous mode or when starting the stream.
1119 */
1120 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1121 resizer_set_outaddr(res, buffer->isp_addr);
1122
1123 return 0;
1124}
1125
1126static const struct isp_video_operations resizer_video_ops = {
1127 .queue = resizer_video_queue,
1128};
1129
1130/* -----------------------------------------------------------------------------
1131 * V4L2 subdev operations
1132 */
1133
1134/*
1135 * resizer_set_stream - Enable/Disable streaming on resizer subdev
1136 * @sd: ISP resizer V4L2 subdev
1137 * @enable: 1 == Enable, 0 == Disable
1138 *
1139 * The resizer hardware can't be enabled without a memory buffer to write to.
1140 * As the s_stream operation is called in response to a STREAMON call without
1141 * any buffer queued yet, just update the state field and return immediately.
1142 * The resizer will be enabled in resizer_video_queue().
1143 */
1144static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
1145{
1146 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1147 struct isp_video *video_out = &res->video_out;
1148 struct isp_device *isp = to_isp_device(res);
1149 struct device *dev = to_device(res);
1150
1151 if (res->state == ISP_PIPELINE_STREAM_STOPPED) {
1152 if (enable == ISP_PIPELINE_STREAM_STOPPED)
1153 return 0;
1154
1155 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER);
1156 resizer_configure(res);
1157 res->error = 0;
1158 resizer_print_status(res);
1159 }
1160
1161 switch (enable) {
1162 case ISP_PIPELINE_STREAM_CONTINUOUS:
1163 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_WRITE);
1164 if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
1165 resizer_enable_oneshot(res);
1166 isp_video_dmaqueue_flags_clr(video_out);
1167 }
1168 break;
1169
1170 case ISP_PIPELINE_STREAM_SINGLESHOT:
1171 if (res->input == RESIZER_INPUT_MEMORY)
1172 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_READ);
1173 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_WRITE);
1174
1175 resizer_enable_oneshot(res);
1176 break;
1177
1178 case ISP_PIPELINE_STREAM_STOPPED:
1179 if (omap3isp_module_sync_idle(&sd->entity, &res->wait,
1180 &res->stopping))
1181 dev_dbg(dev, "%s: module stop timeout.\n", sd->name);
1182 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_RESIZER_READ |
1183 OMAP3_ISP_SBL_RESIZER_WRITE);
1184 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_RESIZER);
1185 isp_video_dmaqueue_flags_clr(video_out);
1186 break;
1187 }
1188
1189 res->state = enable;
1190 return 0;
1191}
1192
1193/*
1194 * resizer_g_crop - handle get crop subdev operation
1195 * @sd : pointer to v4l2 subdev structure
1196 * @pad : subdev pad
1197 * @crop : pointer to crop structure
1198 * @which : active or try format
1199 * return zero
1200 */
1201static int resizer_g_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1202 struct v4l2_subdev_crop *crop)
1203{
1204 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1205 struct v4l2_mbus_framefmt *format;
1206 struct resizer_ratio ratio;
1207
1208 /* Only sink pad has crop capability */
1209 if (crop->pad != RESZ_PAD_SINK)
1210 return -EINVAL;
1211
1212 format = __resizer_get_format(res, fh, RESZ_PAD_SOURCE, crop->which);
1213 crop->rect = *__resizer_get_crop(res, fh, crop->which);
1214 resizer_calc_ratios(res, &crop->rect, format, &ratio);
1215
1216 return 0;
1217}
1218
1219/*
1220 * resizer_try_crop - mangles crop parameters.
1221 */
1222static void resizer_try_crop(const struct v4l2_mbus_framefmt *sink,
1223 const struct v4l2_mbus_framefmt *source,
1224 struct v4l2_rect *crop)
1225{
1226 const unsigned int spv = DEFAULT_PHASE;
1227 const unsigned int sph = DEFAULT_PHASE;
1228
1229 /* Crop rectangle is constrained to the output size so that zoom ratio
1230 * cannot exceed +/-4.0.
1231 */
1232 unsigned int min_width =
1233 ((32 * sph + (source->width - 1) * 64 + 16) >> 8) + 7;
1234 unsigned int min_height =
1235 ((32 * spv + (source->height - 1) * 64 + 16) >> 8) + 4;
1236 unsigned int max_width =
1237 ((64 * sph + (source->width - 1) * 1024 + 32) >> 8) + 7;
1238 unsigned int max_height =
1239 ((64 * spv + (source->height - 1) * 1024 + 32) >> 8) + 7;
1240
1241 crop->width = clamp_t(u32, crop->width, min_width, max_width);
1242 crop->height = clamp_t(u32, crop->height, min_height, max_height);
1243
1244 /* Crop can not go beyond of the input rectangle */
1245 crop->left = clamp_t(u32, crop->left, 0, sink->width - MIN_IN_WIDTH);
1246 crop->width = clamp_t(u32, crop->width, MIN_IN_WIDTH,
1247 sink->width - crop->left);
1248 crop->top = clamp_t(u32, crop->top, 0, sink->height - MIN_IN_HEIGHT);
1249 crop->height = clamp_t(u32, crop->height, MIN_IN_HEIGHT,
1250 sink->height - crop->top);
1251}
1252
1253/*
1254 * resizer_s_crop - handle set crop subdev operation
1255 * @sd : pointer to v4l2 subdev structure
1256 * @pad : subdev pad
1257 * @crop : pointer to crop structure
1258 * @which : active or try format
1259 * return -EINVAL or zero when succeed
1260 */
1261static int resizer_s_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1262 struct v4l2_subdev_crop *crop)
1263{
1264 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1265 struct isp_device *isp = to_isp_device(res);
1266 struct v4l2_mbus_framefmt *format_sink, *format_source;
1267 struct resizer_ratio ratio;
1268
1269 /* Only sink pad has crop capability */
1270 if (crop->pad != RESZ_PAD_SINK)
1271 return -EINVAL;
1272
1273 format_sink = __resizer_get_format(res, fh, RESZ_PAD_SINK,
1274 crop->which);
1275 format_source = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
1276 crop->which);
1277
1278 dev_dbg(isp->dev, "%s: L=%d,T=%d,W=%d,H=%d,which=%d\n", __func__,
1279 crop->rect.left, crop->rect.top, crop->rect.width,
1280 crop->rect.height, crop->which);
1281
1282 dev_dbg(isp->dev, "%s: input=%dx%d, output=%dx%d\n", __func__,
1283 format_sink->width, format_sink->height,
1284 format_source->width, format_source->height);
1285
1286 resizer_try_crop(format_sink, format_source, &crop->rect);
1287 *__resizer_get_crop(res, fh, crop->which) = crop->rect;
1288 resizer_calc_ratios(res, &crop->rect, format_source, &ratio);
1289
1290 if (crop->which == V4L2_SUBDEV_FORMAT_TRY)
1291 return 0;
1292
1293 res->ratio = ratio;
1294 res->crop.active = crop->rect;
1295
1296 /*
1297 * s_crop can be called while streaming is on. In this case
1298 * the crop values will be set in the next IRQ.
1299 */
1300 if (res->state != ISP_PIPELINE_STREAM_STOPPED)
1301 res->applycrop = 1;
1302
1303 return 0;
1304}
1305
1306/* resizer pixel formats */
1307static const unsigned int resizer_formats[] = {
1308 V4L2_MBUS_FMT_UYVY8_1X16,
1309 V4L2_MBUS_FMT_YUYV8_1X16,
1310};
1311
1312static unsigned int resizer_max_in_width(struct isp_res_device *res)
1313{
1314 struct isp_device *isp = to_isp_device(res);
1315
1316 if (res->input == RESIZER_INPUT_MEMORY) {
1317 return MAX_IN_WIDTH_MEMORY_MODE;
1318 } else {
1319 if (isp->revision == ISP_REVISION_1_0)
1320 return MAX_IN_WIDTH_ONTHEFLY_MODE_ES1;
1321 else
1322 return MAX_IN_WIDTH_ONTHEFLY_MODE_ES2;
1323 }
1324}
1325
1326/*
1327 * resizer_try_format - Handle try format by pad subdev method
1328 * @res : ISP resizer device
1329 * @fh : V4L2 subdev file handle
1330 * @pad : pad num
1331 * @fmt : pointer to v4l2 format structure
1332 * @which : wanted subdev format
1333 */
1334static void resizer_try_format(struct isp_res_device *res,
1335 struct v4l2_subdev_fh *fh, unsigned int pad,
1336 struct v4l2_mbus_framefmt *fmt,
1337 enum v4l2_subdev_format_whence which)
1338{
1339 struct v4l2_mbus_framefmt *format;
1340 struct resizer_ratio ratio;
1341 struct v4l2_rect crop;
1342
1343 switch (pad) {
1344 case RESZ_PAD_SINK:
1345 if (fmt->code != V4L2_MBUS_FMT_YUYV8_1X16 &&
1346 fmt->code != V4L2_MBUS_FMT_UYVY8_1X16)
1347 fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
1348
1349 fmt->width = clamp_t(u32, fmt->width, MIN_IN_WIDTH,
1350 resizer_max_in_width(res));
1351 fmt->height = clamp_t(u32, fmt->height, MIN_IN_HEIGHT,
1352 MAX_IN_HEIGHT);
1353 break;
1354
1355 case RESZ_PAD_SOURCE:
1356 format = __resizer_get_format(res, fh, RESZ_PAD_SINK, which);
1357 fmt->code = format->code;
1358
1359 crop = *__resizer_get_crop(res, fh, which);
1360 resizer_calc_ratios(res, &crop, fmt, &ratio);
1361 break;
1362 }
1363
1364 fmt->colorspace = V4L2_COLORSPACE_JPEG;
1365 fmt->field = V4L2_FIELD_NONE;
1366}
1367
1368/*
1369 * resizer_enum_mbus_code - Handle pixel format enumeration
1370 * @sd : pointer to v4l2 subdev structure
1371 * @fh : V4L2 subdev file handle
1372 * @code : pointer to v4l2_subdev_mbus_code_enum structure
1373 * return -EINVAL or zero on success
1374 */
1375static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
1376 struct v4l2_subdev_fh *fh,
1377 struct v4l2_subdev_mbus_code_enum *code)
1378{
1379 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1380 struct v4l2_mbus_framefmt *format;
1381
1382 if (code->pad == RESZ_PAD_SINK) {
1383 if (code->index >= ARRAY_SIZE(resizer_formats))
1384 return -EINVAL;
1385
1386 code->code = resizer_formats[code->index];
1387 } else {
1388 if (code->index != 0)
1389 return -EINVAL;
1390
1391 format = __resizer_get_format(res, fh, RESZ_PAD_SINK,
1392 V4L2_SUBDEV_FORMAT_TRY);
1393 code->code = format->code;
1394 }
1395
1396 return 0;
1397}
1398
1399static int resizer_enum_frame_size(struct v4l2_subdev *sd,
1400 struct v4l2_subdev_fh *fh,
1401 struct v4l2_subdev_frame_size_enum *fse)
1402{
1403 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1404 struct v4l2_mbus_framefmt format;
1405
1406 if (fse->index != 0)
1407 return -EINVAL;
1408
1409 format.code = fse->code;
1410 format.width = 1;
1411 format.height = 1;
1412 resizer_try_format(res, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1413 fse->min_width = format.width;
1414 fse->min_height = format.height;
1415
1416 if (format.code != fse->code)
1417 return -EINVAL;
1418
1419 format.code = fse->code;
1420 format.width = -1;
1421 format.height = -1;
1422 resizer_try_format(res, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1423 fse->max_width = format.width;
1424 fse->max_height = format.height;
1425
1426 return 0;
1427}
1428
1429/*
1430 * resizer_get_format - Handle get format by pads subdev method
1431 * @sd : pointer to v4l2 subdev structure
1432 * @fh : V4L2 subdev file handle
1433 * @fmt : pointer to v4l2 subdev format structure
1434 * return -EINVAL or zero on success
1435 */
1436static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1437 struct v4l2_subdev_format *fmt)
1438{
1439 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1440 struct v4l2_mbus_framefmt *format;
1441
1442 format = __resizer_get_format(res, fh, fmt->pad, fmt->which);
1443 if (format == NULL)
1444 return -EINVAL;
1445
1446 fmt->format = *format;
1447 return 0;
1448}
1449
1450/*
1451 * resizer_set_format - Handle set format by pads subdev method
1452 * @sd : pointer to v4l2 subdev structure
1453 * @fh : V4L2 subdev file handle
1454 * @fmt : pointer to v4l2 subdev format structure
1455 * return -EINVAL or zero on success
1456 */
1457static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1458 struct v4l2_subdev_format *fmt)
1459{
1460 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1461 struct v4l2_mbus_framefmt *format;
1462 struct v4l2_rect *crop;
1463
1464 format = __resizer_get_format(res, fh, fmt->pad, fmt->which);
1465 if (format == NULL)
1466 return -EINVAL;
1467
1468 resizer_try_format(res, fh, fmt->pad, &fmt->format, fmt->which);
1469 *format = fmt->format;
1470
1471 if (fmt->pad == RESZ_PAD_SINK) {
1472 /* reset crop rectangle */
1473 crop = __resizer_get_crop(res, fh, fmt->which);
1474 crop->left = 0;
1475 crop->top = 0;
1476 crop->width = fmt->format.width;
1477 crop->height = fmt->format.height;
1478
1479 /* Propagate the format from sink to source */
1480 format = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
1481 fmt->which);
1482 *format = fmt->format;
1483 resizer_try_format(res, fh, RESZ_PAD_SOURCE, format,
1484 fmt->which);
1485 }
1486
1487 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
1488 /* Compute and store the active crop rectangle and resizer
1489 * ratios. format already points to the source pad active
1490 * format.
1491 */
1492 res->crop.active = res->crop.request;
1493 resizer_calc_ratios(res, &res->crop.active, format,
1494 &res->ratio);
1495 }
1496
1497 return 0;
1498}
1499
1500/*
1501 * resizer_init_formats - Initialize formats on all pads
1502 * @sd: ISP resizer V4L2 subdevice
1503 * @fh: V4L2 subdev file handle
1504 *
1505 * Initialize all pad formats with default values. If fh is not NULL, try
1506 * formats are initialized on the file handle. Otherwise active formats are
1507 * initialized on the device.
1508 */
1509static int resizer_init_formats(struct v4l2_subdev *sd,
1510 struct v4l2_subdev_fh *fh)
1511{
1512 struct v4l2_subdev_format format;
1513
1514 memset(&format, 0, sizeof(format));
1515 format.pad = RESZ_PAD_SINK;
1516 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1517 format.format.code = V4L2_MBUS_FMT_YUYV8_1X16;
1518 format.format.width = 4096;
1519 format.format.height = 4096;
1520 resizer_set_format(sd, fh, &format);
1521
1522 return 0;
1523}
1524
1525/* subdev video operations */
1526static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = {
1527 .s_stream = resizer_set_stream,
1528};
1529
1530/* subdev pad operations */
1531static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = {
1532 .enum_mbus_code = resizer_enum_mbus_code,
1533 .enum_frame_size = resizer_enum_frame_size,
1534 .get_fmt = resizer_get_format,
1535 .set_fmt = resizer_set_format,
1536 .get_crop = resizer_g_crop,
1537 .set_crop = resizer_s_crop,
1538};
1539
1540/* subdev operations */
1541static const struct v4l2_subdev_ops resizer_v4l2_ops = {
1542 .video = &resizer_v4l2_video_ops,
1543 .pad = &resizer_v4l2_pad_ops,
1544};
1545
1546/* subdev internal operations */
1547static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = {
1548 .open = resizer_init_formats,
1549};
1550
1551/* -----------------------------------------------------------------------------
1552 * Media entity operations
1553 */
1554
1555/*
1556 * resizer_link_setup - Setup resizer connections.
1557 * @entity : Pointer to media entity structure
1558 * @local : Pointer to local pad array
1559 * @remote : Pointer to remote pad array
1560 * @flags : Link flags
1561 * return -EINVAL or zero on success
1562 */
1563static int resizer_link_setup(struct media_entity *entity,
1564 const struct media_pad *local,
1565 const struct media_pad *remote, u32 flags)
1566{
1567 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1568 struct isp_res_device *res = v4l2_get_subdevdata(sd);
1569
1570 switch (local->index | media_entity_type(remote->entity)) {
1571 case RESZ_PAD_SINK | MEDIA_ENT_T_DEVNODE:
1572 /* read from memory */
1573 if (flags & MEDIA_LNK_FL_ENABLED) {
1574 if (res->input == RESIZER_INPUT_VP)
1575 return -EBUSY;
1576 res->input = RESIZER_INPUT_MEMORY;
1577 } else {
1578 if (res->input == RESIZER_INPUT_MEMORY)
1579 res->input = RESIZER_INPUT_NONE;
1580 }
1581 break;
1582
1583 case RESZ_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
1584 /* read from ccdc or previewer */
1585 if (flags & MEDIA_LNK_FL_ENABLED) {
1586 if (res->input == RESIZER_INPUT_MEMORY)
1587 return -EBUSY;
1588 res->input = RESIZER_INPUT_VP;
1589 } else {
1590 if (res->input == RESIZER_INPUT_VP)
1591 res->input = RESIZER_INPUT_NONE;
1592 }
1593 break;
1594
1595 case RESZ_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
1596 /* resizer always write to memory */
1597 break;
1598
1599 default:
1600 return -EINVAL;
1601 }
1602
1603 return 0;
1604}
1605
1606/* media operations */
1607static const struct media_entity_operations resizer_media_ops = {
1608 .link_setup = resizer_link_setup,
1609};
1610
1611/*
1612 * resizer_init_entities - Initialize resizer subdev and media entity.
1613 * @res : Pointer to resizer device structure
1614 * return -ENOMEM or zero on success
1615 */
1616static int resizer_init_entities(struct isp_res_device *res)
1617{
1618 struct v4l2_subdev *sd = &res->subdev;
1619 struct media_pad *pads = res->pads;
1620 struct media_entity *me = &sd->entity;
1621 int ret;
1622
1623 res->input = RESIZER_INPUT_NONE;
1624
1625 v4l2_subdev_init(sd, &resizer_v4l2_ops);
1626 sd->internal_ops = &resizer_v4l2_internal_ops;
1627 strlcpy(sd->name, "OMAP3 ISP resizer", sizeof(sd->name));
1628 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
1629 v4l2_set_subdevdata(sd, res);
1630 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1631
1632 pads[RESZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1633 pads[RESZ_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1634
1635 me->ops = &resizer_media_ops;
1636 ret = media_entity_init(me, RESZ_PADS_NUM, pads, 0);
1637 if (ret < 0)
1638 return ret;
1639
1640 resizer_init_formats(sd, NULL);
1641
1642 res->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1643 res->video_in.ops = &resizer_video_ops;
1644 res->video_in.isp = to_isp_device(res);
1645 res->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
1646 res->video_in.bpl_alignment = 32;
1647 res->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1648 res->video_out.ops = &resizer_video_ops;
1649 res->video_out.isp = to_isp_device(res);
1650 res->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
1651 res->video_out.bpl_alignment = 32;
1652
1653 ret = omap3isp_video_init(&res->video_in, "resizer");
1654 if (ret < 0)
1655 return ret;
1656
1657 ret = omap3isp_video_init(&res->video_out, "resizer");
1658 if (ret < 0)
1659 return ret;
1660
1661 /* Connect the video nodes to the resizer subdev. */
1662 ret = media_entity_create_link(&res->video_in.video.entity, 0,
1663 &res->subdev.entity, RESZ_PAD_SINK, 0);
1664 if (ret < 0)
1665 return ret;
1666
1667 ret = media_entity_create_link(&res->subdev.entity, RESZ_PAD_SOURCE,
1668 &res->video_out.video.entity, 0, 0);
1669 if (ret < 0)
1670 return ret;
1671
1672 return 0;
1673}
1674
1675void omap3isp_resizer_unregister_entities(struct isp_res_device *res)
1676{
1677 media_entity_cleanup(&res->subdev.entity);
1678
1679 v4l2_device_unregister_subdev(&res->subdev);
1680 omap3isp_video_unregister(&res->video_in);
1681 omap3isp_video_unregister(&res->video_out);
1682}
1683
1684int omap3isp_resizer_register_entities(struct isp_res_device *res,
1685 struct v4l2_device *vdev)
1686{
1687 int ret;
1688
1689 /* Register the subdev and video nodes. */
1690 ret = v4l2_device_register_subdev(vdev, &res->subdev);
1691 if (ret < 0)
1692 goto error;
1693
1694 ret = omap3isp_video_register(&res->video_in, vdev);
1695 if (ret < 0)
1696 goto error;
1697
1698 ret = omap3isp_video_register(&res->video_out, vdev);
1699 if (ret < 0)
1700 goto error;
1701
1702 return 0;
1703
1704error:
1705 omap3isp_resizer_unregister_entities(res);
1706 return ret;
1707}
1708
1709/* -----------------------------------------------------------------------------
1710 * ISP resizer initialization and cleanup
1711 */
1712
1713void omap3isp_resizer_cleanup(struct isp_device *isp)
1714{
1715}
1716
1717/*
1718 * isp_resizer_init - Resizer initialization.
1719 * @isp : Pointer to ISP device
1720 * return -ENOMEM or zero on success
1721 */
1722int omap3isp_resizer_init(struct isp_device *isp)
1723{
1724 struct isp_res_device *res = &isp->isp_res;
1725 int ret;
1726
1727 init_waitqueue_head(&res->wait);
1728 atomic_set(&res->stopping, 0);
1729 ret = resizer_init_entities(res);
1730 if (ret < 0)
1731 goto out;
1732
1733out:
1734 if (ret)
1735 omap3isp_resizer_cleanup(isp);
1736
1737 return ret;
1738}
diff --git a/drivers/media/video/omap3isp/ispresizer.h b/drivers/media/video/omap3isp/ispresizer.h
new file mode 100644
index 00000000000..76abc2e4212
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispresizer.h
@@ -0,0 +1,147 @@
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 unsigned int error;
111
112 u32 addr_base; /* stored source buffer address in memory mode */
113 u32 crop_offset; /* additional offset for crop in memory mode */
114 struct resizer_ratio ratio;
115 int pm_state;
116 unsigned int applycrop:1;
117 enum isp_pipeline_stream_state state;
118 wait_queue_head_t wait;
119 atomic_t stopping;
120
121 struct {
122 struct v4l2_rect request;
123 struct v4l2_rect active;
124 } crop;
125};
126
127struct isp_device;
128
129int omap3isp_resizer_init(struct isp_device *isp);
130void omap3isp_resizer_cleanup(struct isp_device *isp);
131
132int omap3isp_resizer_register_entities(struct isp_res_device *res,
133 struct v4l2_device *vdev);
134void omap3isp_resizer_unregister_entities(struct isp_res_device *res);
135void omap3isp_resizer_isr_frame_sync(struct isp_res_device *res);
136void omap3isp_resizer_isr(struct isp_res_device *isp_res);
137
138void omap3isp_resizer_max_rate(struct isp_res_device *res,
139 unsigned int *max_rate);
140
141void omap3isp_resizer_suspend(struct isp_res_device *isp_res);
142
143void omap3isp_resizer_resume(struct isp_res_device *isp_res);
144
145int omap3isp_resizer_busy(struct isp_res_device *isp_res);
146
147#endif /* OMAP3_ISP_RESIZER_H */
diff --git a/drivers/media/video/omap3isp/ispstat.c b/drivers/media/video/omap3isp/ispstat.c
new file mode 100644
index 00000000000..036fc938bbb
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispstat.c
@@ -0,0 +1,1092 @@
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
1026static int isp_stat_init_entities(struct ispstat *stat, const char *name,
1027 const struct v4l2_subdev_ops *sd_ops)
1028{
1029 struct v4l2_subdev *subdev = &stat->subdev;
1030 struct media_entity *me = &subdev->entity;
1031
1032 v4l2_subdev_init(subdev, sd_ops);
1033 snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name);
1034 subdev->grp_id = 1 << 16; /* group ID for isp subdevs */
1035 subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1036 v4l2_set_subdevdata(subdev, stat);
1037
1038 stat->pad.flags = MEDIA_PAD_FL_SINK;
1039 me->ops = NULL;
1040
1041 return media_entity_init(me, 1, &stat->pad, 0);
1042}
1043
1044int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
1045 struct v4l2_fh *fh,
1046 struct v4l2_event_subscription *sub)
1047{
1048 struct ispstat *stat = v4l2_get_subdevdata(subdev);
1049
1050 if (sub->type != stat->event_type)
1051 return -EINVAL;
1052
1053 return v4l2_event_subscribe(fh, sub, STAT_NEVENTS);
1054}
1055
1056int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
1057 struct v4l2_fh *fh,
1058 struct v4l2_event_subscription *sub)
1059{
1060 return v4l2_event_unsubscribe(fh, sub);
1061}
1062
1063void omap3isp_stat_unregister_entities(struct ispstat *stat)
1064{
1065 media_entity_cleanup(&stat->subdev.entity);
1066 v4l2_device_unregister_subdev(&stat->subdev);
1067}
1068
1069int omap3isp_stat_register_entities(struct ispstat *stat,
1070 struct v4l2_device *vdev)
1071{
1072 return v4l2_device_register_subdev(vdev, &stat->subdev);
1073}
1074
1075int omap3isp_stat_init(struct ispstat *stat, const char *name,
1076 const struct v4l2_subdev_ops *sd_ops)
1077{
1078 stat->buf = kcalloc(STAT_MAX_BUFS, sizeof(*stat->buf), GFP_KERNEL);
1079 if (!stat->buf)
1080 return -ENOMEM;
1081 isp_stat_buf_clear(stat);
1082 mutex_init(&stat->ioctl_lock);
1083 atomic_set(&stat->buf_err, 0);
1084
1085 return isp_stat_init_entities(stat, name, sd_ops);
1086}
1087
1088void omap3isp_stat_free(struct ispstat *stat)
1089{
1090 isp_stat_bufs_free(stat);
1091 kfree(stat->buf);
1092}
diff --git a/drivers/media/video/omap3isp/ispstat.h b/drivers/media/video/omap3isp/ispstat.h
new file mode 100644
index 00000000000..d86da94fa50
--- /dev/null
+++ b/drivers/media/video/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_free(struct ispstat *stat);
148int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
149 struct v4l2_fh *fh,
150 struct v4l2_event_subscription *sub);
151int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
152 struct v4l2_fh *fh,
153 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/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c
new file mode 100644
index 00000000000..6d1d55b7c72
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispvideo.c
@@ -0,0 +1,1334 @@
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/pagemap.h>
30#include <linux/scatterlist.h>
31#include <linux/sched.h>
32#include <linux/slab.h>
33#include <linux/vmalloc.h>
34#include <media/v4l2-dev.h>
35#include <media/v4l2-ioctl.h>
36#include <plat/iommu.h>
37#include <plat/iovmm.h>
38#include <plat/omap-pm.h>
39
40#include "ispvideo.h"
41#include "isp.h"
42
43
44/* -----------------------------------------------------------------------------
45 * Helper functions
46 */
47
48static struct isp_format_info formats[] = {
49 { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
50 V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
51 V4L2_PIX_FMT_GREY, 8, },
52 { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
53 V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
54 V4L2_PIX_FMT_Y10, 10, },
55 { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
56 V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
57 V4L2_PIX_FMT_Y12, 12, },
58 { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
59 V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
60 V4L2_PIX_FMT_SBGGR8, 8, },
61 { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
62 V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
63 V4L2_PIX_FMT_SGBRG8, 8, },
64 { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
65 V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
66 V4L2_PIX_FMT_SGRBG8, 8, },
67 { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
68 V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
69 V4L2_PIX_FMT_SRGGB8, 8, },
70 { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
71 V4L2_MBUS_FMT_SGRBG10_1X10, 0,
72 V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
73 { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
74 V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
75 V4L2_PIX_FMT_SBGGR10, 10, },
76 { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
77 V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
78 V4L2_PIX_FMT_SGBRG10, 10, },
79 { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
80 V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
81 V4L2_PIX_FMT_SGRBG10, 10, },
82 { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
83 V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
84 V4L2_PIX_FMT_SRGGB10, 10, },
85 { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
86 V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
87 V4L2_PIX_FMT_SBGGR12, 12, },
88 { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
89 V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
90 V4L2_PIX_FMT_SGBRG12, 12, },
91 { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
92 V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
93 V4L2_PIX_FMT_SGRBG12, 12, },
94 { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
95 V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
96 V4L2_PIX_FMT_SRGGB12, 12, },
97 { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
98 V4L2_MBUS_FMT_UYVY8_1X16, 0,
99 V4L2_PIX_FMT_UYVY, 16, },
100 { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
101 V4L2_MBUS_FMT_YUYV8_1X16, 0,
102 V4L2_PIX_FMT_YUYV, 16, },
103};
104
105const struct isp_format_info *
106omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
107{
108 unsigned int i;
109
110 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
111 if (formats[i].code == code)
112 return &formats[i];
113 }
114
115 return NULL;
116}
117
118/*
119 * Decide whether desired output pixel code can be obtained with
120 * the lane shifter by shifting the input pixel code.
121 * @in: input pixelcode to shifter
122 * @out: output pixelcode from shifter
123 * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
124 *
125 * return true if the combination is possible
126 * return false otherwise
127 */
128static bool isp_video_is_shiftable(enum v4l2_mbus_pixelcode in,
129 enum v4l2_mbus_pixelcode out,
130 unsigned int additional_shift)
131{
132 const struct isp_format_info *in_info, *out_info;
133
134 if (in == out)
135 return true;
136
137 in_info = omap3isp_video_format_info(in);
138 out_info = omap3isp_video_format_info(out);
139
140 if ((in_info->flavor == 0) || (out_info->flavor == 0))
141 return false;
142
143 if (in_info->flavor != out_info->flavor)
144 return false;
145
146 return in_info->bpp - out_info->bpp + additional_shift <= 6;
147}
148
149/*
150 * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
151 * @video: ISP video instance
152 * @mbus: v4l2_mbus_framefmt format (input)
153 * @pix: v4l2_pix_format format (output)
154 *
155 * Fill the output pix structure with information from the input mbus format.
156 * The bytesperline and sizeimage fields are computed from the requested bytes
157 * per line value in the pix format and information from the video instance.
158 *
159 * Return the number of padding bytes at end of line.
160 */
161static unsigned int isp_video_mbus_to_pix(const struct isp_video *video,
162 const struct v4l2_mbus_framefmt *mbus,
163 struct v4l2_pix_format *pix)
164{
165 unsigned int bpl = pix->bytesperline;
166 unsigned int min_bpl;
167 unsigned int i;
168
169 memset(pix, 0, sizeof(*pix));
170 pix->width = mbus->width;
171 pix->height = mbus->height;
172
173 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
174 if (formats[i].code == mbus->code)
175 break;
176 }
177
178 if (WARN_ON(i == ARRAY_SIZE(formats)))
179 return 0;
180
181 min_bpl = pix->width * ALIGN(formats[i].bpp, 8) / 8;
182
183 /* Clamp the requested bytes per line value. If the maximum bytes per
184 * line value is zero, the module doesn't support user configurable line
185 * sizes. Override the requested value with the minimum in that case.
186 */
187 if (video->bpl_max)
188 bpl = clamp(bpl, min_bpl, video->bpl_max);
189 else
190 bpl = min_bpl;
191
192 if (!video->bpl_zero_padding || bpl != min_bpl)
193 bpl = ALIGN(bpl, video->bpl_alignment);
194
195 pix->pixelformat = formats[i].pixelformat;
196 pix->bytesperline = bpl;
197 pix->sizeimage = pix->bytesperline * pix->height;
198 pix->colorspace = mbus->colorspace;
199 pix->field = mbus->field;
200
201 return bpl - min_bpl;
202}
203
204static void isp_video_pix_to_mbus(const struct v4l2_pix_format *pix,
205 struct v4l2_mbus_framefmt *mbus)
206{
207 unsigned int i;
208
209 memset(mbus, 0, sizeof(*mbus));
210 mbus->width = pix->width;
211 mbus->height = pix->height;
212
213 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
214 if (formats[i].pixelformat == pix->pixelformat)
215 break;
216 }
217
218 if (WARN_ON(i == ARRAY_SIZE(formats)))
219 return;
220
221 mbus->code = formats[i].code;
222 mbus->colorspace = pix->colorspace;
223 mbus->field = pix->field;
224}
225
226static struct v4l2_subdev *
227isp_video_remote_subdev(struct isp_video *video, u32 *pad)
228{
229 struct media_pad *remote;
230
231 remote = media_entity_remote_source(&video->pad);
232
233 if (remote == NULL ||
234 media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
235 return NULL;
236
237 if (pad)
238 *pad = remote->index;
239
240 return media_entity_to_v4l2_subdev(remote->entity);
241}
242
243/* Return a pointer to the ISP video instance at the far end of the pipeline. */
244static struct isp_video *
245isp_video_far_end(struct isp_video *video)
246{
247 struct media_entity_graph graph;
248 struct media_entity *entity = &video->video.entity;
249 struct media_device *mdev = entity->parent;
250 struct isp_video *far_end = NULL;
251
252 mutex_lock(&mdev->graph_mutex);
253 media_entity_graph_walk_start(&graph, entity);
254
255 while ((entity = media_entity_graph_walk_next(&graph))) {
256 if (entity == &video->video.entity)
257 continue;
258
259 if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
260 continue;
261
262 far_end = to_isp_video(media_entity_to_video_device(entity));
263 if (far_end->type != video->type)
264 break;
265
266 far_end = NULL;
267 }
268
269 mutex_unlock(&mdev->graph_mutex);
270 return far_end;
271}
272
273/*
274 * Validate a pipeline by checking both ends of all links for format
275 * discrepancies.
276 *
277 * Compute the minimum time per frame value as the maximum of time per frame
278 * limits reported by every block in the pipeline.
279 *
280 * Return 0 if all formats match, or -EPIPE if at least one link is found with
281 * different formats on its two ends.
282 */
283static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
284{
285 struct isp_device *isp = pipe->output->isp;
286 struct v4l2_subdev_format fmt_source;
287 struct v4l2_subdev_format fmt_sink;
288 struct media_pad *pad;
289 struct v4l2_subdev *subdev;
290 int ret;
291
292 pipe->max_rate = pipe->l3_ick;
293
294 subdev = isp_video_remote_subdev(pipe->output, NULL);
295 if (subdev == NULL)
296 return -EPIPE;
297
298 while (1) {
299 unsigned int shifter_link;
300 /* Retrieve the sink format */
301 pad = &subdev->entity.pads[0];
302 if (!(pad->flags & MEDIA_PAD_FL_SINK))
303 break;
304
305 fmt_sink.pad = pad->index;
306 fmt_sink.which = V4L2_SUBDEV_FORMAT_ACTIVE;
307 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_sink);
308 if (ret < 0 && ret != -ENOIOCTLCMD)
309 return -EPIPE;
310
311 /* Update the maximum frame rate */
312 if (subdev == &isp->isp_res.subdev)
313 omap3isp_resizer_max_rate(&isp->isp_res,
314 &pipe->max_rate);
315
316 /* Check ccdc maximum data rate when data comes from sensor
317 * TODO: Include ccdc rate in pipe->max_rate and compare the
318 * total pipe rate with the input data rate from sensor.
319 */
320 if (subdev == &isp->isp_ccdc.subdev && pipe->input == NULL) {
321 unsigned int rate = UINT_MAX;
322
323 omap3isp_ccdc_max_rate(&isp->isp_ccdc, &rate);
324 if (isp->isp_ccdc.vpcfg.pixelclk > rate)
325 return -ENOSPC;
326 }
327
328 /* If sink pad is on CCDC, the link has the lane shifter
329 * in the middle of it. */
330 shifter_link = subdev == &isp->isp_ccdc.subdev;
331
332 /* Retrieve the source format */
333 pad = media_entity_remote_source(pad);
334 if (pad == NULL ||
335 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
336 break;
337
338 subdev = media_entity_to_v4l2_subdev(pad->entity);
339
340 fmt_source.pad = pad->index;
341 fmt_source.which = V4L2_SUBDEV_FORMAT_ACTIVE;
342 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_source);
343 if (ret < 0 && ret != -ENOIOCTLCMD)
344 return -EPIPE;
345
346 /* Check if the two ends match */
347 if (fmt_source.format.width != fmt_sink.format.width ||
348 fmt_source.format.height != fmt_sink.format.height)
349 return -EPIPE;
350
351 if (shifter_link) {
352 unsigned int parallel_shift = 0;
353 if (isp->isp_ccdc.input == CCDC_INPUT_PARALLEL) {
354 struct isp_parallel_platform_data *pdata =
355 &((struct isp_v4l2_subdevs_group *)
356 subdev->host_priv)->bus.parallel;
357 parallel_shift = pdata->data_lane_shift * 2;
358 }
359 if (!isp_video_is_shiftable(fmt_source.format.code,
360 fmt_sink.format.code,
361 parallel_shift))
362 return -EPIPE;
363 } else if (fmt_source.format.code != fmt_sink.format.code)
364 return -EPIPE;
365 }
366
367 return 0;
368}
369
370static int
371__isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
372{
373 struct v4l2_subdev_format fmt;
374 struct v4l2_subdev *subdev;
375 u32 pad;
376 int ret;
377
378 subdev = isp_video_remote_subdev(video, &pad);
379 if (subdev == NULL)
380 return -EINVAL;
381
382 mutex_lock(&video->mutex);
383
384 fmt.pad = pad;
385 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
386 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
387 if (ret == -ENOIOCTLCMD)
388 ret = -EINVAL;
389
390 mutex_unlock(&video->mutex);
391
392 if (ret)
393 return ret;
394
395 format->type = video->type;
396 return isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
397}
398
399static int
400isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
401{
402 struct v4l2_format format;
403 int ret;
404
405 memcpy(&format, &vfh->format, sizeof(format));
406 ret = __isp_video_get_format(video, &format);
407 if (ret < 0)
408 return ret;
409
410 if (vfh->format.fmt.pix.pixelformat != format.fmt.pix.pixelformat ||
411 vfh->format.fmt.pix.height != format.fmt.pix.height ||
412 vfh->format.fmt.pix.width != format.fmt.pix.width ||
413 vfh->format.fmt.pix.bytesperline != format.fmt.pix.bytesperline ||
414 vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage)
415 return -EINVAL;
416
417 return ret;
418}
419
420/* -----------------------------------------------------------------------------
421 * IOMMU management
422 */
423
424#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
425
426/*
427 * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list
428 * @dev: Device pointer specific to the OMAP3 ISP.
429 * @sglist: Pointer to source Scatter gather list to allocate.
430 * @sglen: Number of elements of the scatter-gatter list.
431 *
432 * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
433 * we ran out of memory.
434 */
435static dma_addr_t
436ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
437{
438 struct sg_table *sgt;
439 u32 da;
440
441 sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
442 if (sgt == NULL)
443 return -ENOMEM;
444
445 sgt->sgl = (struct scatterlist *)sglist;
446 sgt->nents = sglen;
447 sgt->orig_nents = sglen;
448
449 da = omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
450 if (IS_ERR_VALUE(da))
451 kfree(sgt);
452
453 return da;
454}
455
456/*
457 * ispmmu_vunmap - Unmap a device address from the ISP MMU
458 * @dev: Device pointer specific to the OMAP3 ISP.
459 * @da: Device address generated from a ispmmu_vmap call.
460 */
461static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
462{
463 struct sg_table *sgt;
464
465 sgt = omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
466 kfree(sgt);
467}
468
469/* -----------------------------------------------------------------------------
470 * Video queue operations
471 */
472
473static void isp_video_queue_prepare(struct isp_video_queue *queue,
474 unsigned int *nbuffers, unsigned int *size)
475{
476 struct isp_video_fh *vfh =
477 container_of(queue, struct isp_video_fh, queue);
478 struct isp_video *video = vfh->video;
479
480 *size = vfh->format.fmt.pix.sizeimage;
481 if (*size == 0)
482 return;
483
484 *nbuffers = min(*nbuffers, video->capture_mem / PAGE_ALIGN(*size));
485}
486
487static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
488{
489 struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
490 struct isp_buffer *buffer = to_isp_buffer(buf);
491 struct isp_video *video = vfh->video;
492
493 if (buffer->isp_addr) {
494 ispmmu_vunmap(video->isp, buffer->isp_addr);
495 buffer->isp_addr = 0;
496 }
497}
498
499static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
500{
501 struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
502 struct isp_buffer *buffer = to_isp_buffer(buf);
503 struct isp_video *video = vfh->video;
504 unsigned long addr;
505
506 addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen);
507 if (IS_ERR_VALUE(addr))
508 return -EIO;
509
510 if (!IS_ALIGNED(addr, 32)) {
511 dev_dbg(video->isp->dev, "Buffer address must be "
512 "aligned to 32 bytes boundary.\n");
513 ispmmu_vunmap(video->isp, buffer->isp_addr);
514 return -EINVAL;
515 }
516
517 buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
518 buffer->isp_addr = addr;
519 return 0;
520}
521
522/*
523 * isp_video_buffer_queue - Add buffer to streaming queue
524 * @buf: Video buffer
525 *
526 * In memory-to-memory mode, start streaming on the pipeline if buffers are
527 * queued on both the input and the output, if the pipeline isn't already busy.
528 * If the pipeline is busy, it will be restarted in the output module interrupt
529 * handler.
530 */
531static void isp_video_buffer_queue(struct isp_video_buffer *buf)
532{
533 struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
534 struct isp_buffer *buffer = to_isp_buffer(buf);
535 struct isp_video *video = vfh->video;
536 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
537 enum isp_pipeline_state state;
538 unsigned long flags;
539 unsigned int empty;
540 unsigned int start;
541
542 empty = list_empty(&video->dmaqueue);
543 list_add_tail(&buffer->buffer.irqlist, &video->dmaqueue);
544
545 if (empty) {
546 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
547 state = ISP_PIPELINE_QUEUE_OUTPUT;
548 else
549 state = ISP_PIPELINE_QUEUE_INPUT;
550
551 spin_lock_irqsave(&pipe->lock, flags);
552 pipe->state |= state;
553 video->ops->queue(video, buffer);
554 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
555
556 start = isp_pipeline_ready(pipe);
557 if (start)
558 pipe->state |= ISP_PIPELINE_STREAM;
559 spin_unlock_irqrestore(&pipe->lock, flags);
560
561 if (start)
562 omap3isp_pipeline_set_stream(pipe,
563 ISP_PIPELINE_STREAM_SINGLESHOT);
564 }
565}
566
567static const struct isp_video_queue_operations isp_video_queue_ops = {
568 .queue_prepare = &isp_video_queue_prepare,
569 .buffer_prepare = &isp_video_buffer_prepare,
570 .buffer_queue = &isp_video_buffer_queue,
571 .buffer_cleanup = &isp_video_buffer_cleanup,
572};
573
574/*
575 * omap3isp_video_buffer_next - Complete the current buffer and return the next
576 * @video: ISP video object
577 * @error: Whether an error occurred during capture
578 *
579 * Remove the current video buffer from the DMA queue and fill its timestamp,
580 * field count and state fields before waking up its completion handler.
581 *
582 * The buffer state is set to VIDEOBUF_DONE if no error occurred (@error is 0)
583 * or VIDEOBUF_ERROR otherwise (@error is non-zero).
584 *
585 * The DMA queue is expected to contain at least one buffer.
586 *
587 * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is
588 * empty.
589 */
590struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
591 unsigned int error)
592{
593 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
594 struct isp_video_queue *queue = video->queue;
595 enum isp_pipeline_state state;
596 struct isp_video_buffer *buf;
597 unsigned long flags;
598 struct timespec ts;
599
600 spin_lock_irqsave(&queue->irqlock, flags);
601 if (WARN_ON(list_empty(&video->dmaqueue))) {
602 spin_unlock_irqrestore(&queue->irqlock, flags);
603 return NULL;
604 }
605
606 buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
607 irqlist);
608 list_del(&buf->irqlist);
609 spin_unlock_irqrestore(&queue->irqlock, flags);
610
611 ktime_get_ts(&ts);
612 buf->vbuf.timestamp.tv_sec = ts.tv_sec;
613 buf->vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
614
615 /* Do frame number propagation only if this is the output video node.
616 * Frame number either comes from the CSI receivers or it gets
617 * incremented here if H3A is not active.
618 * Note: There is no guarantee that the output buffer will finish
619 * first, so the input number might lag behind by 1 in some cases.
620 */
621 if (video == pipe->output && !pipe->do_propagation)
622 buf->vbuf.sequence = atomic_inc_return(&pipe->frame_number);
623 else
624 buf->vbuf.sequence = atomic_read(&pipe->frame_number);
625
626 buf->state = error ? ISP_BUF_STATE_ERROR : ISP_BUF_STATE_DONE;
627
628 wake_up(&buf->wait);
629
630 if (list_empty(&video->dmaqueue)) {
631 if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
632 state = ISP_PIPELINE_QUEUE_OUTPUT
633 | ISP_PIPELINE_STREAM;
634 else
635 state = ISP_PIPELINE_QUEUE_INPUT
636 | ISP_PIPELINE_STREAM;
637
638 spin_lock_irqsave(&pipe->lock, flags);
639 pipe->state &= ~state;
640 if (video->pipe.stream_state == ISP_PIPELINE_STREAM_CONTINUOUS)
641 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
642 spin_unlock_irqrestore(&pipe->lock, flags);
643 return NULL;
644 }
645
646 if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) {
647 spin_lock_irqsave(&pipe->lock, flags);
648 pipe->state &= ~ISP_PIPELINE_STREAM;
649 spin_unlock_irqrestore(&pipe->lock, flags);
650 }
651
652 buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
653 irqlist);
654 buf->state = ISP_BUF_STATE_ACTIVE;
655 return to_isp_buffer(buf);
656}
657
658/*
659 * omap3isp_video_resume - Perform resume operation on the buffers
660 * @video: ISP video object
661 * @continuous: Pipeline is in single shot mode if 0 or continuous mode otherwise
662 *
663 * This function is intended to be used on suspend/resume scenario. It
664 * requests video queue layer to discard buffers marked as DONE if it's in
665 * continuous mode and requests ISP modules to queue again the ACTIVE buffer
666 * if there's any.
667 */
668void omap3isp_video_resume(struct isp_video *video, int continuous)
669{
670 struct isp_buffer *buf = NULL;
671
672 if (continuous && video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
673 omap3isp_video_queue_discard_done(video->queue);
674
675 if (!list_empty(&video->dmaqueue)) {
676 buf = list_first_entry(&video->dmaqueue,
677 struct isp_buffer, buffer.irqlist);
678 video->ops->queue(video, buf);
679 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
680 } else {
681 if (continuous)
682 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
683 }
684}
685
686/* -----------------------------------------------------------------------------
687 * V4L2 ioctls
688 */
689
690static int
691isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
692{
693 struct isp_video *video = video_drvdata(file);
694
695 strlcpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver));
696 strlcpy(cap->card, video->video.name, sizeof(cap->card));
697 strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
698
699 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
700 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
701 else
702 cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
703
704 return 0;
705}
706
707static int
708isp_video_get_format(struct file *file, void *fh, struct v4l2_format *format)
709{
710 struct isp_video_fh *vfh = to_isp_video_fh(fh);
711 struct isp_video *video = video_drvdata(file);
712
713 if (format->type != video->type)
714 return -EINVAL;
715
716 mutex_lock(&video->mutex);
717 *format = vfh->format;
718 mutex_unlock(&video->mutex);
719
720 return 0;
721}
722
723static int
724isp_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
725{
726 struct isp_video_fh *vfh = to_isp_video_fh(fh);
727 struct isp_video *video = video_drvdata(file);
728 struct v4l2_mbus_framefmt fmt;
729
730 if (format->type != video->type)
731 return -EINVAL;
732
733 mutex_lock(&video->mutex);
734
735 /* Fill the bytesperline and sizeimage fields by converting to media bus
736 * format and back to pixel format.
737 */
738 isp_video_pix_to_mbus(&format->fmt.pix, &fmt);
739 isp_video_mbus_to_pix(video, &fmt, &format->fmt.pix);
740
741 vfh->format = *format;
742
743 mutex_unlock(&video->mutex);
744 return 0;
745}
746
747static int
748isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
749{
750 struct isp_video *video = video_drvdata(file);
751 struct v4l2_subdev_format fmt;
752 struct v4l2_subdev *subdev;
753 u32 pad;
754 int ret;
755
756 if (format->type != video->type)
757 return -EINVAL;
758
759 subdev = isp_video_remote_subdev(video, &pad);
760 if (subdev == NULL)
761 return -EINVAL;
762
763 isp_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
764
765 fmt.pad = pad;
766 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
767 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
768 if (ret)
769 return ret == -ENOIOCTLCMD ? -EINVAL : ret;
770
771 isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
772 return 0;
773}
774
775static int
776isp_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
777{
778 struct isp_video *video = video_drvdata(file);
779 struct v4l2_subdev *subdev;
780 int ret;
781
782 subdev = isp_video_remote_subdev(video, NULL);
783 if (subdev == NULL)
784 return -EINVAL;
785
786 mutex_lock(&video->mutex);
787 ret = v4l2_subdev_call(subdev, video, cropcap, cropcap);
788 mutex_unlock(&video->mutex);
789
790 return ret == -ENOIOCTLCMD ? -EINVAL : ret;
791}
792
793static int
794isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
795{
796 struct isp_video *video = video_drvdata(file);
797 struct v4l2_subdev_format format;
798 struct v4l2_subdev *subdev;
799 u32 pad;
800 int ret;
801
802 subdev = isp_video_remote_subdev(video, &pad);
803 if (subdev == NULL)
804 return -EINVAL;
805
806 /* Try the get crop operation first and fallback to get format if not
807 * implemented.
808 */
809 ret = v4l2_subdev_call(subdev, video, g_crop, crop);
810 if (ret != -ENOIOCTLCMD)
811 return ret;
812
813 format.pad = pad;
814 format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
815 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
816 if (ret < 0)
817 return ret == -ENOIOCTLCMD ? -EINVAL : ret;
818
819 crop->c.left = 0;
820 crop->c.top = 0;
821 crop->c.width = format.format.width;
822 crop->c.height = format.format.height;
823
824 return 0;
825}
826
827static int
828isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop)
829{
830 struct isp_video *video = video_drvdata(file);
831 struct v4l2_subdev *subdev;
832 int ret;
833
834 subdev = isp_video_remote_subdev(video, NULL);
835 if (subdev == NULL)
836 return -EINVAL;
837
838 mutex_lock(&video->mutex);
839 ret = v4l2_subdev_call(subdev, video, s_crop, crop);
840 mutex_unlock(&video->mutex);
841
842 return ret == -ENOIOCTLCMD ? -EINVAL : ret;
843}
844
845static int
846isp_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a)
847{
848 struct isp_video_fh *vfh = to_isp_video_fh(fh);
849 struct isp_video *video = video_drvdata(file);
850
851 if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
852 video->type != a->type)
853 return -EINVAL;
854
855 memset(a, 0, sizeof(*a));
856 a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
857 a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
858 a->parm.output.timeperframe = vfh->timeperframe;
859
860 return 0;
861}
862
863static int
864isp_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a)
865{
866 struct isp_video_fh *vfh = to_isp_video_fh(fh);
867 struct isp_video *video = video_drvdata(file);
868
869 if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
870 video->type != a->type)
871 return -EINVAL;
872
873 if (a->parm.output.timeperframe.denominator == 0)
874 a->parm.output.timeperframe.denominator = 1;
875
876 vfh->timeperframe = a->parm.output.timeperframe;
877
878 return 0;
879}
880
881static int
882isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
883{
884 struct isp_video_fh *vfh = to_isp_video_fh(fh);
885
886 return omap3isp_video_queue_reqbufs(&vfh->queue, rb);
887}
888
889static int
890isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
891{
892 struct isp_video_fh *vfh = to_isp_video_fh(fh);
893
894 return omap3isp_video_queue_querybuf(&vfh->queue, b);
895}
896
897static int
898isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
899{
900 struct isp_video_fh *vfh = to_isp_video_fh(fh);
901
902 return omap3isp_video_queue_qbuf(&vfh->queue, b);
903}
904
905static int
906isp_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
907{
908 struct isp_video_fh *vfh = to_isp_video_fh(fh);
909
910 return omap3isp_video_queue_dqbuf(&vfh->queue, b,
911 file->f_flags & O_NONBLOCK);
912}
913
914/*
915 * Stream management
916 *
917 * Every ISP pipeline has a single input and a single output. The input can be
918 * either a sensor or a video node. The output is always a video node.
919 *
920 * As every pipeline has an output video node, the ISP video objects at the
921 * pipeline output stores the pipeline state. It tracks the streaming state of
922 * both the input and output, as well as the availability of buffers.
923 *
924 * In sensor-to-memory mode, frames are always available at the pipeline input.
925 * Starting the sensor usually requires I2C transfers and must be done in
926 * interruptible context. The pipeline is started and stopped synchronously
927 * to the stream on/off commands. All modules in the pipeline will get their
928 * subdev set stream handler called. The module at the end of the pipeline must
929 * delay starting the hardware until buffers are available at its output.
930 *
931 * In memory-to-memory mode, starting/stopping the stream requires
932 * synchronization between the input and output. ISP modules can't be stopped
933 * in the middle of a frame, and at least some of the modules seem to become
934 * busy as soon as they're started, even if they don't receive a frame start
935 * event. For that reason frames need to be processed in single-shot mode. The
936 * driver needs to wait until a frame is completely processed and written to
937 * memory before restarting the pipeline for the next frame. Pipelined
938 * processing might be possible but requires more testing.
939 *
940 * Stream start must be delayed until buffers are available at both the input
941 * and output. The pipeline must be started in the videobuf queue callback with
942 * the buffers queue spinlock held. The modules subdev set stream operation must
943 * not sleep.
944 */
945static int
946isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
947{
948 struct isp_video_fh *vfh = to_isp_video_fh(fh);
949 struct isp_video *video = video_drvdata(file);
950 enum isp_pipeline_state state;
951 struct isp_pipeline *pipe;
952 struct isp_video *far_end;
953 unsigned long flags;
954 int ret;
955
956 if (type != video->type)
957 return -EINVAL;
958
959 mutex_lock(&video->stream_lock);
960
961 if (video->streaming) {
962 mutex_unlock(&video->stream_lock);
963 return -EBUSY;
964 }
965
966 /* Start streaming on the pipeline. No link touching an entity in the
967 * pipeline can be activated or deactivated once streaming is started.
968 */
969 pipe = video->video.entity.pipe
970 ? to_isp_pipeline(&video->video.entity) : &video->pipe;
971 media_entity_pipeline_start(&video->video.entity, &pipe->pipe);
972
973 /* Verify that the currently configured format matches the output of
974 * the connected subdev.
975 */
976 ret = isp_video_check_format(video, vfh);
977 if (ret < 0)
978 goto error;
979
980 video->bpl_padding = ret;
981 video->bpl_value = vfh->format.fmt.pix.bytesperline;
982
983 /* Find the ISP video node connected at the far end of the pipeline and
984 * update the pipeline.
985 */
986 far_end = isp_video_far_end(video);
987
988 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
989 state = ISP_PIPELINE_STREAM_OUTPUT | ISP_PIPELINE_IDLE_OUTPUT;
990 pipe->input = far_end;
991 pipe->output = video;
992 } else {
993 if (far_end == NULL) {
994 ret = -EPIPE;
995 goto error;
996 }
997
998 state = ISP_PIPELINE_STREAM_INPUT | ISP_PIPELINE_IDLE_INPUT;
999 pipe->input = video;
1000 pipe->output = far_end;
1001 }
1002
1003 if (video->isp->pdata->set_constraints)
1004 video->isp->pdata->set_constraints(video->isp, true);
1005 pipe->l3_ick = clk_get_rate(video->isp->clock[ISP_CLK_L3_ICK]);
1006
1007 /* Validate the pipeline and update its state. */
1008 ret = isp_video_validate_pipeline(pipe);
1009 if (ret < 0)
1010 goto error;
1011
1012 spin_lock_irqsave(&pipe->lock, flags);
1013 pipe->state &= ~ISP_PIPELINE_STREAM;
1014 pipe->state |= state;
1015 spin_unlock_irqrestore(&pipe->lock, flags);
1016
1017 /* Set the maximum time per frame as the value requested by userspace.
1018 * This is a soft limit that can be overridden if the hardware doesn't
1019 * support the request limit.
1020 */
1021 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1022 pipe->max_timeperframe = vfh->timeperframe;
1023
1024 video->queue = &vfh->queue;
1025 INIT_LIST_HEAD(&video->dmaqueue);
1026 atomic_set(&pipe->frame_number, -1);
1027
1028 ret = omap3isp_video_queue_streamon(&vfh->queue);
1029 if (ret < 0)
1030 goto error;
1031
1032 /* In sensor-to-memory mode, the stream can be started synchronously
1033 * to the stream on command. In memory-to-memory mode, it will be
1034 * started when buffers are queued on both the input and output.
1035 */
1036 if (pipe->input == NULL) {
1037 ret = omap3isp_pipeline_set_stream(pipe,
1038 ISP_PIPELINE_STREAM_CONTINUOUS);
1039 if (ret < 0)
1040 goto error;
1041 spin_lock_irqsave(&video->queue->irqlock, flags);
1042 if (list_empty(&video->dmaqueue))
1043 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
1044 spin_unlock_irqrestore(&video->queue->irqlock, flags);
1045 }
1046
1047error:
1048 if (ret < 0) {
1049 omap3isp_video_queue_streamoff(&vfh->queue);
1050 if (video->isp->pdata->set_constraints)
1051 video->isp->pdata->set_constraints(video->isp, false);
1052 media_entity_pipeline_stop(&video->video.entity);
1053 video->queue = NULL;
1054 }
1055
1056 if (!ret)
1057 video->streaming = 1;
1058
1059 mutex_unlock(&video->stream_lock);
1060 return ret;
1061}
1062
1063static int
1064isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
1065{
1066 struct isp_video_fh *vfh = to_isp_video_fh(fh);
1067 struct isp_video *video = video_drvdata(file);
1068 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
1069 enum isp_pipeline_state state;
1070 unsigned int streaming;
1071 unsigned long flags;
1072
1073 if (type != video->type)
1074 return -EINVAL;
1075
1076 mutex_lock(&video->stream_lock);
1077
1078 /* Make sure we're not streaming yet. */
1079 mutex_lock(&vfh->queue.lock);
1080 streaming = vfh->queue.streaming;
1081 mutex_unlock(&vfh->queue.lock);
1082
1083 if (!streaming)
1084 goto done;
1085
1086 /* Update the pipeline state. */
1087 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1088 state = ISP_PIPELINE_STREAM_OUTPUT
1089 | ISP_PIPELINE_QUEUE_OUTPUT;
1090 else
1091 state = ISP_PIPELINE_STREAM_INPUT
1092 | ISP_PIPELINE_QUEUE_INPUT;
1093
1094 spin_lock_irqsave(&pipe->lock, flags);
1095 pipe->state &= ~state;
1096 spin_unlock_irqrestore(&pipe->lock, flags);
1097
1098 /* Stop the stream. */
1099 omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_STOPPED);
1100 omap3isp_video_queue_streamoff(&vfh->queue);
1101 video->queue = NULL;
1102 video->streaming = 0;
1103
1104 if (video->isp->pdata->set_constraints)
1105 video->isp->pdata->set_constraints(video->isp, false);
1106 media_entity_pipeline_stop(&video->video.entity);
1107
1108done:
1109 mutex_unlock(&video->stream_lock);
1110 return 0;
1111}
1112
1113static int
1114isp_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
1115{
1116 if (input->index > 0)
1117 return -EINVAL;
1118
1119 strlcpy(input->name, "camera", sizeof(input->name));
1120 input->type = V4L2_INPUT_TYPE_CAMERA;
1121
1122 return 0;
1123}
1124
1125static int
1126isp_video_g_input(struct file *file, void *fh, unsigned int *input)
1127{
1128 *input = 0;
1129
1130 return 0;
1131}
1132
1133static int
1134isp_video_s_input(struct file *file, void *fh, unsigned int input)
1135{
1136 return input == 0 ? 0 : -EINVAL;
1137}
1138
1139static const struct v4l2_ioctl_ops isp_video_ioctl_ops = {
1140 .vidioc_querycap = isp_video_querycap,
1141 .vidioc_g_fmt_vid_cap = isp_video_get_format,
1142 .vidioc_s_fmt_vid_cap = isp_video_set_format,
1143 .vidioc_try_fmt_vid_cap = isp_video_try_format,
1144 .vidioc_g_fmt_vid_out = isp_video_get_format,
1145 .vidioc_s_fmt_vid_out = isp_video_set_format,
1146 .vidioc_try_fmt_vid_out = isp_video_try_format,
1147 .vidioc_cropcap = isp_video_cropcap,
1148 .vidioc_g_crop = isp_video_get_crop,
1149 .vidioc_s_crop = isp_video_set_crop,
1150 .vidioc_g_parm = isp_video_get_param,
1151 .vidioc_s_parm = isp_video_set_param,
1152 .vidioc_reqbufs = isp_video_reqbufs,
1153 .vidioc_querybuf = isp_video_querybuf,
1154 .vidioc_qbuf = isp_video_qbuf,
1155 .vidioc_dqbuf = isp_video_dqbuf,
1156 .vidioc_streamon = isp_video_streamon,
1157 .vidioc_streamoff = isp_video_streamoff,
1158 .vidioc_enum_input = isp_video_enum_input,
1159 .vidioc_g_input = isp_video_g_input,
1160 .vidioc_s_input = isp_video_s_input,
1161};
1162
1163/* -----------------------------------------------------------------------------
1164 * V4L2 file operations
1165 */
1166
1167static int isp_video_open(struct file *file)
1168{
1169 struct isp_video *video = video_drvdata(file);
1170 struct isp_video_fh *handle;
1171 int ret = 0;
1172
1173 handle = kzalloc(sizeof(*handle), GFP_KERNEL);
1174 if (handle == NULL)
1175 return -ENOMEM;
1176
1177 v4l2_fh_init(&handle->vfh, &video->video);
1178 v4l2_fh_add(&handle->vfh);
1179
1180 /* If this is the first user, initialise the pipeline. */
1181 if (omap3isp_get(video->isp) == NULL) {
1182 ret = -EBUSY;
1183 goto done;
1184 }
1185
1186 ret = omap3isp_pipeline_pm_use(&video->video.entity, 1);
1187 if (ret < 0) {
1188 omap3isp_put(video->isp);
1189 goto done;
1190 }
1191
1192 omap3isp_video_queue_init(&handle->queue, video->type,
1193 &isp_video_queue_ops, video->isp->dev,
1194 sizeof(struct isp_buffer));
1195
1196 memset(&handle->format, 0, sizeof(handle->format));
1197 handle->format.type = video->type;
1198 handle->timeperframe.denominator = 1;
1199
1200 handle->video = video;
1201 file->private_data = &handle->vfh;
1202
1203done:
1204 if (ret < 0) {
1205 v4l2_fh_del(&handle->vfh);
1206 kfree(handle);
1207 }
1208
1209 return ret;
1210}
1211
1212static int isp_video_release(struct file *file)
1213{
1214 struct isp_video *video = video_drvdata(file);
1215 struct v4l2_fh *vfh = file->private_data;
1216 struct isp_video_fh *handle = to_isp_video_fh(vfh);
1217
1218 /* Disable streaming and free the buffers queue resources. */
1219 isp_video_streamoff(file, vfh, video->type);
1220
1221 mutex_lock(&handle->queue.lock);
1222 omap3isp_video_queue_cleanup(&handle->queue);
1223 mutex_unlock(&handle->queue.lock);
1224
1225 omap3isp_pipeline_pm_use(&video->video.entity, 0);
1226
1227 /* Release the file handle. */
1228 v4l2_fh_del(vfh);
1229 kfree(handle);
1230 file->private_data = NULL;
1231
1232 omap3isp_put(video->isp);
1233
1234 return 0;
1235}
1236
1237static unsigned int isp_video_poll(struct file *file, poll_table *wait)
1238{
1239 struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
1240 struct isp_video_queue *queue = &vfh->queue;
1241
1242 return omap3isp_video_queue_poll(queue, file, wait);
1243}
1244
1245static int isp_video_mmap(struct file *file, struct vm_area_struct *vma)
1246{
1247 struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
1248
1249 return omap3isp_video_queue_mmap(&vfh->queue, vma);
1250}
1251
1252static struct v4l2_file_operations isp_video_fops = {
1253 .owner = THIS_MODULE,
1254 .unlocked_ioctl = video_ioctl2,
1255 .open = isp_video_open,
1256 .release = isp_video_release,
1257 .poll = isp_video_poll,
1258 .mmap = isp_video_mmap,
1259};
1260
1261/* -----------------------------------------------------------------------------
1262 * ISP video core
1263 */
1264
1265static const struct isp_video_operations isp_video_dummy_ops = {
1266};
1267
1268int omap3isp_video_init(struct isp_video *video, const char *name)
1269{
1270 const char *direction;
1271 int ret;
1272
1273 switch (video->type) {
1274 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1275 direction = "output";
1276 video->pad.flags = MEDIA_PAD_FL_SINK;
1277 break;
1278 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1279 direction = "input";
1280 video->pad.flags = MEDIA_PAD_FL_SOURCE;
1281 break;
1282
1283 default:
1284 return -EINVAL;
1285 }
1286
1287 ret = media_entity_init(&video->video.entity, 1, &video->pad, 0);
1288 if (ret < 0)
1289 return ret;
1290
1291 mutex_init(&video->mutex);
1292 atomic_set(&video->active, 0);
1293
1294 spin_lock_init(&video->pipe.lock);
1295 mutex_init(&video->stream_lock);
1296
1297 /* Initialize the video device. */
1298 if (video->ops == NULL)
1299 video->ops = &isp_video_dummy_ops;
1300
1301 video->video.fops = &isp_video_fops;
1302 snprintf(video->video.name, sizeof(video->video.name),
1303 "OMAP3 ISP %s %s", name, direction);
1304 video->video.vfl_type = VFL_TYPE_GRABBER;
1305 video->video.release = video_device_release_empty;
1306 video->video.ioctl_ops = &isp_video_ioctl_ops;
1307 video->pipe.stream_state = ISP_PIPELINE_STREAM_STOPPED;
1308
1309 video_set_drvdata(&video->video, video);
1310
1311 return 0;
1312}
1313
1314int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
1315{
1316 int ret;
1317
1318 video->video.v4l2_dev = vdev;
1319
1320 ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
1321 if (ret < 0)
1322 printk(KERN_ERR "%s: could not register video device (%d)\n",
1323 __func__, ret);
1324
1325 return ret;
1326}
1327
1328void omap3isp_video_unregister(struct isp_video *video)
1329{
1330 if (video_is_registered(&video->video)) {
1331 media_entity_cleanup(&video->video.entity);
1332 video_unregister_device(&video->video);
1333 }
1334}
diff --git a/drivers/media/video/omap3isp/ispvideo.h b/drivers/media/video/omap3isp/ispvideo.h
new file mode 100644
index 00000000000..53160aa24e6
--- /dev/null
+++ b/drivers/media/video/omap3isp/ispvideo.h
@@ -0,0 +1,204 @@
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 * @bpp: Bits per pixel
55 */
56struct isp_format_info {
57 enum v4l2_mbus_pixelcode code;
58 enum v4l2_mbus_pixelcode truncated;
59 enum v4l2_mbus_pixelcode uncompressed;
60 enum v4l2_mbus_pixelcode flavor;
61 u32 pixelformat;
62 unsigned int bpp;
63};
64
65enum isp_pipeline_stream_state {
66 ISP_PIPELINE_STREAM_STOPPED = 0,
67 ISP_PIPELINE_STREAM_CONTINUOUS = 1,
68 ISP_PIPELINE_STREAM_SINGLESHOT = 2,
69};
70
71enum isp_pipeline_state {
72 /* The stream has been started on the input video node. */
73 ISP_PIPELINE_STREAM_INPUT = 1,
74 /* The stream has been started on the output video node. */
75 ISP_PIPELINE_STREAM_OUTPUT = 2,
76 /* At least one buffer is queued on the input video node. */
77 ISP_PIPELINE_QUEUE_INPUT = 4,
78 /* At least one buffer is queued on the output video node. */
79 ISP_PIPELINE_QUEUE_OUTPUT = 8,
80 /* The input entity is idle, ready to be started. */
81 ISP_PIPELINE_IDLE_INPUT = 16,
82 /* The output entity is idle, ready to be started. */
83 ISP_PIPELINE_IDLE_OUTPUT = 32,
84 /* The pipeline is currently streaming. */
85 ISP_PIPELINE_STREAM = 64,
86};
87
88struct isp_pipeline {
89 struct media_pipeline pipe;
90 spinlock_t lock; /* Pipeline state and queue flags */
91 unsigned int state;
92 enum isp_pipeline_stream_state stream_state;
93 struct isp_video *input;
94 struct isp_video *output;
95 unsigned long l3_ick;
96 unsigned int max_rate;
97 atomic_t frame_number;
98 bool do_propagation; /* of frame number */
99 struct v4l2_fract max_timeperframe;
100};
101
102#define to_isp_pipeline(__e) \
103 container_of((__e)->pipe, struct isp_pipeline, pipe)
104
105static inline int isp_pipeline_ready(struct isp_pipeline *pipe)
106{
107 return pipe->state == (ISP_PIPELINE_STREAM_INPUT |
108 ISP_PIPELINE_STREAM_OUTPUT |
109 ISP_PIPELINE_QUEUE_INPUT |
110 ISP_PIPELINE_QUEUE_OUTPUT |
111 ISP_PIPELINE_IDLE_INPUT |
112 ISP_PIPELINE_IDLE_OUTPUT);
113}
114
115/*
116 * struct isp_buffer - ISP buffer
117 * @buffer: ISP video buffer
118 * @isp_addr: MMU mapped address (a.k.a. device address) of the buffer.
119 */
120struct isp_buffer {
121 struct isp_video_buffer buffer;
122 dma_addr_t isp_addr;
123};
124
125#define to_isp_buffer(buf) container_of(buf, struct isp_buffer, buffer)
126
127enum isp_video_dmaqueue_flags {
128 /* Set if DMA queue becomes empty when ISP_PIPELINE_STREAM_CONTINUOUS */
129 ISP_VIDEO_DMAQUEUE_UNDERRUN = (1 << 0),
130 /* Set when queuing buffer to an empty DMA queue */
131 ISP_VIDEO_DMAQUEUE_QUEUED = (1 << 1),
132};
133
134#define isp_video_dmaqueue_flags_clr(video) \
135 ({ (video)->dmaqueue_flags = 0; })
136
137/*
138 * struct isp_video_operations - ISP video operations
139 * @queue: Resume streaming when a buffer is queued. Called on VIDIOC_QBUF
140 * if there was no buffer previously queued.
141 */
142struct isp_video_operations {
143 int(*queue)(struct isp_video *video, struct isp_buffer *buffer);
144};
145
146struct isp_video {
147 struct video_device video;
148 enum v4l2_buf_type type;
149 struct media_pad pad;
150
151 struct mutex mutex; /* format and crop settings */
152 atomic_t active;
153
154 struct isp_device *isp;
155
156 unsigned int capture_mem;
157 unsigned int bpl_alignment; /* alignment value */
158 unsigned int bpl_zero_padding; /* whether the alignment is optional */
159 unsigned int bpl_max; /* maximum bytes per line value */
160 unsigned int bpl_value; /* bytes per line value */
161 unsigned int bpl_padding; /* padding at end of line */
162
163 /* Entity video node streaming */
164 unsigned int streaming:1;
165
166 /* Pipeline state */
167 struct isp_pipeline pipe;
168 struct mutex stream_lock; /* pipeline and stream states */
169
170 /* Video buffers queue */
171 struct isp_video_queue *queue;
172 struct list_head dmaqueue;
173 enum isp_video_dmaqueue_flags dmaqueue_flags;
174
175 const struct isp_video_operations *ops;
176};
177
178#define to_isp_video(vdev) container_of(vdev, struct isp_video, video)
179
180struct isp_video_fh {
181 struct v4l2_fh vfh;
182 struct isp_video *video;
183 struct isp_video_queue queue;
184 struct v4l2_format format;
185 struct v4l2_fract timeperframe;
186};
187
188#define to_isp_video_fh(fh) container_of(fh, struct isp_video_fh, vfh)
189#define isp_video_queue_to_isp_video_fh(q) \
190 container_of(q, struct isp_video_fh, queue)
191
192int omap3isp_video_init(struct isp_video *video, const char *name);
193int omap3isp_video_register(struct isp_video *video,
194 struct v4l2_device *vdev);
195void omap3isp_video_unregister(struct isp_video *video);
196struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
197 unsigned int error);
198void omap3isp_video_resume(struct isp_video *video, int continuous);
199struct media_pad *omap3isp_video_remote_pad(struct isp_video *video);
200
201const struct isp_format_info *
202omap3isp_video_format_info(enum v4l2_mbus_pixelcode code);
203
204#endif /* OMAP3_ISP_VIDEO_H */
diff --git a/drivers/media/video/omap3isp/luma_enhance_table.h b/drivers/media/video/omap3isp/luma_enhance_table.h
new file mode 100644
index 00000000000..098b45e2280
--- /dev/null
+++ b/drivers/media/video/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/video/omap3isp/noise_filter_table.h b/drivers/media/video/omap3isp/noise_filter_table.h
new file mode 100644
index 00000000000..d50451a4a24
--- /dev/null
+++ b/drivers/media/video/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