[Meego-kernel] [MFLD Camera - PATCH v3 3/9] ISP v4l2 driver based on v4l2 API and framework implemenation on MFLD platform.

Zhang, Xiaolin xiaolin.zhang at intel.com
Wed Dec 1 10:52:17 PST 2010


>From 95425dd8183b036664937fbb2110dda2537afbe3 Mon Sep 17 00:00:00 2001
From: Xiaolin Zhang <xiaolin.zhang at intel.com>
Date: Wed, 1 Dec 2010 21:41:39 +0800
Subject: [MFLD Camera - PATCH v3 3/9] ISP v4l2 driver based on v4l2 API and framework implemenation on MFLD platform.

Signed-off-by: Xiaolin Zhang <xiaolin.zhang at intel.com>
---
 .../mfld_ci/mfldisp/include/mfldisp/ispparam.h     |  354 ++
 .../mfldisp/include/mfldisp/mfldisp_internal.h     |  134 +
 .../mfldisp/include/mfldisp/mfldisp_sensor.h       |   67 +
 .../mfld_ci/mfldisp/include/mfldisp/mfldisp_v4l2.h |  239 ++
 drivers/media/video/mfld_ci/mfldisp/mfldisp_v4l2.c | 4335 ++++++++++++++++++++
 5 files changed, 5129 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/mfld_ci/mfldisp/include/mfldisp/ispparam.h
 create mode 100644 drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_internal.h
 create mode 100644 drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_sensor.h
 create mode 100644 drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_v4l2.h
 create mode 100644 drivers/media/video/mfld_ci/mfldisp/mfldisp_v4l2.c

diff --git a/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/ispparam.h b/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/ispparam.h
new file mode 100644
index 0000000..fb077e6
--- /dev/null
+++ b/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/ispparam.h
@@ -0,0 +1,354 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+/*
+ * structure for handling ISP parameters,
+ *
+ * this structure will shared both in kernel/user space
+ */
+#ifndef        ISP_PARAM_H_
+#define        ISP_PARAM_H_
+
+unsigned short default_gamma_table[sh_css_gamma_table_size] = {
+       0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16,
+       17, 18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 31, 32, 33, 35, 36,
+       38, 39, 41, 42, 44, 45, 47, 48, 49, 51, 52, 54, 55, 57, 58, 60,
+       61, 62, 64, 65, 66, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79,
+       80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 93, 94,
+       95, 96, 97, 98, 98, 99, 100, 101, 102, 102, 103, 104, 105, 105, 106,
+       107,
+       108, 108, 109, 110, 110, 111, 112, 112, 113, 114, 114, 115, 116, 116,
+       117, 118,
+       118, 119, 120, 120, 121, 121, 122, 123, 123, 124, 125, 125, 126, 126,
+       127, 127,               /* 128 */
+       128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 134, 134, 135, 135,
+       136, 136,
+       137, 137, 138, 138, 139, 139, 140, 140, 141, 141, 142, 142, 143, 143,
+       144, 144,
+       145, 145, 145, 146, 146, 147, 147, 148, 148, 149, 149, 150, 150, 150,
+       151, 151,
+       152, 152, 152, 153, 153, 154, 154, 155, 155, 155, 156, 156, 156, 157,
+       157, 158,
+       158, 158, 159, 159, 160, 160, 160, 161, 161, 161, 162, 162, 162, 163,
+       163, 163,
+       164, 164, 164, 165, 165, 165, 166, 166, 166, 167, 167, 167, 168, 168,
+       168, 169,
+       169, 169, 170, 170, 170, 170, 171, 171, 171, 172, 172, 172, 172, 173,
+       173, 173,
+       174, 174, 174, 174, 175, 175, 175, 176, 176, 176, 176, 177, 177, 177,
+       177, 178,               /* 256 */
+       178, 178, 178, 179, 179, 179, 179, 180, 180, 180, 180, 181, 181, 181,
+       181, 182,
+       182, 182, 182, 182, 183, 183, 183, 183, 184, 184, 184, 184, 184, 185,
+       185, 185,
+       185, 186, 186, 186, 186, 186, 187, 187, 187, 187, 187, 188, 188, 188,
+       188, 188,
+       189, 189, 189, 189, 189, 190, 190, 190, 190, 190, 191, 191, 191, 191,
+       191, 192,
+       192, 192, 192, 192, 192, 193, 193, 193, 193, 193, 194, 194, 194, 194,
+       194, 194,
+       195, 195, 195, 195, 195, 195, 196, 196, 196, 196, 196, 196, 197, 197,
+       197, 197,
+       197, 197, 198, 198, 198, 198, 198, 198, 198, 199, 199, 199, 199, 199,
+       199, 200,
+       200, 200, 200, 200, 200, 200, 201, 201, 201, 201, 201, 201, 201, 202,
+       202, 202,               /* 384 */
+       202, 202, 202, 202, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204,
+       204, 204,
+       204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 206, 206, 206,
+       206, 206,
+       206, 206, 206, 207, 207, 207, 207, 207, 207, 207, 207, 208, 208, 208,
+       208, 208,
+       208, 208, 208, 209, 209, 209, 209, 209, 209, 209, 209, 209, 210, 210,
+       210, 210,
+       210, 210, 210, 210, 210, 211, 211, 211, 211, 211, 211, 211, 211, 211,
+       212, 212,
+       212, 212, 212, 212, 212, 212, 212, 213, 213, 213, 213, 213, 213, 213,
+       213, 213,
+       214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 215, 215, 215, 215,
+       215, 215,
+       215, 215, 215, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 217,
+       217, 217,               /* 512 */
+       217, 217, 217, 217, 217, 217, 217, 218, 218, 218, 218, 218, 218, 218,
+       218, 218,
+       218, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 220, 220, 220,
+       220, 220,
+       220, 220, 220, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+       221, 221,
+       222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 223, 223, 223, 223,
+       223, 223,
+       223, 223, 223, 223, 223, 224, 224, 224, 224, 224, 224, 224, 224, 224,
+       224, 224,
+       225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 226, 226, 226,
+       226, 226,
+       226, 226, 226, 226, 226, 226, 226, 227, 227, 227, 227, 227, 227, 227,
+       227, 227,
+       227, 227, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
+       229, 229,
+       229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 230, 230, 230, 230,
+       230, 230,
+       230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231,
+       231, 231,
+       231, 231, 231, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+       232, 233,
+       233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 234, 234,
+       234, 234,
+       234, 234, 234, 234, 234, 234, 234, 234, 234, 235, 235, 235, 235, 235,
+       235, 235,
+       235, 235, 235, 235, 235, 235, 236, 236, 236, 236, 236, 236, 236, 236,
+       236, 236,
+       236, 236, 236, 236, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237,
+       237, 237,
+       237, 237, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
+       238, 238,
+       239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
+       240, 240,
+       240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 241, 241,
+       241, 241,
+       241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 242, 242, 242,
+       242, 242,
+       242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 243, 243,
+       243, 243,
+       243, 243, 243, 243, 243, 243, 243, 243, 243, 244, 244, 244, 244, 244,
+       244, 244,
+       244, 244, 244, 244, 244, 244, 244, 244, 245, 245, 245, 245, 245, 245,
+       245, 245,
+       245, 245, 245, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246,
+       246, 246,
+       246, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 247, 247, 247,
+       247, 247,
+       247, 247, 247, 247, 247, 247, 247, 248, 248, 248, 248, 248, 248, 248,
+       248, 248,
+       248, 248, 248, 248, 248, 248, 248, 249, 249, 249, 249, 249, 249, 249,
+       249, 249,
+       249, 249, 249, 249, 249, 249, 249, 250, 250, 250, 250, 250, 250, 250,
+       250, 250,
+       250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, 251, 251,
+       251, 251,
+       251, 251, 251, 251, 251, 251, 251, 252, 252, 252, 252, 252, 252, 252,
+       252, 252,
+       252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253,
+       253, 253,
+       253, 253, 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254,
+       254, 254,
+       254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255,
+       255, 255
+};
+
+unsigned short default_ctc_table[sh_css_ctc_table_size] = {
+       0, 0, 256, 384, 384, 497, 765, 806, 837, 851, 888, 901, 957, 981, 993,
+       1001,
+       1011, 1029, 1028, 1039, 1062, 1059, 1073, 1080, 1083, 1085, 1085, 1098,
+       1080, 1084, 1085, 1093,
+       1078, 1073, 1070, 1069, 1077, 1066, 1072, 1063, 1053, 1044, 1046, 1053,
+       1039, 1028, 1025, 1024,
+       1012, 1013, 1016, 996, 992, 990, 990, 980, 969, 968, 961, 955, 951, 949,
+       933, 930,
+       929, 925, 921, 916, 906, 901, 895, 893, 886, 877, 872, 869, 866, 861,
+       857, 849,
+       845, 838, 836, 832, 823, 821, 815, 813, 809, 805, 796, 793, 790, 785,
+       784, 778,
+       772, 768, 766, 763, 758, 752, 749, 745, 741, 740, 736, 730, 726, 724,
+       723, 718,
+       711, 709, 706, 704, 701, 698, 691, 689, 688, 683, 683, 678, 675, 673,
+       671, 669,
+       666, 663, 661, 660, 656, 656, 653, 650, 648, 647, 646, 643, 639, 638,
+       637, 635,
+       633, 632, 629, 627, 626, 625, 622, 621, 618, 618, 614, 614, 612, 609,
+       606, 606,
+       603, 600, 600, 597, 594, 591, 590, 586, 582, 581, 578, 575, 572, 569,
+       563, 560,
+       557, 554, 551, 548, 545, 539, 536, 533, 529, 527, 524, 519, 516, 513,
+       510, 507,
+       504, 501, 498, 493, 491, 488, 485, 484, 480, 476, 474, 471, 467, 466,
+       464, 460,
+       459, 455, 453, 449, 447, 446, 443, 441, 438, 435, 432, 432, 429, 427,
+       426, 422,
+       419, 418, 416, 414, 412, 410, 408, 406, 404, 402, 401, 398, 397, 395,
+       393, 390,
+       389, 388, 387, 384, 382, 380, 378, 377, 376, 375, 372, 370, 368, 368,
+       366, 364,
+       363, 361, 360, 358, 357, 355, 354, 352, 351, 350, 349, 346, 345, 344,
+       344, 342,
+       340, 339, 337, 337, 336, 335, 333, 331, 330, 329, 328, 326, 326, 324,
+       324, 322,
+       321, 320, 318, 318, 318, 317, 315, 313, 312, 311, 311, 310, 308, 307,
+       306, 306,
+       304, 304, 302, 301, 300, 300, 299, 297, 297, 296, 296, 294, 294, 292,
+       291, 291,
+       291, 290, 288, 287, 286, 286, 287, 285, 284, 283, 282, 282, 281, 281,
+       279, 278,
+       278, 278, 276, 276, 275, 274, 274, 273, 271, 270, 269, 268, 268, 267,
+       265, 262,
+       261, 260, 260, 259, 257, 254, 252, 252, 251, 251, 249, 246, 245, 244,
+       243, 242,
+       240, 239, 239, 237, 235, 235, 233, 231, 232, 230, 229, 226, 225, 224,
+       225, 224,
+       223, 220, 219, 219, 218, 217, 217, 214, 213, 213, 212, 211, 209, 209,
+       209, 208,
+       206, 205, 204, 203, 204, 203, 201, 200, 199, 197, 198, 198, 197, 195,
+       194, 194,
+       193, 192, 192, 191, 189, 190, 189, 188, 186, 187, 186, 185, 185, 184,
+       183, 181,
+       183, 182, 181, 180, 179, 178, 178, 178, 177, 176, 175, 176, 175, 174,
+       174, 173,
+       172, 173, 172, 171, 170, 170, 169, 169, 169, 168, 167, 166, 167, 167,
+       166, 165,
+       164, 164, 164, 163, 164, 163, 162, 163, 162, 161, 160, 161, 160, 160,
+       160, 159,
+       158, 157, 158, 158, 157, 157, 156, 156, 156, 156, 155, 155, 154, 154,
+       154, 154,
+       154, 153, 152, 153, 152, 152, 151, 152, 151, 152, 151, 150, 150, 149,
+       149, 150,
+       149, 149, 148, 148, 148, 149, 148, 147, 146, 146, 147, 146, 147, 146,
+       145, 146,
+       146, 145, 144, 145, 144, 145, 144, 144, 143, 143, 143, 144, 143, 142,
+       142, 142,
+       142, 142, 142, 141, 141, 141, 141, 140, 140, 141, 140, 140, 141, 140,
+       139, 139,
+       139, 140, 139, 139, 138, 138, 137, 139, 138, 138, 138, 137, 138, 137,
+       137, 137,
+       137, 136, 137, 136, 136, 136, 136, 135, 136, 135, 135, 135, 135, 136,
+       135, 135,
+       134, 134, 133, 135, 134, 134, 134, 133, 134, 133, 134, 133, 133, 132,
+       133, 133,
+       132, 133, 132, 132, 132, 132, 131, 131, 131, 132, 131, 131, 130, 131,
+       130, 132,
+       131, 130, 130, 129, 130, 129, 130, 129, 129, 129, 130, 129, 128, 128,
+       128, 128,
+       129, 128, 128, 127, 127, 128, 128, 127, 127, 126, 126, 127, 127, 126,
+       126, 126,
+       127, 126, 126, 126, 125, 125, 126, 125, 125, 124, 124, 124, 125, 125,
+       124, 124,
+       123, 124, 124, 123, 123, 122, 122, 122, 122, 122, 121, 120, 120, 119,
+       118, 118,
+       118, 117, 117, 116, 115, 115, 115, 114, 114, 113, 113, 112, 111, 111,
+       111, 110,
+       110, 109, 109, 108, 108, 108, 107, 107, 106, 106, 105, 105, 105, 104,
+       104, 103,
+       103, 102, 102, 102, 102, 101, 101, 100, 100, 99, 99, 99, 99, 99, 99, 98,
+       97, 98, 97, 97, 97, 96, 96, 95, 96, 95, 96, 95, 95, 94, 94, 95,
+       94, 94, 94, 93, 93, 92, 93, 93, 93, 93, 92, 92, 91, 92, 92, 92,
+       91, 91, 90, 90, 91, 91, 91, 90, 90, 90, 90, 91, 90, 90, 90, 89,
+       89, 89, 90, 89, 89, 89, 89, 89, 88, 89, 89, 88, 88, 88, 88, 87,
+       89, 88, 88, 88, 88, 88, 87, 88, 88, 88, 87, 87, 87, 87, 87, 88,
+       87, 87, 87, 87, 87, 87, 88, 87, 87, 87, 87, 86, 86, 87, 87, 87,
+       87, 86, 86, 86, 87, 87, 86, 87, 86, 86, 86, 87, 87, 86, 86, 86,
+       86, 86, 87, 87, 86, 85, 85, 85, 84, 85, 85, 84, 84, 83, 83, 82,
+       82, 82, 81, 81, 80, 79, 79, 79, 78, 77, 77, 76, 76, 76, 75, 74,
+       74, 74, 73, 73, 72, 71, 71, 71, 70, 70, 69, 69, 68, 68, 67, 67,
+       67, 66, 66, 65, 65, 64, 64, 63, 62, 62, 62, 61, 60, 60, 59, 59,
+       58, 58, 57, 57, 56, 56, 56, 55, 55, 54, 55, 55, 54, 53, 53, 52,
+       53, 53, 52, 51, 51, 50, 51, 50, 49, 49, 50, 49, 49, 48, 48, 47,
+       47, 48, 46, 45, 45, 45, 46, 45, 45, 44, 45, 45, 45, 43, 42, 42,
+       41, 43, 41, 40, 40, 39, 40, 41, 39, 39, 39, 39, 39, 38, 35, 35,
+       34, 37, 36, 34, 33, 33, 33, 35, 34, 32, 32, 31, 32, 30, 29, 26,
+       25, 25, 27, 26, 23, 23, 23, 25, 24, 24, 22, 21, 20, 19, 16, 14,
+       13, 13, 13, 10, 9, 7, 7, 7, 12, 12, 12, 7, 0, 0, 0, 0
+};
+
+/* multiple axis color correction table, 64values = 2x2matrix
+ * for 16area, 1value per 16bit */
+const short default_macc_table[sh_css_num_macc_axes * 4] = {
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256
+};
+
+const short blue_macc_table[sh_css_num_macc_axes * 4] = {
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256
+};
+
+const short green_macc_table[sh_css_num_macc_axes * 4] = {
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256
+};
+
+const short skin_macc_table[sh_css_num_macc_axes * 4] = {
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256,
+       256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256
+};
+
+struct sh_css_isp_cc_config default_cc_config = {
+       .fraction_bits = 8,
+       .matrix = {255, 29, 120, 0, -374, -342, 0, -672, 301},
+};
+
+struct hCss_isp_cc_config sepia_cc_config = {
+       .fraction_bits = 8,
+       .matrix = {255, 29, 120, 0, -374, -342, 0, -672, 301},
+};
+
+struct sh_css_isp_cc_config negative_cc_config = {
+       .fraction_bits = 8,
+       .matrix = {255, 29, 120, 0, -374, -342, 0, -672, 301},
+};
+
+struct sh_css_isp_cc_config mono_cc_config = {
+       .fraction_bits = 8,
+       .matrix = {255, 29, 120, 0, -374, -342, 0, -672, 301},
+};
+
+struct sh_css_isp_tnr_config default_tnr_config = {
+       .gain = 32768,
+       .threshold_y = 32,
+       .threshold_uv = 32,
+};
+
+struct sh_css_isp_ob_config default_ob_config = {
+       .mode = sh_css_isp_ob_mode_none,
+       .level_gr = 0,
+       .level_r = 0,
+       .level_b = 0,
+       .level_gb = 0,
+       .start_position = 0,
+       .end_position = 0
+};
+
+struct sh_css_isp_nr_config default_nr_config = {
+       .gain = 16384,
+       .direction = 1280,
+       .threshold_cb = 0,
+       .threshold_cr = 0
+};
+
+struct sh_css_isp_ee_config default_ee_config = {
+       .gain = 8192,
+       .threshold = 128,
+       .detail_gain = 2048
+};
+
+struct sh_css_isp_dp_config default_dp_config = {
+       .threshold = 8192,
+       .gain = 2048
+};
+
+#endif /* ISP_PARAM_H_ */
diff --git a/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_internal.h b/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_internal.h
new file mode 100644
index 0000000..cc389bf
--- /dev/null
+++ b/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_internal.h
@@ -0,0 +1,134 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#ifndef MFLDISP_INTERNAL_H_
+#define MFLDISP_INTERNAL_H_
+
+#include <linux/kernel.h>
+
+#define LOG_LENGTH     100
+#define ISP_NAME       "atomisp"
+#define mfld_isp_dbg(level, fmt, arg...) do {\
+       if (!(strcmp(level, KERN_INFO)) || \
+               !(strcmp(level, KERN_ERR))) {\
+               printk(level "%s: " fmt, "atomisp", ##arg); \
+       } \
+} while (0)
+
+extern void hrt_isp_css_mm_set_user_ptr(unsigned int userptr,
+                                       unsigned int num_pages);
+#ifdef USE_DYNAMIC_BIN
+#define HIVE_ADDR_sp_dma_proxy_run_entry 0x767
+#define HIVE_ADDR_sp_dma_proxy_init_entry 0xC42
+#define HIVE_ADDR_super_impose_offline_entry 0x543
+#define HIVE_ADDR_sp_gen_histogram_entry 0x420
+#define HIVE_ADDR_copy_frame_entry 0x2CD
+#define HIVE_ADDR_sp_bin_copy_entry 0x250
+#define HIVE_ADDR_sp_start_isp_entry 0x0
+
+#define _hrt_transfer_embedded_sp(code_func, data_func, bss_func, \
+       view_table_func, args...) \
+{\
+code_func(0x0, 0x0, 0x1E5F0, ## args);\
+data_func(scalar_processor_dmem, 0x4, 0x1E5F0, 0x2A1, ## args);\
+bss_func(scalar_processor_dmem, 0x2A8, 0x3860, ## args);\
+}
+
+
+extern char *_hrt_blob_sp;
+extern char *_hrt_blob_isp_bayer_ds_var;
+extern char *_hrt_blob_isp_copy_var;
+extern char *_hrt_blob_isp_primary_16mp;
+extern char *_hrt_blob_isp_primary_14mp;
+extern char *_hrt_blob_isp_primary_var;
+extern char *_hrt_blob_isp_primary_ds;
+extern char *_hrt_blob_isp_primary_small;
+extern char *_hrt_blob_isp_preview_var;
+extern char *_hrt_blob_isp_preview_ds;
+extern char *_hrt_blob_isp_video_online;
+extern char *_hrt_blob_isp_video_online_nodz;
+extern char *_hrt_blob_isp_video_online_ds;
+extern char *_hrt_blob_isp_video_offline;
+extern char *_hrt_blob_isp_xnr_var;
+extern char *_hrt_blob_isp_pregdc_var;
+extern char *_hrt_blob_isp_gdc_var;
+extern char *_hrt_blob_isp_postgdc_var;
+extern char *_hrt_blob_isp_vf_pp;
+
+extern unsigned int _hrt_text_size_of_sp;
+extern unsigned int _hrt_size_of_sp;
+
+extern unsigned int _hrt_text_size_of_isp_bayer_ds_var;
+extern unsigned int _hrt_size_of_isp_bayer_ds_var;
+
+extern unsigned int _hrt_text_size_of_isp_copy_var;
+extern unsigned int _hrt_size_of_isp_copy_var;
+
+extern unsigned int _hrt_text_size_of_isp_gdc_var;
+extern unsigned int _hrt_size_of_isp_gdc_var;
+
+extern unsigned int _hrt_text_size_of_isp_postgdc_var;
+extern unsigned int _hrt_size_of_isp_postgdc_var;
+
+extern unsigned int _hrt_text_size_of_isp_pregdc_var;
+extern unsigned int _hrt_size_of_isp_pregdc_var;
+
+extern unsigned int _hrt_text_size_of_isp_preview_ds;
+extern unsigned int _hrt_size_of_isp_preview_ds;
+
+extern unsigned int _hrt_text_size_of_isp_preview_var;
+extern unsigned int _hrt_size_of_isp_preview_var;
+
+extern unsigned int _hrt_text_size_of_isp_primary_14mp;
+extern unsigned int _hrt_size_of_isp_primary_14mp;
+
+extern unsigned int _hrt_text_size_of_isp_primary_16mp;
+extern unsigned int _hrt_size_of_isp_primary_16mp;
+
+extern unsigned int _hrt_text_size_of_isp_primary_ds;
+extern unsigned int _hrt_size_of_isp_primary_ds;
+
+extern unsigned int _hrt_text_size_of_isp_primary_small;
+extern unsigned int _hrt_size_of_isp_primary_small;
+
+extern unsigned int _hrt_text_size_of_isp_primary_var;
+extern unsigned int _hrt_size_of_isp_primary_var;
+
+extern unsigned int _hrt_text_size_of_isp_vf_pp;
+extern unsigned int _hrt_size_of_isp_vf_pp;
+
+extern unsigned int _hrt_text_size_of_isp_video_offline;
+extern unsigned int _hrt_size_of_isp_video_offline;
+
+extern unsigned int _hrt_text_size_of_isp_video_online_ds;
+extern unsigned int _hrt_size_of_isp_video_online_ds;
+
+extern unsigned int _hrt_text_size_of_isp_video_online_nodz;
+extern unsigned int _hrt_size_of_isp_video_online_nodz;
+
+extern unsigned int _hrt_text_size_of_isp_video_online;
+extern unsigned int _hrt_size_of_isp_video_online;
+
+extern unsigned int _hrt_text_size_of_isp_xnr_var;
+extern unsigned int _hrt_size_of_isp_xnr_var;
+#endif
+#endif /* MFLDISP_INTERNAL_H_ */
diff --git a/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_sensor.h b/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_sensor.h
new file mode 100644
index 0000000..f45782a
--- /dev/null
+++ b/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_sensor.h
@@ -0,0 +1,67 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _SensorParams_h_
+#define _SensorParams_h_
+
+#define MIPI_PORT_LANE_1       0
+#define MIPI_PORT_LANE_4       1
+
+
+#define BAYER_ORDER_GRBG       0
+#define BAYER_ORDER_RGGB       1
+#define BAYER_ORDER_BGGR       2
+#define BAYER_ORDER_GBRG       3
+
+#define INPUT_FORMAT_YUV420_8_LEGACY   0
+#define INPUT_FORMAT_YUV420_8          1
+#define INPUT_FORMAT_YUV420_10         2
+#define INPUT_FORMAT_YUV422_8          3
+#define INPUT_FORMAT_YUV422_10         4
+#define INPUT_FORMAT_RGB_444           5
+#define INPUT_FORMAT_RGB_555           6
+#define INPUT_FORMAT_RGB_565           7
+#define INPUT_FORMAT_RGB_666           8
+#define INPUT_FORMAT_RGB_888           9
+#define INPUT_FORMAT_RAW_6             10
+#define INPUT_FORMAT_RAW_7             11
+#define INPUT_FORMAT_RAW_8             12
+#define INPUT_FORMAT_RAW_10            13
+#define INPUT_FORMAT_RAW_12            14
+#define INPUT_FORMAT_RAW_14            15
+#define INPUT_FORMAT_RAW_16            16
+#define INPUT_FORMAT_BINARY_8          17
+
+struct mfld_ci_mipi_camera {
+       u32 port;
+       u32 num_of_lane;
+       u32 input_format;
+       u32 raw_bayer_order;
+       struct sh_css_shading_table*
+               (*get_shading_table)(unsigned int frame_width,
+                                       unsigned int frame_height,
+                                       unsigned int table_width,
+                                       unsigned int table_height);
+};
+
+#endif /* _SensorParams_h_ */
diff --git a/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_v4l2.h b/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_v4l2.h
new file mode 100644
index 0000000..00c4210
--- /dev/null
+++ b/drivers/media/video/mfld_ci/mfldisp/include/mfldisp/mfldisp_v4l2.h
@@ -0,0 +1,239 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef MFLDISP_V4L2_H_
+#define MFLDISP_V4L2_H_
+
+#define ATOMISP_MAJOR          0
+#define ATOMISP_MINOR          3
+#define ATOMISP_PATCHLEVEL     1
+
+#define DRIVER_VERSION_STR     __stringify(ATOMISP_MAJOR) \
+       "." __stringify(ATOMISP_MINOR) "." __stringify(ATOMISP_PATCHLEVEL)
+#define DRIVER_VERSION         KERNEL_VERSION(ATOMISP_MAJOR, \
+       ATOMISP_MINOR, ATOMISP_PATCHLEVEL)
+
+#define CI_MODE_PREVIEW                0x8000
+#define CI_MODE_VIDEO          0x4000
+#define CI_MODE_STILL_CAPTURE  0x2000
+#define CI_MODE_NONE           0x0000
+
+void *get_io_virt_addr(unsigned int address);
+
+#define MFLD_CI_I2C_BUS_1      4
+#define MFLD_CI_I2C_BUS_2      5
+
+#define CAMERA_SENSOR          0
+#define CAMERA_SENSOR_MOTOR    1
+#define XENON_FLASH            2
+#define LED_FLASH              3
+
+#define MFLD_WIDTH_RESTRICT    2
+#define MFLD_HEIGHT_RESTRICT   2
+
+/*#define MFLD_ISP_MAX_WIDTH   4608*/
+/*#define MFLD_ISP_MAX_HEIGHT  3450*/
+
+#define MFLD_ISP_MAX_WIDTH     1280
+#define MFLD_ISP_MAX_HEIGHT    720
+
+#include <linux/i2c.h>
+struct mfld_isp_subdev_info {
+       char *name;
+       u8 i2c_addr;
+       int i2c_id;
+};
+
+struct mfld_isp_subdev {
+       u32 subdev_type;
+       struct mfld_isp_subdev_info camera;
+       struct mfld_isp_subdev_info motor;
+       struct mfld_isp_subdev_info flash;
+};
+
+struct mfld_isp_3a_binary {
+       unsigned int mode;
+       int s3atbl_width;
+       int s3atbl_height;
+       int width;
+       int height;
+       int deci_factor;
+};
+
+#include "css/sh_css.h"
+
+struct mfld_isp_parm {
+       struct sh_css_grid_info info;
+       struct sh_css_isp_wb_config wb_config;
+       struct sh_css_isp_cc_config cc_config;
+       struct sh_css_isp_ob_config ob_config;
+       struct sh_css_isp_dp_config dp_config;
+       struct sh_css_isp_nr_config nr_config;
+       struct sh_css_isp_ee_config ee_config;
+       struct sh_css_isp_tnr_config tnr_config;
+};
+
+struct mfld_isp_dis_config {
+       int *w_sdis_vertproj_tbl;
+       int *w_sdis_horiproj_tbl;
+       short *sdis_vertcoef_tbl;
+       short *sdis_horicoef_tbl;
+       int dis_x;
+       int dis_y;
+};
+
+struct mfld_3a_stat {
+       void __user *w_3a_stat;
+};
+
+struct mfld_isp_gamma_tbl {
+       unsigned short gamma_table[1024];
+};
+
+/*Private IOCTLs for ISP */
+#define ATOMISP_IOC_G_XNR \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 0, int)
+#define ATOMISP_IOC_S_XNR \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 1, int)
+#define ATOMISP_IOC_G_BAYER_NR \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 2, struct sh_css_isp_nr_config)
+#define ATOMISP_IOC_S_BAYER_NR \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 3, struct sh_css_isp_nr_config)
+#define ATOMISP_IOC_G_TNR \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 4, struct sh_css_isp_tnr_config)
+#define ATOMISP_IOC_S_TNR \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 5, struct sh_css_isp_tnr_config)
+#define ATOMISP_IOC_G_HISTOGRAM \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 6, struct sh_css_histogram)
+#define ATOMISP_IOC_S_HISTOGRAM \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 7, struct sh_css_histogram)
+#define ATOMISP_IOC_G_BLACK_LEVEL_COMP \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 8, struct sh_css_isp_ob_config)
+#define ATOMISP_IOC_S_BLACK_LEVEL_COMP \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 9, struct sh_css_isp_ob_config)
+#define ATOMISP_IOC_G_YCC_NR \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 10, struct sh_css_isp_nr_config)
+#define ATOMISP_IOC_S_YCC_NR \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 11, struct sh_css_isp_nr_config)
+#define ATOMISP_IOC_G_EE \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 12, struct sh_css_isp_ee_config)
+#define ATOMISP_IOC_S_EE \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 13, struct sh_css_isp_ee_config)
+#define ATOMISP_IOC_G_DIS_STAT \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 14, struct mfld_isp_dis_config)
+#define ATOMISP_IOC_S_DIS_STAT \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 15, struct mfld_isp_dis_config)
+#define ATOMISP_IOC_G_3A_STAT \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 16, struct mfld_3a_stat)
+#define ATOMISP_IOC_G_ISP_PARM \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 17, struct mfld_isp_parm)
+#define ATOMISP_IOC_S_ISP_PARM \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 18, struct mfld_isp_parm)
+#define ATOMISP_IOC_G_ISP_GAMMA \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 19, struct mfld_isp_gamma_tbl)
+#define ATOMISP_IOC_S_ISP_GAMMA \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 20, struct mfld_isp_gamma_tbl)
+
+/*Extended IDs for Camera Class*/
+#define V4L2_CID_CAMERA_LASTP1 \
+       (V4L2_CID_CAMERA_CLASS_BASE + 22)
+
+#define V4L2_CID_ISO_ABSOLUTE \
+       (V4L2_CID_CAMERA_LASTP1 + 0)
+#define V4L2_CID_APERTURE_ABSOLUTE \
+       (V4L2_CID_CAMERA_LASTP1 + 1)
+#define V4L2_CID_SS_EXPOSURE_ABSOLUTE \
+       (V4L2_CID_CAMERA_LASTP1 + 2)
+#define V4L2_CID_SS_ISO_ABSOLUTE \
+       (V4L2_CID_CAMERA_LASTP1 + 3)
+#define V4L2_CID_SS_APERTURE_ABSOLUTE \
+       (V4L2_CID_CAMERA_LASTP1 + 4)
+#define V4L2_CID_FLASH_DELAY \
+       (V4L2_CID_CAMERA_LASTP1 + 5)
+#define V4L2_CID_FLASH_DURATION \
+       (V4L2_CID_CAMERA_LASTP1 + 6)
+
+/* Flash and privacy (indicator) light controls */
+#define V4L2_CID_FLASH_STROBE                  (V4L2_CID_CAMERA_CLASS_BASE+17)
+#define V4L2_CID_FLASH_TIMEOUT                 (V4L2_CID_CAMERA_CLASS_BASE+18)
+#define V4L2_CID_FLASH_INTENSITY               (V4L2_CID_CAMERA_CLASS_BASE+19)
+#define V4L2_CID_TORCH_INTENSITY               (V4L2_CID_CAMERA_CLASS_BASE+20)
+#define V4L2_CID_INDICATOR_INTENSITY           (V4L2_CID_CAMERA_CLASS_BASE+21)
+/*Private control IDs*/
+#define V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION \
+       (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC \
+       (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_ATOMISP_VIDEO_STABLIZATION \
+       (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_ATOMISP_FIXED_PATTERN_NR \
+       (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION \
+       (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_ATOMISP_SHADING_CORRECTION \
+       (V4L2_CID_PRIVATE_BASE + 5)
+
+#ifdef USE_DYNAMIC_BIN
+/* This is for the firmware Loading from user space */
+struct bi_h {
+       int ID;
+       unsigned int offset;
+       unsigned int size;
+       unsigned int text_size;
+};
+
+struct bi_file_h {
+       int version;
+       int binary_nr;
+       unsigned int h_size;
+       unsigned int bi_offset;
+};
+
+enum isp_bin_binary_id {
+       isp_bin_sp,
+       isp_bin_copy_var,
+       isp_bin_bayer_ds_var,
+       isp_bin_vf_pp,
+       isp_bin_xnr_var,
+       isp_bin_pregdc_var,
+       isp_bin_gdc_var,
+       isp_bin_postgdc_var,
+       isp_bin_preview_var,
+       isp_bin_preview_ds,
+       isp_bin_primary_var,
+       isp_bin_primary_small,
+       isp_bin_primary_ds,
+       isp_bin_primary_14mp,
+       isp_bin_primary_16mp,
+       isp_bin_video_offline,
+       isp_bin_video_online,
+       isp_bin_video_online_nodz,
+       isp_bin_video_online_ds,
+       isp_binary_number,
+};
+
+#define FW_PATH        "shisp.bin"
+#define SUPPORTED_BIN  isp_binary_number
+#endif
+
+#endif /* MFLDISP_V4L2_H_ */
diff --git a/drivers/media/video/mfld_ci/mfldisp/mfldisp_v4l2.c b/drivers/media/video/mfld_ci/mfldisp/mfldisp_v4l2.c
new file mode 100644
index 0000000..477f309
--- /dev/null
+++ b/drivers/media/video/mfld_ci/mfldisp/mfldisp_v4l2.c
@@ -0,0 +1,4335 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>      /* mfld_isp_dbg */
+#include <linux/version.h>     /* mfld_isp_dbg */
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>                /* for kmalloc */
+#include <linux/mm.h>          /* for GFP_ATOMIC */
+#include <linux/pci.h>         /* for DMA */
+#include <linux/pm_runtime.h>  /* for runtime pm */
+#include <linux/stringify.h>
+
+#include <linux/io.h>          /* ioremap */
+#include <linux/uaccess.h>     /* access_ok */
+#include <linux/param.h>               /* access_ok */
+#include <asm/irq.h>
+#include <linux/poll.h>
+#include <linux/stddef.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/firmware.h>
+
+#include <asm/intel_scu_ipc.h>
+
+#include <hmm/hmm.h>
+
+/* SH header files */
+#include <css/sh_css.h>
+
+
+#include "mfldisp_v4l2.h"
+#include "mfldisp_internal.h"
+#include <mfldisp_sensor.h>
+#include "mfld_mem.h"
+#define CI_MAX_BUF_NUM 4
+#define video_num      4
+
+#define        BITS_PER_PIXEL_RAW      16      /* raw type now */
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+/* TODO: translate css error into v4l2 error */
+#define return_on_css_error(stat) \
+       do { \
+               sh_css_err err = (stat); \
+               if (err != sh_css_success) { \
+                       mfld_isp_dbg(KERN_ERR, "Error find in %s, %d\n", \
+                                __func__, __LINE__); \
+                       return -EINVAL; \
+               } \
+       } while (0)
+
+#define goto_on_css_error(stat, ret, err_label) \
+       do { \
+               ret = (stat); \
+               if (ret != sh_css_success) { \
+                       mfld_isp_dbg(KERN_ERR, "Error find in %s, %d\n", \
+                                __func__, __LINE__); \
+                       goto err_label; \
+               } \
+       } while (0)
+
+/* for v4l2_capability */
+static const char *DRIVER = "atomisp"; /* max size 15 */
+static const char *CARD = "ATOM ISP MFLD";     /* max size 31 */
+static const char *BUS_INFO = "None";  /* max size 31 */
+static const __u32 VERSION = DRIVER_VERSION;
+static int nr = -1;
+static int isp_probe;
+
+struct ci_tvnorm {
+       char *name;
+       v4l2_std_id id;
+       u32 cxiformat;
+       u32 cxoformat;
+};
+
+struct ci_format {
+       __u32 pixelformat;
+       __u8 description[32];   /* the same as struct v4l2_fmtdesc */
+};
+
+struct ci_resolution {
+       __u32 width;
+       __u32 height;
+};
+
+struct ci_buffer {
+       struct sh_css_frame *handle;
+       __u32 size;
+       __u32 idx;
+       __u32 flags;
+
+       enum v4l2_memory buf_type;
+       /* for user ptr */
+       __u32 userptr;
+};
+
+struct ci_buffer_list {
+       struct list_head list;
+       struct ci_buffer *buf;
+};
+
+static struct ci_tvnorm tvnorms[] = {
+       {
+        .name = "CI Format",
+        .id = V4L2_STD_NTSC_M,
+        .cxiformat = 0,
+        .cxoformat = 0x181f0008,
+        },
+       {
+        .name = "CI Format NULL",
+        .id = V4L2_STD_NTSC_M_JP,
+        .cxiformat = 1,
+        .cxoformat = 0x181f0008,
+        }
+};
+
+/* subdev table */
+static struct mfld_isp_subdev mfld_isp_subdev_table[] = {
+       {
+        .subdev_type = CAMERA_SENSOR,
+        .camera = {
+                       .name = "smiapp",
+                       .i2c_addr = 0x10,
+                       .i2c_id = MFLD_CI_I2C_BUS_1
+               }
+
+        },
+       {
+        .subdev_type = CAMERA_SENSOR,
+        .camera = {
+                       .name = "dis71430m",
+                       .i2c_addr = 0x69,
+                       .i2c_id = MFLD_CI_I2C_BUS_1
+               }
+
+        },
+       {
+        .subdev_type = CAMERA_SENSOR,
+        .camera = {
+                       .name = "ov2720",
+                       .i2c_addr = 0x36,
+                       .i2c_id = MFLD_CI_I2C_BUS_1,
+               }
+        },
+        {
+         .subdev_type = LED_FLASH,
+         .flash = {
+                        .name = "mfld_ledflash",
+                        .i2c_addr = 0x30,
+                        .i2c_id = MFLD_CI_I2C_BUS_1,
+               }
+         },
+        {
+         .subdev_type = CAMERA_SENSOR_MOTOR,
+         .motor = {
+                        .name = "ad58xx",
+                        .i2c_addr = 0x0E,
+                        .i2c_id = MFLD_CI_I2C_BUS_1,
+               }
+         },
+};
+
+#define N_SUBDEV \
+       (sizeof(mfld_isp_subdev_table)/sizeof(mfld_isp_subdev_table[0]))
+
+struct ci_camera_subdev {
+       u32 type;
+       struct v4l2_subdev *camera;
+       struct v4l2_subdev *motor;
+};
+
+enum frame_state {
+       S_UNUSED = 0,   /* unused */
+       S_QUEUED,       /* ready to capture */
+       S_GRABBING,     /* in the process of being captured */
+       S_DONE, /* finished grabbing, but not been synced yet */
+       S_ERROR,        /* something bad happened while capturing */
+};
+
+struct frame_info {
+       enum frame_state state;
+       u32 flags;
+};
+
+struct fifo {
+       int front;
+       int back;
+       int data[CI_MAX_BUF_NUM + 1];
+       struct frame_info info[CI_MAX_BUF_NUM + 1];
+};
+
+/*
+ * ci device struct
+ */
+struct ci_device {
+       struct v4l2_device v4l2_dev;
+       struct video_device *vdev;
+       int open;
+
+       __u32 width;
+       __u32 height;
+       __u32 pixelformat;
+       __u32 framesize;
+       __u32 pixeldepth;
+       __u32 bytesperline;
+       __u32 imagesize;
+
+       __u32 snr_width;
+       __u32 snr_height;
+       __u32 snr_max_width;
+       __u32 snr_max_height;
+       __u32 snr_pixelformat;
+
+       int buf_allocated;
+       __u32 bufnum;
+       struct ci_buffer **imagebuf;    /* array of allocated buffers */
+       struct fifo buf_queue;
+       enum v4l2_memory buf_type;
+
+       struct ci_tvnorm *tvnorm;
+       int input;
+
+       struct sh_css_frame *vf_frame;
+       struct sh_css_frame *regular_output_frame;
+
+       enum sh_css_frame_format sh_pixelformat;
+
+       int camera_curr;
+       struct ci_camera_subdev cameras[N_SUBDEV];
+       struct v4l2_subdev *xenon_flash;
+       struct v4l2_subdev *led_flash;
+
+       int streaming;
+
+       int run_mode;
+       int online_process;
+       int bayer_downscaling;
+
+#ifdef MFLD_ASIC
+       void __iomem *base;
+#endif
+
+       /*OSPM related */
+       uint32_t apm_reg;
+       uint16_t apm_base;
+       uint32_t ospm_base;
+
+       struct sh_css_params *isp_params;
+
+       u32 color_effect;
+       u32 gdc_cac_en;
+       u32 bad_pixel_en;
+       u32 video_dis_en;
+       u32 sc_en;
+       u32 fpn_en;
+       u32 xnr_en;
+       int false_color;
+
+       struct sh_css_isp_ee_config *ee_config;
+       struct sh_css_isp_nr_config *nr_config;
+       struct sh_css_isp_tnr_config *tnr_config;
+       struct sh_css_isp_ob_config *ob_config;
+
+       int dis_x;
+       int dis_y;
+};
+
+#define        _TO_CI_DEVICE(dev)      container_of(dev, struct ci_device, vdev)
+
+/*
+ * input image data, and current frame resolution for test
+ */
+#define        ISP_PARAM_MMAP_OFFSET   0xfffff000
+
+void __iomem *io_base;
+static struct ci_device *CI_DEV;
+struct video_device *VDEV;
+static const int vf_width = 640;
+static const int vf_height = 480;
+static const enum sh_css_frame_format vf_format = sh_css_frame_format_yuv420;
+
+struct v4l2_subdev *get_current_camera(struct ci_device *ci)
+{
+       if (ci->camera_curr < 0 || ci->camera_curr > 4)
+               return NULL;
+
+       return ci->cameras[ci->camera_curr].camera;
+}
+
+static struct mfld_ci_mipi_camera *to_sensor_mipi_info(struct v4l2_subdev *sd)
+{
+       return (struct mfld_ci_mipi_camera *)v4l2_get_subdevdata(sd);
+}
+/*
+ * supported V4L2 fmts and resolutions
+ */
+static const struct ci_format SUPPORTED_FMTS[] = {
+       {
+        .pixelformat = V4L2_PIX_FMT_YUV420,
+        .description = "YUV420, planner"},
+       {
+        .pixelformat = V4L2_PIX_FMT_YVU420,
+        .description = "YVU420, planner"},
+       {
+        .pixelformat = V4L2_PIX_FMT_YUV422P,
+        .description = "YUV422, planner"},
+       {
+        .pixelformat = V4L2_PIX_FMT_YUV444,
+        .description = "YUV444"},
+       {
+        .pixelformat = V4L2_PIX_FMT_NV12,
+        .description = "NV12, interleaved"},
+       {
+        .pixelformat = V4L2_PIX_FMT_NV21,
+        .description = "NV21, interleaved"},
+       {
+        .pixelformat = V4L2_PIX_FMT_NV16,
+        .description = "NV16, interleaved"},
+       {
+        .pixelformat = V4L2_PIX_FMT_NV61,
+        .description = "NV61, interleaved"},
+       {
+        .pixelformat = V4L2_PIX_FMT_YUYV,
+        .description = "YUYV, interleaved"},
+       {
+        .pixelformat = V4L2_PIX_FMT_UYVY,
+        .description = "UYVY, interleaved"},
+       {
+        .pixelformat = V4L2_PIX_FMT_SBGGR16,
+        .description = "Bayer 16"},
+       {
+        .pixelformat = V4L2_PIX_FMT_SBGGR8,
+        .description = "Bayer 8"},
+       {
+        .pixelformat = V4L2_PIX_FMT_SGBRG8,
+        .description = "Bayer 8"},
+       {
+        .pixelformat = V4L2_PIX_FMT_SGRBG8,
+        .description = "Bayer 8"},
+       {
+        .pixelformat = V4L2_PIX_FMT_SRGGB8,
+        .description = "Bayer 8"},
+       {
+        .pixelformat = V4L2_PIX_FMT_SBGGR10,
+        .description = "Bayer 10"},
+       {
+        .pixelformat = V4L2_PIX_FMT_SGBRG10,
+        .description = "Bayer 10"},
+       {
+        .pixelformat = V4L2_PIX_FMT_SGRBG10,
+        .description = "Bayer 10"},
+       {
+        .pixelformat = V4L2_PIX_FMT_SRGGB10,
+        .description = "Bayer 10"},
+       {
+        .pixelformat = V4L2_PIX_FMT_RGB24,
+        .description = "24 RGB 8-8-8"},
+       {
+        .pixelformat = V4L2_PIX_FMT_RGB32,
+        .description = "32 RGB 8-8-8-8"},
+       {
+        .pixelformat = V4L2_PIX_FMT_RGB565,
+        .description = "16 RGB 5-6-5"}
+};
+
+static const __u32 SUPPORTED_FMT_NUM =
+       sizeof(SUPPORTED_FMTS) / sizeof(SUPPORTED_FMTS[0]);
+
+static struct ci_resolution SUPPORTED_RESOLUTIONS[] = {
+       {.width = 4352, .height = 3264},
+       /*{.width = 2560, .height = 1920}, */
+       {.width = 1920, .height = 1080},
+       {.width = 1280, .height = 720},
+       {.width = 640, .height = 480}
+};
+
+static const __u32 SUPPORTED_RESOLUTION_NUM =
+       sizeof(SUPPORTED_RESOLUTIONS) / sizeof(SUPPORTED_RESOLUTIONS[0]);
+
+struct v4l2_queryctrl ci_v4l2_controls[] = {
+       {
+        .id = V4L2_CID_AUTOGAIN,
+        .type = V4L2_CTRL_TYPE_BOOLEAN,
+        .name = "Automatic Gain Control",
+        .minimum = 0,
+        .maximum = 1,
+        .step = 1,
+        .default_value = 0,
+        },
+       {
+        .id = V4L2_CID_AUTO_WHITE_BALANCE,
+        .type = V4L2_CTRL_TYPE_BOOLEAN,
+        .name = "Automatic White Balance",
+        .minimum = 0,
+        .maximum = 1,
+        .step = 1,
+        .default_value = 0,
+        },
+       {
+        .id = V4L2_CID_RED_BALANCE,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Red Balance",
+        .minimum = 0x00,
+        .maximum = 0xff,
+        .step = 1,
+        .default_value = 0x00,
+        },
+       {
+        .id = V4L2_CID_BLUE_BALANCE,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Blue Balance",
+        .minimum = 0x00,
+        .maximum = 0xff,
+        .step = 1,
+        .default_value = 0x00,
+        },
+       {
+        .id = V4L2_CID_EXPOSURE,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Shutter Control",
+        .minimum = 0x00,
+        .maximum = 0xff,
+        .step = 1,
+        .default_value = 0x00,
+        },
+       {
+        .id = V4L2_CID_GAMMA,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Gamma",
+        .minimum = 0x00,
+        .maximum = 0xff,
+        .step = 1,
+        .default_value = 0x00,
+        },
+       {
+        .id = V4L2_CID_HFLIP,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Image h-flip",
+        .minimum = 0,
+        .maximum = 1,
+        .step = 1,
+        .default_value = 0,
+        },
+       {
+        .id = V4L2_CID_VFLIP,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Image v-flip",
+        .minimum = 0,
+        .maximum = 1,
+        .step = 1,
+        .default_value = 0,
+        },
+       {
+        .id = V4L2_CID_COLORFX,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Image Color Effect",
+        .minimum = 0,
+        .maximum = 9,
+        .step = 1,
+        .default_value = 0,
+        },
+       {
+        .id = V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Bad Pixel Correction",
+        .minimum = 0,
+        .maximum = 1,
+        .step = 1,
+        .default_value = 0,
+        },
+       {
+        .id = V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "GDC/CAC",
+        .minimum = 0,
+        .maximum = 1,
+        .step = 1,
+        .default_value = 0,
+        },
+       {
+        .id = V4L2_CID_ATOMISP_VIDEO_STABLIZATION,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Video Stablization",
+        .minimum = 0,
+        .maximum = 1,
+        .step = 1,
+        .default_value = 0,
+        },
+       {
+        .id = V4L2_CID_ATOMISP_FIXED_PATTERN_NR,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Fixed Pattern Noise Reduction",
+        .minimum = 0,
+        .maximum = 1,
+        .step = 1,
+        .default_value = 0,
+        },
+       {
+        .id = V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "False Color Correction",
+        .minimum = 0,
+        .maximum = 1,
+        .step = 1,
+        .default_value = 0,
+        },
+       {
+        .id = V4L2_CID_ATOMISP_SHADING_CORRECTION,
+        .type = V4L2_CTRL_TYPE_INTEGER,
+        .name = "Lens Shading Correction",
+        .minimum = 0,
+        .maximum = 1,
+        .step = 1,
+        .default_value = 0,
+        }
+};
+
+static const __u32 SUPPORTED_CTRL_NUM =
+       sizeof(ci_v4l2_controls) / sizeof(ci_v4l2_controls[0]);
+
+static inline void MSG_WRITE32(uint port, uint offset, u32 value);
+static inline u32 MSG_READ32(uint port, uint offset);
+
+void *get_io_virt_addr(unsigned int address)
+{
+       unsigned int ret = 0;
+
+       ret = (unsigned int)io_base + (address & 0x003FFFFF);
+
+       return (void *)ret;
+}
+
+/*
+ * utils for buffer allocation/free
+ */
+static inline unsigned long kvirt_to_pa(void *virt)
+{
+       __u32 kva;
+
+       kva = (unsigned long)page_address(vmalloc_to_page(virt));
+       kva |= ((__u32) virt) & (PAGE_SIZE - 1);        /* restore the offset */
+       return __pa(kva);
+}
+
+#define __bytes_to_pgnr_ceil(bytes) \
+       (((bytes) + ((1<<PAGE_SHIFT) - 1)) >> PAGE_SHIFT)
+
+int get_frame_pgnr(const struct sh_css_frame *frame, __u32 * p_pgnr)
+{
+       if (!frame) {
+               mfld_isp_dbg(KERN_ERR, "NULL frame pointer.\n");
+               return -EINVAL;
+       }
+
+       (*p_pgnr) = __bytes_to_pgnr_ceil(frame->data_bytes);
+       return 0;
+}
+
+#define        alloc_buffer(handle) __alloc_buffer(handle, 0)
+
+static struct ci_buffer *__alloc_buffer(struct sh_css_frame *handle,
+                                       __u32 flags)
+{
+       __u32 pgnr;
+       struct ci_buffer *buffer;
+
+       mfld_isp_dbg(KERN_DEBUG, "__alloc_isp_buffer\n");
+
+       if (!handle) {
+               mfld_isp_dbg(KERN_ERR, "NULL ISP buffer pointer!\n");
+               return NULL;
+       }
+
+       buffer = kmalloc(sizeof(struct ci_buffer), GFP_KERNEL);
+       if (buffer == NULL) {
+               mfld_isp_dbg(KERN_ERR, "out of memory\n");
+               return NULL;
+       }
+       memset(buffer, 0, sizeof(struct ci_buffer));
+
+       buffer->handle = handle;
+       buffer->flags = flags;
+
+       get_frame_pgnr(handle, &pgnr);
+       buffer->size = (pgnr << PAGE_SHIFT);
+
+       buffer->buf_type = V4L2_MEMORY_MMAP;
+
+       mfld_isp_dbg(KERN_DEBUG, "alloc_buffer: %u pages, %u bytes.\n",
+                       pgnr, buffer->size);
+
+       return buffer;
+}
+
+#define        alloc_user_buffer(handle, userptr, pgnr, index) \
+               __alloc_user_buffer(handle, 0, userptr, pgnr, index)
+
+static struct ci_buffer *__alloc_user_buffer(struct sh_css_frame *handle,
+                                               __u32 flags, __u32 userptr,
+                                               __u32 pgnr, __u32 index)
+{
+       __u32 __pgnr;
+       struct ci_buffer *buffer;
+
+       mfld_isp_dbg(KERN_DEBUG, "__alloc_isp_buffer\n");
+
+       if (!handle) {
+               mfld_isp_dbg(KERN_ERR, "NULL ISP buffer pointer!\n");
+               return NULL;
+       }
+
+       buffer = kmalloc(sizeof(struct ci_buffer), GFP_KERNEL);
+       if (buffer == NULL) {
+               mfld_isp_dbg(KERN_ERR, "out of memory\n");
+               return NULL;
+       }
+       memset(buffer, 0, sizeof(struct ci_buffer));
+
+       buffer->handle = handle;
+       buffer->flags = flags;
+
+       get_frame_pgnr(handle, &__pgnr);
+
+       if (__pgnr != pgnr)
+               mfld_isp_dbg(KERN_ERR, "user memory size is not the same"
+                               " as expected...\n");
+
+       buffer->size = (__pgnr << PAGE_SHIFT);
+
+       mfld_isp_dbg(KERN_DEBUG, "alloc_buffer: %u pages, %u bytes.\n",
+                       __pgnr, buffer->size);
+
+       buffer->userptr = userptr;
+
+       buffer->buf_type = V4L2_MEMORY_USERPTR;
+       buffer->idx = index;
+
+       return buffer;
+}
+
+static void free_buffer(struct ci_buffer *buf)
+{
+       kfree(buf);
+}
+
+/*
+ * get SH fmt according to V4L2 fmt
+ */
+static enum sh_css_frame_format v4l2_fmt_to_sh_fmt(__u32 fmt)
+{
+       switch (fmt) {
+       case V4L2_PIX_FMT_YUV420:
+               return sh_css_frame_format_yuv420;
+       case V4L2_PIX_FMT_YVU420:
+               return sh_css_frame_format_yv12;
+       case V4L2_PIX_FMT_YUV422P:
+               return sh_css_frame_format_yuv422;
+       case V4L2_PIX_FMT_YUV444:
+               return sh_css_frame_format_yuv444;
+       case V4L2_PIX_FMT_NV12:
+               return sh_css_frame_format_nv12;
+       case V4L2_PIX_FMT_NV21:
+               return sh_css_frame_format_nv21;
+       case V4L2_PIX_FMT_NV16:
+               return sh_css_frame_format_nv16;
+       case V4L2_PIX_FMT_NV61:
+               return sh_css_frame_format_nv61;
+       case V4L2_PIX_FMT_UYVY:
+               return sh_css_frame_format_uyvy;
+       case V4L2_PIX_FMT_YUYV:
+               return sh_css_frame_format_yuyv;
+       case V4L2_PIX_FMT_RGB24:
+               return sh_css_frame_format_planar_rgb888;
+       case V4L2_PIX_FMT_RGB32:
+               return sh_css_frame_format_rgba888;
+       case V4L2_PIX_FMT_RGB565:
+               return sh_css_frame_format_rgb565;
+       case V4L2_PIX_FMT_SBGGR16:
+               return sh_css_frame_format_vraw16;
+       case V4L2_PIX_FMT_SBGGR10:
+       case V4L2_PIX_FMT_SGBRG10:
+       case V4L2_PIX_FMT_SGRBG10:
+       case V4L2_PIX_FMT_SRGGB10:
+               return sh_css_frame_format_raw16;
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+               return sh_css_frame_format_raw8;
+       default:
+               return -1;
+       }
+}
+
+static struct ci_format *get_ci_format(__u32 pixelformat)
+{
+       __u32 i;
+       for (i = 0; i < SUPPORTED_FMT_NUM; i++) {
+               if (SUPPORTED_FMTS[i].pixelformat == pixelformat)
+                       return (struct ci_format *)(&(SUPPORTED_FMTS[i]));
+       }
+       return NULL;
+}
+
+static __u32 get_pixel_depth(__u32 pixelformat)
+{
+       switch (pixelformat) {
+       case V4L2_PIX_FMT_YUV420:
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
+       case V4L2_PIX_FMT_YVU420:
+               return 12;
+       case V4L2_PIX_FMT_YUV422P:
+       case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_NV61:
+       case V4L2_PIX_FMT_RGB565:
+       case V4L2_PIX_FMT_SBGGR16:
+       case V4L2_PIX_FMT_SBGGR10:
+       case V4L2_PIX_FMT_SGBRG10:
+       case V4L2_PIX_FMT_SGRBG10:
+       case V4L2_PIX_FMT_SRGGB10:
+               return 16;
+       case V4L2_PIX_FMT_RGB24:
+       case V4L2_PIX_FMT_YUV444:
+               return 24;
+       case V4L2_PIX_FMT_RGB32:
+               return 32;
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+               return 8;
+       default:
+               return 8 * 2;   /* raw type now */
+       }
+}
+
+static int is_pixelformat_supported(__u32 pixelformat)
+{
+       int i;
+
+       for (i = 0; i < SUPPORTED_FMT_NUM; i++) {
+               mfld_isp_dbg(KERN_WARNING,
+                               "pixel try %x, %x\n", pixelformat,
+                               SUPPORTED_FMTS[i].pixelformat);
+               if (pixelformat == SUPPORTED_FMTS[i].pixelformat)
+                       return 1;
+       }
+
+       return 0;
+}
+
+static int is_resolution_supported(__u32 width, __u32 height)
+{
+       int i;
+
+       mfld_isp_dbg(KERN_DEBUG,
+                       "SUPPORTED_RESOLUTION_NUM: %d\n",
+                       SUPPORTED_RESOLUTION_NUM);
+       for (i = 0; i < SUPPORTED_RESOLUTION_NUM; i++) {
+               if (width == SUPPORTED_RESOLUTIONS[i].width &&
+                       height == SUPPORTED_RESOLUTIONS[i].height)
+                       return 1;
+       }
+
+       return 0;
+}
+
+/* MFLD ISP feature control */
+static int mfld_isp_gdc_cac(struct ci_device *ci, int flag, __s32 * value);
+static int mfld_isp_xnr(struct ci_device *ci, int flag, int *arg)
+{
+       int xnr_enable = (*arg == 0) ? 0 : 1;
+       int gdc_enable = 1;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (flag == 0) {
+               *arg = ci->xnr_en;
+               return 0;
+       }
+
+       if (ci->run_mode == CI_MODE_STILL_CAPTURE) {
+               if (!ci->gdc_cac_en && xnr_enable == 1)
+                       mfld_isp_gdc_cac(ci, 1, &gdc_enable);
+               sh_css_capture_enable_xnr(xnr_enable);
+       }
+       return 0;
+}
+
+static int mfld_isp_bayer_nr(struct ci_device *ci, int flag,
+                               struct sh_css_isp_nr_config *arg)
+{
+       const struct sh_css_isp_ee_config **default_ee_config = NULL;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (arg == NULL)
+               return -EINVAL;
+
+       /* Get nr config from current setup */
+       if (flag == 0) {
+               memcpy(arg, ci->nr_config, sizeof(struct sh_css_isp_nr_config));
+               return 0;
+       }
+
+       /* Set nr config to isp parameters */
+       sh_css_params_get_default_ee_config(default_ee_config);
+       sh_css_params_configure_nree(ci->isp_params, arg, *default_ee_config);
+       memcpy(ci->nr_config, arg, sizeof(struct sh_css_isp_nr_config));
+
+       return 0;
+}
+
+static int mfld_isp_tnr(struct ci_device *ci, int flag,
+                       struct sh_css_isp_tnr_config *arg)
+{
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (arg == NULL)
+               return -EINVAL;
+
+       /* Get tnr config from current setup */
+       if (flag == 0) {
+               memcpy(arg, ci->tnr_config,
+                       sizeof(struct sh_css_isp_tnr_config));
+               return 0;
+       }
+
+       if (arg->threshold_y == 0 && arg->threshold_uv == 0)
+
+               /* Set tnr config to isp parameters */
+               sh_css_params_configure_tnr(ci->isp_params, arg);
+       memcpy(ci->tnr_config, arg, sizeof(struct sh_css_isp_tnr_config));
+
+       return 0;
+}
+
+static int mfld_isp_histogram(struct ci_device *ci, int flag, void *arg)
+{
+       return 0;
+}
+
+static int mfld_isp_black_level(struct ci_device *ci, int flag,
+                               struct sh_css_isp_ob_config *arg)
+{
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (arg == NULL)
+               return -EINVAL;
+
+       /* Get ob config from current setup */
+       if (flag == 0) {
+               memcpy(arg, ci->ob_config, sizeof(struct sh_css_isp_ob_config));
+               return 0;
+       }
+
+       /* Set ob config to isp parameters */
+       sh_css_params_configure_ob(ci->isp_params, arg);
+       memcpy(ci->ob_config, arg, sizeof(struct sh_css_isp_ob_config));
+
+       return 0;
+}
+
+static int mfld_isp_ycc_nr(struct ci_device *ci, int flag,
+                               struct sh_css_isp_nr_config *arg)
+{
+       const struct sh_css_isp_ee_config **default_ee_config = NULL;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (arg == NULL)
+               return -EINVAL;
+
+       /* Get nr config from current setup */
+       if (flag == 0) {
+               memcpy(arg, ci->nr_config, sizeof(struct sh_css_isp_nr_config));
+               return 0;
+       }
+
+       /* Set nr config to isp parameters */
+       sh_css_params_get_default_ee_config(default_ee_config);
+       sh_css_params_configure_nree(ci->isp_params, arg, *default_ee_config);
+       memcpy(ci->nr_config, arg, sizeof(struct sh_css_isp_nr_config));
+
+       return 0;
+}
+
+static int mfld_isp_ee(struct ci_device *ci, int flag,
+                       struct sh_css_isp_ee_config *arg)
+{
+       const struct sh_css_isp_nr_config **default_nr_config = NULL;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (arg == NULL)
+               return -EINVAL;
+
+       /* Get ee config from current setup */
+       if (flag == 0) {
+               memcpy(arg, ci->ee_config, sizeof(struct sh_css_isp_ee_config));
+               return 0;
+       }
+
+       /* Set ee config to isp parameters */
+       sh_css_params_get_default_nr_config(default_nr_config);
+       sh_css_params_configure_nree(ci->isp_params, *default_nr_config, arg);
+       memcpy(ci->ee_config, arg, sizeof(struct sh_css_isp_ee_config));
+       return 0;
+}
+
+static int mfld_isp_set_gamma(struct ci_device *ci, int flag,
+                               struct mfld_isp_gamma_tbl *arg)
+{
+       sh_css_params_set_gamma_table(ci->isp_params, arg->gamma_table);
+       return 0;
+}
+
+static int mfld_isp_get_gamma(struct ci_device *ci, int flag,
+                               struct mfld_isp_gamma_tbl *arg)
+{
+       sh_css_params_get_gamma_table(ci->isp_params, arg->gamma_table);
+       return 0;
+}
+
+static int mfld_isp_dis_stat(struct ci_device *ci, int flag,
+                               struct mfld_isp_dis_config *arg)
+{
+       int width_size, height_size;
+       int error;
+       int *w_sdis_hori_proj = NULL, *w_sdis_vert_proj = NULL;
+       short *sdis_hori_coef = NULL, *sdis_vert_coef = NULL;
+       struct sh_css_grid_info info;
+
+       switch (ci->run_mode) {
+       case CI_MODE_PREVIEW:
+               sh_css_preview_get_grid_info(&info);
+               break;
+       case CI_MODE_VIDEO:
+               sh_css_video_get_grid_info(&info);
+               break;
+       default:
+               sh_css_capture_get_grid_info(&info);
+               break;
+       }
+
+       if (flag == 0) {
+               if (arg->w_sdis_vertproj_tbl == NULL ||
+                   arg->w_sdis_horiproj_tbl == NULL)
+                       return -EINVAL;
+
+               width_size = sh_css_num_dis_coef_types * info.width_dis
+                   * sizeof(int);
+               height_size = sh_css_num_dis_coef_types * info.height_dis
+                   * sizeof(int);
+               w_sdis_hori_proj = kmalloc(height_size, GFP_KERNEL);
+               if (w_sdis_hori_proj == NULL) {
+                       mfld_isp_dbg(KERN_ERR, "Failed to request memory\n");
+                       return -ENOMEM;
+               }
+               w_sdis_vert_proj = kmalloc(width_size, GFP_KERNEL);
+               if (w_sdis_vert_proj == NULL) {
+                       mfld_isp_dbg(KERN_ERR, "Failed to request memory\n");
+                       kfree(w_sdis_hori_proj);
+                       return -ENOMEM;
+               }
+
+               sh_css_params_dis_get_projections(w_sdis_hori_proj,
+                                                w_sdis_vert_proj);
+
+               error = copy_to_user(arg->w_sdis_vertproj_tbl,
+                            w_sdis_vert_proj,
+                            sh_css_num_dis_coef_types * info.width_dis
+                            * sizeof(int));
+
+               error = copy_to_user(arg->w_sdis_horiproj_tbl,
+                            w_sdis_hori_proj,
+                            sh_css_num_dis_coef_types * info.height_dis
+                            * sizeof(int));
+
+               arg->dis_x = ci->dis_x;
+               arg->dis_y = ci->dis_y;
+
+               kfree(w_sdis_hori_proj);
+               kfree(w_sdis_vert_proj);
+       } else {
+               if (arg->sdis_vertcoef_tbl == NULL ||
+                   arg->sdis_horicoef_tbl == NULL)
+                       return -EINVAL;
+
+               width_size = sizeof(short) *sh_css_num_dis_coef_types *
+                   info.dis_vertcoef_num;
+               height_size = sizeof(short) *sh_css_num_dis_coef_types *
+                   info.dis_horicoef_num;
+               sh_css_params_dis_get_coefficients(&sdis_hori_coef,
+                                                  &sdis_vert_coef);
+               error = copy_from_user(sdis_hori_coef,
+                              (void __user *)arg->sdis_horicoef_tbl,
+                              height_size);
+               error = copy_from_user(sdis_vert_coef,
+                              (void __user *)arg->sdis_vertcoef_tbl,
+                              width_size);
+
+               ci->dis_x = arg->dis_x;
+               ci->dis_y = arg->dis_y;
+       }
+       return 0;
+}
+
+static int mfld_isp_3a_stat(struct ci_device *ci, int flag,
+                               struct mfld_3a_stat *arg)
+{
+       struct sh_css_grid_info info;
+       struct sh_css_isp_3a_output *output;
+       unsigned int bytes;
+       unsigned long ret;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (flag != 0)
+               return -EINVAL;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       switch (ci->run_mode) {
+       case CI_MODE_STILL_CAPTURE:
+               sh_css_capture_get_grid_info(&info);
+               break;
+       case CI_MODE_PREVIEW:
+               sh_css_preview_get_grid_info(&info);
+               break;
+       case CI_MODE_VIDEO:
+               sh_css_video_get_grid_info(&info);
+               break;
+       }
+
+       bytes =
+               info.width_3a * info.height_3a * sizeof(struct
+                                                       sh_css_isp_3a_output);
+       output = kmalloc(bytes, GFP_KERNEL);
+
+       sh_css_params_3a_get_statistics(output);
+       ret = copy_to_user(arg->w_3a_stat, output, bytes);
+       if (ret)
+               mfld_isp_dbg(KERN_DEBUG,
+                               "copy to user failed copied %lu bytes\n", ret);
+
+#ifdef CI_ISP_DEBUG
+       int i;
+       /*for (i = 0; i < info.width_3a * info.height_3a; i++) { */
+       for (i = 0; i < 10; i++) {
+               struct sh_css_isp_3a_output *pt;
+               pt = output + i * sizeof(struct sh_css_isp_3a_output);
+               mfld_isp_dbg(KERN_DEBUG, "Get 3A stat from kernel %d\n", i);
+               mfld_isp_dbg(KERN_DEBUG, "ae_y = %d\n", pt->ae_Y);
+               mfld_isp_dbg(KERN_DEBUG, "awb_cnt = %d\n", pt->awb_cnt);
+               mfld_isp_dbg(KERN_DEBUG, "awb_GR = %d\n", pt->awb_GR);
+               mfld_isp_dbg(KERN_DEBUG, "awb_R = %d\n", pt->awb_R);
+               mfld_isp_dbg(KERN_DEBUG, "awb_B = %d\n", pt->awb_B);
+               mfld_isp_dbg(KERN_DEBUG, "awb_GB = %d\n", pt->awb_GB);
+               mfld_isp_dbg(KERN_DEBUG, "af_hpf1 = %d\n", pt->af_hpf1);
+               mfld_isp_dbg(KERN_DEBUG, "af_hpf2 = %d\n", pt->af_hpf2);
+       }
+#endif
+       kfree(output);
+       return 0;
+}
+
+static int mfld_isp_param(struct ci_device *ci, int flag,
+                               struct mfld_isp_parm *arg)
+{
+       struct sh_css_grid_info *info;
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+
+       /* Read parameter for 3A bianry info */
+       if (flag == 0) {
+               if (&arg->info == NULL) {
+                       mfld_isp_dbg(KERN_ERR, "NULL pointer in grid_info\n");
+                       return -EINVAL;
+               }
+
+               info = &arg->info;
+               switch (ci->run_mode) {
+               case CI_MODE_STILL_CAPTURE:
+                       sh_css_capture_get_grid_info(info);
+                       break;
+               case CI_MODE_PREVIEW:
+                       sh_css_preview_get_grid_info(info);
+                       break;
+               case CI_MODE_VIDEO:
+                       sh_css_video_get_grid_info(info);
+                       break;
+               }
+               return 0;
+       }
+
+       sh_css_params_configure_wb(ci->isp_params, &arg->wb_config);
+       sh_css_params_configure_cc(ci->isp_params, &arg->cc_config);
+       sh_css_params_configure_ob(ci->isp_params, &arg->ob_config);
+       sh_css_params_configure_dp(ci->isp_params, &arg->dp_config);
+       sh_css_params_configure_nree(ci->isp_params, &arg->nr_config,
+                                       &arg->ee_config);
+       sh_css_params_configure_tnr(ci->isp_params, &arg->tnr_config);
+#ifdef CI_ISP_DEBUG
+       struct sh_css_isp_wb_config *wb_config = &arg->wb_config;
+       struct sh_css_isp_cc_config *cc_config = &arg->cc_config;
+       struct sh_css_isp_ob_config *ob_config = &arg->ob_config;
+       mfld_isp_dbg(KERN_DEBUG, "wb: gr = %x, r = %x, b = %x, gb = %x\n",
+                       wb_config->gr, wb_config->r,
+                       wb_config->b, wb_config->gb);
+       mfld_isp_dbg(KERN_DEBUG, "CC matrix, %d, %d, %d, %d, %d, %d\n",
+                       cc_config->matrix[0], cc_config->matrix[1],
+                       cc_config->matrix[2], cc_config->matrix[3],
+                       cc_config->matrix[4], cc_config->matrix[5]);
+       mfld_isp_dbg(KERN_DEBUG, "OB: gr %x, r %x, b %x, gb %x\n",
+                       ob_config->level_gr, ob_config->level_r,
+                       ob_config->level_b, ob_config->level_gb);
+#endif
+       return 0;
+}
+
+static const struct sh_css_isp_cc_config sepia_cc_config = {
+       .fraction_bits  = 8,
+       .matrix         = {141, 18, 68, -40, -5, -19, 35, 4, 16},
+};
+
+static const struct sh_css_isp_cc_config nega_cc_config = {
+       .fraction_bits  = 8,
+       .matrix         = {255, 29, 120, 0, 374, 342, 0, 672, -301},
+};
+
+static const struct sh_css_isp_cc_config mono_cc_config = {
+       .fraction_bits  = 8,
+       .matrix         = {255, 29, 120, 0, 0, 0, 0, 0, 0},
+};
+
+static const short skin_macc_table[] = {
+       8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192,
+       8192, 4096, 0, 6144, 7168, 2048, -1024, 4096, 6144, 0, 4096, 8192, 4096,
+       -1024, 2048, 7168,
+       8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192,
+       8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192
+};
+
+static const short blue_macc_table[] = {
+       24576, -16384, 0, 16384, 24576, -16384, 8192, 0, 8192, 0, 0, 8192, 8192,
+       0, 0, 8192,
+       8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192,
+       24576, 0, 0, 24576, 32767, 16384, -8192, 8192, 8192, 0, 0, 8192, 24576,
+       8192, -16384, 0,
+       8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192
+};
+
+static const short green_macc_table[] = {
+       8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192,
+       16384, 16384, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0,
+       8192,
+       8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 16384, 16384, 8192, 0, 0,
+       8192,
+       16384, 16384, 0, 24576, 20480, 8192, -4096, 32767, 24576, 0, 16384,
+       16384, 32767, -4096, 8192, 20480
+};
+
+static unsigned short vivid_ctc_table[] = {
+       0, 0, 0
+};
+
+static int mfld_isp_color_effect(struct ci_device *ci, int flag, __s32 *effect)
+{
+       const struct sh_css_isp_cc_config *cc_config = NULL;
+       const short *macc_table = NULL;
+       const unsigned short *ctc_table = NULL;
+       const short *default_macc_table[1];
+       const struct sh_css_isp_cc_config *default_cc_config[1];
+       const unsigned short *default_ctc_table[1];
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (flag == 0) {
+               *effect = ci->color_effect;
+               return 0;
+       }
+
+       if (*effect == ci->color_effect)
+               return 0;
+
+       switch (*effect) {
+       case V4L2_COLORFX_NONE:
+               sh_css_params_get_default_macc_table(default_macc_table);
+               sh_css_params_get_default_cc_config(default_cc_config);
+               sh_css_params_get_default_ctc_table(default_ctc_table);
+               cc_config = *default_cc_config;
+               macc_table = *default_macc_table;
+               ctc_table = *default_ctc_table;
+               break;
+       case V4L2_COLORFX_SEPIA:
+               cc_config = (const struct sh_css_isp_cc_config *)
+                   &sepia_cc_config;
+               break;
+       case V4L2_COLORFX_NEGATIVE:
+               cc_config = &nega_cc_config;
+               break;
+       case V4L2_COLORFX_BW:
+               cc_config = &mono_cc_config;
+               break;
+       case V4L2_COLORFX_SKY_BLUE:
+               macc_table = blue_macc_table;
+               break;
+       case V4L2_COLORFX_GRASS_GREEN:
+               macc_table = green_macc_table;
+               break;
+       case V4L2_COLORFX_SKIN_WHITEN:
+               macc_table = skin_macc_table;
+               break;
+       case V4L2_COLORFX_VIVID:
+               ctc_table = vivid_ctc_table;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (cc_config)
+               sh_css_params_configure_cc(ci->isp_params, cc_config);
+       if (macc_table)
+               sh_css_params_set_macc_table(ci->isp_params, macc_table);
+       if (ctc_table)
+               sh_css_params_set_ctc_table(ci->isp_params,
+                                           (unsigned short *)ctc_table);
+       ci->color_effect = (u32)*effect;
+       return 0;
+}
+
+static int mfld_isp_bad_pixel(struct ci_device *ci, int flag, __s32 *value)
+{
+       struct sh_css_isp_dp_config dp_config;
+       const struct sh_css_isp_dp_config **default_dp_config = NULL;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (flag == 0) {
+               *value = ci->bad_pixel_en;
+               return 0;
+       }
+
+       if (*value == ci->bad_pixel_en)
+               return 0;
+
+       if (*value) {
+               sh_css_params_get_default_dp_config(default_dp_config);
+               memcpy(&dp_config, *default_dp_config,
+                       (sizeof(default_dp_config)));
+       } else {
+               dp_config.threshold = 0xFFFF;
+               dp_config.gain = 0xFFFF;
+       }
+
+       sh_css_params_configure_dp(ci->isp_params, &dp_config);
+       ci->bad_pixel_en = (*value == 0) ? 0 : 1;
+
+       return 0;
+}
+
+static int mfld_isp_gdc_cac(struct ci_device *ci, int flag, __s32 * value)
+{
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (flag == 0) {
+               *value = ci->gdc_cac_en;
+               return 0;
+       }
+
+       if (ci->run_mode == CI_MODE_STILL_CAPTURE) {
+               sh_css_capture_set_mode(sh_css_capture_mode_advanced);
+               ci->gdc_cac_en = (*value == 0) ? 0 : 1;
+       }
+
+       return 0;
+}
+
+static int mfld_isp_video_stable(struct ci_device *ci, int flag, __s32 * value)
+{
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (flag == 0) {
+               *value = ci->video_dis_en;
+               return 0;
+       }
+
+       if (ci->run_mode == CI_MODE_VIDEO)
+               ci->video_dis_en = (*value == 0) ? 0 : 1;
+
+       return 0;
+}
+
+static int mfld_isp_fixed_pattern(struct ci_device *ci, int flag, __s32 * value)
+{
+       struct sh_css_frame *raw_black_frame = NULL;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (flag == 0) {
+               *value = ci->fpn_en;
+               return 0;
+       }
+
+       if (*value == 0) {
+               /*ci->isp_params->isp_parameters.fpn_enabled = 0;*/
+               ci->fpn_en = 0;
+               return 0;
+       }
+
+       /* Add function to get black from from sensor with shutter off */
+       sh_css_params_set_black_frame(ci->isp_params, raw_black_frame);
+       ci->fpn_en = 1;
+       return 0;
+}
+
+static int mfld_isp_false_color(struct ci_device *ci, int flag, __s32 * value)
+{
+       const struct sh_css_isp_de_config *default_de_config[1];
+       struct sh_css_isp_de_config de_config;
+       /* Get nr config from current setup */
+       if (flag == 0) {
+               *value = ci->false_color;
+               return 0;
+       }
+
+       /* Set nr config to isp parameters */
+       sh_css_params_get_default_de_config(default_de_config);
+       memcpy(&de_config, *default_de_config,
+              sizeof(struct sh_css_isp_de_config));
+       de_config.pixelnoise = *value;
+       sh_css_params_configure_de(ci->isp_params, &de_config);
+       ci->false_color = *value;
+       return 0;
+}
+
+static int mfld_isp_shading_correction(struct ci_device *ci, int flag,
+                                       __s32 *value)
+{
+       struct mfld_ci_mipi_camera *mipi_info;
+       struct sh_css_shading_table* (*shading_table_func)
+           (unsigned int frame_width,
+            unsigned int frame_height,
+            unsigned int table_width,
+            unsigned int table_height) = NULL;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (flag == 0) {
+               *value = ci->sc_en;
+               return 0;
+       }
+
+       if (*value == 0) {
+               sh_css_set_get_shading_table(NULL);
+               ci->sc_en = 0;
+               return 0;
+       }
+
+       /* set the shading table function */
+       mipi_info = to_sensor_mipi_info(ci->cameras[ci->camera_curr].camera);
+       shading_table_func = mipi_info->get_shading_table;
+       sh_css_set_get_shading_table(shading_table_func);
+       ci->sc_en = 1;
+       return 0;
+}
+
+static int mfld_isp_digital_zoom(struct ci_device *ci, int flag, __s32 * value)
+{
+       u32 zoom;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+       if (flag == 0) {
+               sh_css_get_zoom_factor(&zoom, &zoom);
+               *value = 64 - zoom;
+       }
+
+       if (*value < 0)
+               return -EINVAL;
+
+       if (ci->run_mode == CI_MODE_VIDEO) {
+               zoom = *value;
+               if (zoom >= 64)
+                       zoom = 64;
+               zoom = 64 - zoom;
+               sh_css_set_zoom_factor(zoom, zoom);
+       }
+       return 0;
+}
+
+/*
+ * v4l2 ioctls
+ */
+static int mfld_isp_querycap(struct file *file, void *fh,
+                               struct v4l2_capability *cap)
+{
+       int ret = 0;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_querycaps\n");
+
+       memset(cap, 0, sizeof(struct v4l2_capability));
+       strncpy(cap->driver, DRIVER, strlen(DRIVER));
+       strncpy(cap->card, CARD, strlen(CARD));
+       strncpy(cap->bus_info, BUS_INFO, strlen(BUS_INFO));
+       cap->version = VERSION;
+
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+
+       return ret;
+}
+
+static int mfld_isp_cropcap(struct file *file, void *fh,
+                           struct v4l2_cropcap *cropcap)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       struct v4l2_format snr_fmt;
+       int ret;
+
+       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupport v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       cropcap->bounds.left = 0;
+       cropcap->bounds.top = 0;
+
+#if    (!defined(IMAGE_FROM_FILE) && !defined(IMAGE_FROM_TPG))
+       snr_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       snr_fmt.fmt.pix.height = MFLD_ISP_MAX_HEIGHT;
+       snr_fmt.fmt.pix.width = MFLD_ISP_MAX_WIDTH;
+
+       ret = v4l2_subdev_call(ci->cameras[ci->camera_curr].camera,
+                              video, try_fmt, &snr_fmt);
+       if (ret) {
+               mfld_isp_dbg(KERN_ERR, "failed to try_fmt for sensor\n");
+               return ret;
+       }
+       cropcap->bounds.width = snr_fmt.fmt.pix.width;
+       cropcap->bounds.height = snr_fmt.fmt.pix.height;
+       ci->snr_max_width = snr_fmt.fmt.pix.width;
+       ci->snr_max_height = snr_fmt.fmt.pix.height;
+       ci->snr_pixelformat = snr_fmt.fmt.pix.pixelformat;
+#else
+       cropcap->bounds.width = MFLD_ISP_MAX_WIDTH;
+       cropcap->bounds.height = MFLD_ISP_MAX_HEIGHT;
+#endif
+
+       memcpy(&cropcap->defrect, &cropcap->bounds, sizeof(struct v4l2_rect));
+       cropcap->pixelaspect.numerator = 1;
+       cropcap->pixelaspect.denominator = 1;
+       return 0;
+}
+
+static int mfld_isp_g_crop(struct file *file, void *fh,
+                          struct v4l2_crop *crop)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupport v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       crop->c.left = 0;
+       crop->c.top = 0;
+
+       if (ci->bayer_downscaling) {
+               crop->c.width = ci->snr_max_width;
+               crop->c.height = ci->snr_max_height;
+       } else {
+               crop->c.width = 0;
+               crop->c.height = 0;
+       }
+
+       return 0;
+}
+
+static int mfld_isp_s_crop(struct file *file, void *fh,
+                          struct v4l2_crop *crop)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       struct v4l2_format snr_fmt;
+       int ret;
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupport v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       if (!ci->bayer_downscaling) {
+#if    (!defined(IMAGE_FROM_FILE) && !defined(IMAGE_FROM_TPG))
+               snr_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               snr_fmt.fmt.pix.height = MFLD_ISP_MAX_HEIGHT;
+               snr_fmt.fmt.pix.width = MFLD_ISP_MAX_WIDTH;
+
+               ret = v4l2_subdev_call(ci->cameras[ci->camera_curr].camera,
+                                      video, s_fmt, &snr_fmt);
+               if (ret) {
+                       mfld_isp_dbg(KERN_ERR, "failed to s_fmt for sensor\n");
+                       return ret;
+               }
+               ci->snr_max_width = snr_fmt.fmt.pix.width;
+               ci->snr_max_height = snr_fmt.fmt.pix.height;
+#else
+               ci->snr_max_width = MFLD_ISP_MAX_WIDTH;
+               ci->snr_max_height = MFLD_ISP_MAX_HEIGHT;
+#endif
+               ci->bayer_downscaling = 1;
+       }
+       return 0;
+}
+
+static int mfld_isp_enum_input(struct file *file, void *fh,
+                               struct v4l2_input *input)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_enum_input\n");
+
+       if (input->index)
+               return -EINVAL;
+
+       if (!ci->cameras[input->index].camera)
+               return -EINVAL;
+
+       memset(input, 0, sizeof(struct v4l2_input));
+       strcpy(input->name, ci->cameras[input->index].camera->name);
+       input->type = V4L2_INPUT_TYPE_CAMERA;
+
+       return 0;
+}
+
+static int mfld_isp_g_input(struct file *file, void *fh, unsigned int *input)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_g_input\n");
+
+       *input = ci->camera_curr;
+
+       return 0;
+}
+
+static int mfld_isp_s_input(struct file *file, void *fh, unsigned int input)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       struct v4l2_subdev *camera = NULL;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_s_input\n");
+
+       if (input < 0 || input > 3)
+               return -EINVAL;
+
+       camera = ci->cameras[input].camera;
+       if (!camera)
+               return -EINVAL;
+
+       if (ci->streaming == 1) {
+               mfld_isp_dbg(KERN_ERR, "ISP is still streaming, stop first\n");
+               return -EINVAL;
+       }
+
+       ci->camera_curr = input;
+
+       return 0;
+}
+
+static int mfld_isp_g_std(struct file *file, void *fh, v4l2_std_id * id)
+{
+       return -1;
+}
+
+static int mfld_isp_s_std(struct file *file, void *fh, v4l2_std_id * id)
+{
+       return -1;
+}
+
+static int mfld_isp_enum_fmt_cap(struct file *file, void *fh,
+                                struct v4l2_fmtdesc *f)
+{
+       __u32 index = f->index;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_enum_fmt_cap\n");
+
+       /* check buf index */
+       if (index >= SUPPORTED_FMT_NUM) {
+               mfld_isp_dbg(KERN_ERR, "fmt index extends maxiumn"
+                            " supported fmts number\n");
+               return -EINVAL;
+       }
+       /* check buf type */
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       f->pixelformat = SUPPORTED_FMTS[index].pixelformat;
+       memset(f->description, 0, sizeof(char)*32);
+       strncpy(f->description, SUPPORTED_FMTS[index].description,
+               strlen(SUPPORTED_FMTS[index].description));
+
+       return 0;
+}
+
+static int mfld_isp_g_fmt_cap(struct file *file, void *fh,
+                               struct v4l2_format *f)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_g_fmt_cap\n");
+
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       memset(f, 0, sizeof(struct v4l2_format));
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       if (ci->width != 0) {   /* VIDIOC_S_FMT already called,
+                                       return fmt setted by app */
+               f->fmt.pix.width = ci->width;
+               f->fmt.pix.height = ci->height;
+               f->fmt.pix.pixelformat = ci->pixelformat;
+               f->fmt.pix.bytesperline = ci->bytesperline;
+               f->fmt.pix.sizeimage = ci->framesize;
+               f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
+       } else {                /* otherwise return default value */
+               f->fmt.pix.width = SUPPORTED_RESOLUTIONS[0].width;
+               f->fmt.pix.height = SUPPORTED_RESOLUTIONS[0].height;
+               f->fmt.pix.pixelformat = SUPPORTED_FMTS[0].pixelformat;
+               f->fmt.pix.bytesperline =
+                       get_pixel_depth(f->fmt.pix.pixelformat) *
+                       f->fmt.pix.width;
+               f->fmt.pix.sizeimage = f->fmt.pix.height *
+                       f->fmt.pix.bytesperline;
+               f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
+       }
+
+       return 0;
+}
+
+
+/* This function looks up the closest available resolution. */
+static int mfld_isp_try_fmt_cap(struct file *file, void *fh,
+                               struct v4l2_format *f)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       __u32 out_width = f->fmt.pix.width;
+       __u32 out_height = f->fmt.pix.height;
+       __u32 pixelformat = f->fmt.pix.pixelformat;
+       __u32 in_width, in_height;
+       int ret;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "Wrong v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       mfld_isp_dbg(KERN_DEBUG, "width %d, height %d, format %x\n",
+                    out_width, out_height, pixelformat);
+
+#if    (!defined(IMAGE_FROM_FILE) && !defined(IMAGE_FROM_TPG))
+       if (get_current_camera(ci) == NULL)
+               return -EINVAL;
+
+       ret = v4l2_subdev_call(ci->cameras[ci->camera_curr].camera,
+                              video, try_fmt, f);
+       if (ret)
+               return ret;
+
+       in_width = f->fmt.pix.width;
+       in_height = f->fmt.pix.height;
+
+       mfld_isp_dbg(KERN_DEBUG, "try_fmt, width %d, height %d\n",
+                    in_width, in_height);
+#endif
+       if ((in_width < out_width) &&
+           (in_height < out_height)) {
+               out_width = in_width;
+               out_height = in_height;
+       }
+
+       if (out_width < MFLD_WIDTH_RESTRICT ||
+           out_height < MFLD_HEIGHT_RESTRICT)
+               return -EINVAL;
+
+       out_width = (out_width & ~(MFLD_WIDTH_RESTRICT - 1));
+       out_height = (out_height & ~(MFLD_HEIGHT_RESTRICT - 1));
+
+       mfld_isp_dbg(KERN_DEBUG, "Restrict width %d, height %d\n",
+                    out_width, out_height);
+
+       f->fmt.pix.width = out_width;
+       f->fmt.pix.height = out_height;
+
+       if (!is_pixelformat_supported(pixelformat)) {
+               mfld_isp_dbg(KERN_ERR, "unsupported pixelformat!\n");
+               /* only support 1 pixelformat now */
+               pixelformat = SUPPORTED_FMTS[0].pixelformat;
+       }
+       f->fmt.pix.pixelformat = pixelformat;
+
+       return 0;
+}
+
+static int mfld_isp_s_fmt_cap(struct file *file, void *fh,
+                               struct v4l2_format *f)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       struct v4l2_format snr_fmt;
+       struct mfld_ci_mipi_camera *mipi_info;
+       struct sh_css_frame_info output_info, raw_output_info;
+       __u32 width = f->fmt.pix.width;
+       __u32 height = f->fmt.pix.height;
+       __u32 pixelformat = f->fmt.pix.pixelformat;
+       __u32 effective_input_width;
+       __u32 effective_input_height;
+       int ret;
+
+       mfld_isp_dbg(KERN_DEBUG, "%s\n", __func__);
+
+       if ((f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+           (f->type != V4L2_BUF_TYPE_PRIVATE)) {
+               mfld_isp_dbg(KERN_ERR, "Wrong v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       /* Set online processing */
+       if (f->type == V4L2_BUF_TYPE_PRIVATE)
+               ci->online_process = 0;
+       else
+               ci->online_process = 1;
+
+       if (!ci->bayer_downscaling) {
+#if    (!defined(IMAGE_FROM_FILE) && !defined(IMAGE_FROM_TPG))
+               snr_fmt = *f;
+               snr_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               snr_fmt.fmt.pix.height += 10;
+               snr_fmt.fmt.pix.width += 8;
+
+               ret = v4l2_subdev_call(ci->cameras[ci->camera_curr].camera,
+                                       video, s_fmt, &snr_fmt);
+               if (ret) {
+                       mfld_isp_dbg(KERN_ERR,
+                                       "call s_fmt for sensor failed\n");
+                       return ret;
+               }
+
+               ci->snr_width = snr_fmt.fmt.pix.width;
+               ci->snr_height = snr_fmt.fmt.pix.height;
+               ci->snr_pixelformat = snr_fmt.fmt.pix.pixelformat;
+
+               mfld_isp_dbg(KERN_DEBUG,
+                       "snr_width %d, snr_height %d, pixelfmt %d\n",
+                       ci->snr_width, ci->snr_height, ci->snr_pixelformat);
+
+               if (ci->snr_width < MFLD_WIDTH_RESTRICT ||
+                   ci->snr_height < MFLD_HEIGHT_RESTRICT)
+                       return -EINVAL;
+#endif
+       } else {
+               ci->snr_width = ci->snr_max_width;
+               ci->snr_height = ci->snr_max_height;
+       }
+
+       width = (width & ~(MFLD_WIDTH_RESTRICT - 1));
+       height = (height & ~(MFLD_HEIGHT_RESTRICT - 1));
+
+#if    (!defined(IMAGE_FROM_FILE) && !defined(IMAGE_FROM_TPG))
+       if ((ci->snr_width < width) &&
+           (ci->snr_height < height)) {
+               width = ci->snr_width;
+               height = ci->snr_height;
+       }
+
+       if (((ci->snr_width - 8) > width) &&
+           ((ci->snr_height - 10) > height) &&
+           (ci->bayer_downscaling)) {
+               mfld_isp_dbg(KERN_DEBUG, "Enable Bayer Downscaling\n");
+               effective_input_width = ci->snr_width - 8;
+               effective_input_height = ci->snr_height - 10;
+
+               /*effective_input_width = 1280;*/
+               /*effective_input_height = 720;*/
+       } else {
+               effective_input_width = width;
+               effective_input_height = height;
+       }
+#endif
+
+       ci->pixelformat  = pixelformat;
+       ci->sh_pixelformat = v4l2_fmt_to_sh_fmt(ci->pixelformat);
+
+#ifdef IMAGE_FROM_FILE
+       mfld_isp_dbg(KERN_DEBUG, "alloc IMAGE data for ISP test.\n");
+       mfld_isp_dbg(KERN_DEBUG,
+                    "The size we expect %d\n", ci->width * ci->height * 2);
+       mfld_isp_dbg(KERN_INFO, "The size we got %d\n", g_input_file_size);
+       ci->image_file = g_input_file_data;
+       if (!ci->image_file) {
+               mfld_isp_dbg(KERN_ERR, "Load image file failed.\n");
+               return -1;
+       }
+       if ((ci->width < IMAGE_W) && (ci->height < IMAGE_H)) {
+               ci->input_file = vmalloc(ci->width * ci->height * 2);
+               if (!ci->input_file) {
+                       mfld_isp_dbg(KERN_ERR,
+                                    "Failed to alloc input_file memory\n");
+                       return -1;
+               }
+
+               mfld_isp_resize_image((unsigned short *)ci->image_file,
+                               (unsigned short *)ci->input_file, 0, 0,
+                               IMAGE_W, IMAGE_H, ci->width, ci->height);
+       }
+#endif
+
+#if    (!defined(IMAGE_FROM_FILE) && !defined(IMAGE_FROM_TPG))
+       mfld_isp_dbg(KERN_DEBUG, "snr_width %d, snr_height %d\n",
+                    ci->snr_width, ci->snr_height);
+       sh_css_input_set_resolution(ci->snr_width, ci->snr_height);
+
+       mfld_isp_dbg(KERN_DEBUG, "Setup sensor specifc configure for MIPI\n");
+       mipi_info = to_sensor_mipi_info(ci->cameras[ci->camera_curr].camera);
+       if (mipi_info) {
+               mfld_isp_dbg(KERN_DEBUG,
+                       "MIPI info from camera sensor: bayer %d"
+                       " format %d\n", mipi_info->raw_bayer_order,
+                       mipi_info->input_format);
+               mfld_isp_dbg(KERN_DEBUG, "sensor mipilane - %d\n",
+                       mipi_info->num_of_lane);
+               sh_css_input_set_bayer_order(mipi_info->raw_bayer_order);
+               sh_css_input_set_format(mipi_info->input_format);
+               sh_css_input_configure_port(mipi_info->port,
+                                          mipi_info->num_of_lane,
+                                          0xffff4);
+
+       } else {
+               /*sh_css_input_set_bayer_order(sh_css_bayer_order_rggb);*/
+               mfld_isp_dbg(KERN_DEBUG, "no sensor config info\n");
+               sh_css_input_set_bayer_order(sh_css_bayer_order_bggr);
+               /*sh_css_input_set_bayer_order(sh_css_bayer_order_grbg); */
+               sh_css_input_set_format(sh_css_input_format_raw_10);
+#ifdef MIPI_LANE_4
+               mfld_isp_dbg(KERN_DEBUG, "MIPI 4 lane\n");
+               sh_css_input_configure_port(sh_css_mipi_port_4lane, 4, 0xffff4);
+#endif
+#ifdef MIPI_LANE_2
+               mfld_isp_dbg(KERN_INFO, "MIPI 2 lane\n");
+               sh_css_input_configure_port(sh_css_mipi_port_4lane, 2, 0xffff4);
+#endif
+#ifdef MIPI_LANE_1
+               mfld_isp_dbg(KERN_INFO, "MIPI 1 lane\n");
+               sh_css_input_configure_port(sh_css_mipi_port_4lane, 1, 0xffff4);
+#endif
+       }
+#else
+       sh_css_input_set_resolution(width, height);
+
+#endif
+
+       return_on_css_error(sh_css_input_set_effective_resolution
+                           (effective_input_width, effective_input_height));
+
+       switch (ci->run_mode) {
+       case CI_MODE_PREVIEW:
+               return_on_css_error(sh_css_preview_configure_output
+                                       (width, height, ci->sh_pixelformat));
+               return_on_css_error(sh_css_preview_set_isp_parameters
+                                       (ci->isp_params));
+               return_on_css_error(sh_css_preview_get_output_frame_info
+                                       (&output_info));
+               break;
+       case CI_MODE_VIDEO:
+               return_on_css_error(sh_css_video_configure_viewfinder
+                                       (vf_width, vf_height, vf_format));
+               return_on_css_error(sh_css_video_configure_output
+                                       (width, height, ci->sh_pixelformat));
+               return_on_css_error(sh_css_video_set_isp_parameters
+                                       (ci->isp_params));
+               return_on_css_error(sh_css_video_get_output_frame_info
+                                       (&output_info));
+               break;
+       default:
+#ifdef GDC_EN
+               sh_css_capture_set_mode(sh_css_capture_mode_advanced);
+#endif
+
+#ifdef XNR_EN
+               sh_css_capture_enable_xnr(1);
+#endif
+
+               if (ci->sh_pixelformat == sh_css_frame_format_vraw16 ||
+                       ci->sh_pixelformat == sh_css_frame_format_raw16 ||
+                       ci->sh_pixelformat == sh_css_frame_format_raw8) {
+                       mfld_isp_dbg(KERN_WARNING, "set capture raw mode\n");
+                       return_on_css_error(sh_css_capture_set_mode
+                                               (sh_css_capture_mode_raw));
+               }
+
+               return_on_css_error(sh_css_capture_enable_online
+                                       (ci->online_process));
+
+               return_on_css_error(sh_css_capture_configure_viewfinder
+                                       (vf_width, vf_height, vf_format));
+               return_on_css_error(sh_css_capture_configure_output
+                                       (width, height, ci->sh_pixelformat));
+               return_on_css_error(sh_css_capture_set_isp_parameters
+                                       (ci->isp_params));
+
+               return_on_css_error(sh_css_capture_get_output_frame_info
+                                       (&output_info));
+
+               if (!ci->online_process)
+                       return_on_css_error
+                           (sh_css_capture_get_output_raw_frame_info
+                                           (&raw_output_info));
+
+               if (ci->run_mode != CI_MODE_STILL_CAPTURE) {
+                       mfld_isp_dbg(KERN_ERR,
+                                       "Need to set the running mode first\n");
+                       ci->run_mode = CI_MODE_STILL_CAPTURE;
+               }
+               break;
+       }
+
+       ci->width = width;
+       ci->height = height;
+       ci->pixeldepth = get_pixel_depth(pixelformat);
+       ci->bytesperline = (ci->pixeldepth * output_info.padded_width) / 8;
+       ci->framesize = height * ci->bytesperline;
+       ci->imagesize = PAGE_ALIGN(ci->framesize);
+       f->fmt.pix.sizeimage = ci->imagesize;
+       f->fmt.pix.width = width;
+       f->fmt.pix.height = height;
+       mfld_isp_dbg(KERN_DEBUG, "raw width %d, raw height %d\n",
+               raw_output_info.padded_width, raw_output_info.height);
+       f->fmt.pix.priv = PAGE_ALIGN(raw_output_info.padded_width *
+                                    raw_output_info.height * 2);
+
+       mfld_isp_dbg(KERN_DEBUG, "width = %d, height = %d, fourcc = %s\n",
+                    ci->width, ci->height,
+                    get_ci_format(ci->pixelformat)->description);
+
+       mfld_isp_dbg(KERN_DEBUG, "pixeldepth = %d, frame_size = %d\n",
+                    ci->pixeldepth, ci->framesize);
+       mfld_isp_dbg(KERN_DEBUG, "raw size priv = %d\n", f->fmt.pix.priv);
+       return 0;
+}
+
+static int mfld_isp_enum_framesizes(struct file *file, void *fh,
+                                       struct v4l2_frmsizeenum *arg)
+{
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_enum_framesizes\n");
+
+       if (arg->index < 0 || arg->index >= SUPPORTED_RESOLUTION_NUM)
+               return -EINVAL;
+
+       if (!is_pixelformat_supported(arg->pixel_format))
+               return -EINVAL;
+
+       arg->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+       arg->discrete.width = SUPPORTED_RESOLUTIONS[arg->index].width;
+       arg->discrete.height = SUPPORTED_RESOLUTIONS[arg->index].height;
+
+       return 0;
+}
+
+static int mfld_isp_enum_frameintervals(struct file *file, void *fh,
+                                       struct v4l2_frmivalenum *arg)
+{
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_enum_frameintervals\n");
+
+       if (arg->index < 0 || arg->index >= SUPPORTED_RESOLUTION_NUM)
+               return -EINVAL;
+
+       if (!is_pixelformat_supported(arg->pixel_format))
+               return -EINVAL;
+
+       if (!is_resolution_supported(arg->width, arg->height))
+               return -EINVAL;
+
+       arg->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       arg->discrete.numerator = 1;
+       arg->discrete.denominator = 30;
+
+       return 0;
+}
+
+static void add_frame_to_queue(struct fifo *queue, int frame)
+{
+       queue->data[queue->back] = frame;
+       queue->back = (queue->back + 1) % (CI_MAX_BUF_NUM + 1);
+}
+
+static int frame_queue_empty(struct fifo *queue)
+{
+       return queue->front == queue->back;
+}
+
+static int remove_frame_from_queue(struct fifo *queue)
+{
+       int frame;
+
+       if (frame_queue_empty(queue))
+               return -1;
+
+       frame = queue->data[queue->front];
+       queue->front = (queue->front + 1) % (CI_MAX_BUF_NUM + 1);
+       return frame;
+}
+
+static void init_frame_queue(struct fifo *queue)
+{
+       int i;
+       for (i = 0; i < CI_MAX_BUF_NUM; i++) {
+               queue->data[i] = -1;
+               queue->info[i].state = S_UNUSED;
+               queue->info[i].flags = 0;
+       }
+       queue->front = 0;
+       queue->back = 0;
+}
+
+static int mfld_isp_reqbufs(struct file *file, void *fh,
+                               struct v4l2_requestbuffers *req)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       int i, ret = 0;
+       struct sh_css_frame_info out_info, vf_info;
+       struct sh_css_frame *frame;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_reqbufs %d\n", req->count);
+
+       if (req->count == 0) {
+               if (ci->buf_allocated) {
+                       for (i = 0; i < ci->bufnum; i++)
+                               free_buffer(ci->imagebuf[i]);
+                       kfree(ci->imagebuf);
+                       ci->imagebuf = NULL;
+                       if (ci->vf_frame) {
+                               sh_css_frame_free(ci->vf_frame);
+                               ci->vf_frame = NULL;
+                       }
+                       ci->buf_allocated = 0;
+               }
+               return 0;
+       }
+
+       if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupported v4l2 buf type\n");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       if ((req->memory != V4L2_MEMORY_MMAP) &&
+               (req->memory != V4L2_MEMORY_USERPTR)) {
+               mfld_isp_dbg(KERN_ERR, "unsupported v4l2 memory type\n");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       req->count = ci->bufnum = MIN(req->count, CI_MAX_BUF_NUM);
+
+       init_frame_queue(&ci->buf_queue);
+
+       /* prepare buffer handles for buffers */
+       ci->imagebuf = kmalloc(sizeof(struct ci_buffer *)*ci->bufnum,
+                               GFP_KERNEL);
+       if (ci->imagebuf == NULL) {
+               mfld_isp_dbg(KERN_ERR, "out of memory\n");
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       for (i = 0; i < ci->bufnum; i++)
+               ci->imagebuf[i] = NULL;
+
+       /*Allocate the frame buffer to be used */
+       mfld_isp_dbg(KERN_DEBUG, "allocate_frame ... ");
+       switch (ci->run_mode) {
+       case CI_MODE_STILL_CAPTURE:
+               if (ci->sh_pixelformat != sh_css_frame_format_vraw16 &&
+                       ci->sh_pixelformat != sh_css_frame_format_raw8 &&
+                       ci->sh_pixelformat != sh_css_frame_format_raw16) {
+                       goto_on_css_error
+                               (sh_css_capture_get_viewfinder_frame_info
+                                       (&vf_info), ret, error);
+                       goto_on_css_error
+                               (sh_css_frame_allocate_from_info
+                                       (&ci->vf_frame, &vf_info), ret,
+                                               error);
+               }
+               goto_on_css_error(sh_css_capture_get_output_frame_info
+                                       (&out_info), ret, error);
+               break;
+       case CI_MODE_VIDEO:
+               goto_on_css_error(sh_css_video_get_viewfinder_frame_info
+                                       (&vf_info), ret, error);
+               goto_on_css_error(sh_css_video_get_output_frame_info(&out_info),
+                                       ret, error);
+               goto_on_css_error(sh_css_frame_allocate_from_info
+                                       (&ci->vf_frame, &vf_info), ret, error);
+               break;
+       case CI_MODE_PREVIEW:
+               goto_on_css_error(sh_css_preview_get_output_frame_info
+                                       (&out_info), ret, error);
+               break;
+       }
+
+       ci->buf_type = req->memory;
+
+       /*
+        * for user pointer type, buffers are not really allcated here,
+        * buffers are setup in QBUF operation through v4l2_buffer structure
+        */
+       if (req->memory == V4L2_MEMORY_USERPTR) {
+               mfld_isp_dbg(KERN_DEBUG, "user pointer, not really allocate"
+                               " memory here.\n");
+               return 0;
+       }
+
+       /* allocate output frames, wrap them and store in buffer. */
+       for (i = 0; i < ci->bufnum; i++) {
+               mfld_isp_dbg(KERN_ERR, "%s, %d\n", __func__, __LINE__);
+               goto_on_css_error(sh_css_frame_allocate_from_info(&frame,
+                                                                &out_info),
+                                 ret, error);
+               ci->imagebuf[i] = alloc_buffer(frame);
+               if (!ci->imagebuf[i]) {
+                       mfld_isp_dbg(KERN_ERR, "%s, %d\n", __func__, __LINE__);
+                       ret = -ENOMEM;
+                       goto error;
+               }
+       }
+
+       ci->buf_allocated = 1;
+
+       mfld_isp_dbg(KERN_DEBUG, "request  buffer done\n");
+
+       return 0;
+error:
+       if (ci->imagebuf) {
+               for (i = 0; i < ci->bufnum; i++) {
+                       if (ci->imagebuf[i])
+                               free_buffer(ci->imagebuf[i]);
+               }
+               kfree(ci->imagebuf);
+       }
+       if (ci->vf_frame)
+               sh_css_frame_free(ci->vf_frame);
+
+       return ret;
+}
+
+static int mfld_isp_querybuf(struct file *file, void *fh,
+                               struct v4l2_buffer *buf)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       int index = buf->index;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_querybuf: index = %d\n", index);
+
+       if (index < 0 || index >= ci->bufnum) {
+               mfld_isp_dbg(KERN_ERR, "wrong index, only support 1 buf now\n");
+               return -EINVAL;
+       }
+
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       if (ci->imagebuf == NULL) {
+               mfld_isp_dbg(KERN_ERR, "buffer not allocated\n");
+               return -EINVAL;
+       }
+
+       memset(buf, 0, sizeof(*buf));
+       buf->index = index;
+       buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf->length = ci->imagesize;
+       buf->bytesused = 0;     /* this should be given in VIDIOC_DQBUF */
+       buf->memory = ci->buf_type;
+
+       mfld_isp_dbg(KERN_DEBUG, "ci_querybuf: length = %d, , index=%d\n",
+                    buf->length, buf->index);
+
+       switch (buf->memory) {
+       case V4L2_MEMORY_MMAP:
+               buf->m.offset = index * ci->imagesize;
+               break;
+       case V4L2_MEMORY_USERPTR:
+               mfld_isp_dbg(KERN_DEBUG, "cannot query USERPTR type buf.\n");
+               break;
+       default:
+               mfld_isp_dbg(KERN_ERR, "invalid buf type.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mfld_isp_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       __u32 index;
+       __u32 length;
+       unsigned long userptr;
+       __u32 pgnr;
+
+       __u32 width, height;
+
+       int err = 0;
+       struct sh_css_frame_info out_info;
+       struct sh_css_frame *handle;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_qbuf\n");
+
+       /* do nothing now */
+       index = buf->index;
+       length = buf->length;
+       userptr = buf->m.userptr;
+
+       width = ci->width;
+       height = ci->height;
+
+       if (index >= ci->bufnum) {
+               mfld_isp_dbg(KERN_ERR, "buf index out of range\n");
+               return -EINVAL;
+       }
+
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       if (ci->imagebuf == NULL) {
+               mfld_isp_dbg(KERN_ERR, "buffer not allocated\n");
+               return -EINVAL;
+       }
+
+       if (ci->imagebuf[index] &&
+               (ci->imagebuf[index]->flags & V4L2_BUF_FLAG_QUEUED)) {
+               mfld_isp_dbg(KERN_ERR, "buffer %d already in queue\n", index);
+               return -EINVAL;
+       }
+
+       switch (buf->memory) {
+       case V4L2_MEMORY_MMAP:
+               if (!ci->buf_allocated) {
+                       mfld_isp_dbg(KERN_ERR, "buffers not allocated.\n");
+                       return -EINVAL;
+               }
+               ci->imagebuf[index]->idx = index;
+               break;
+       case V4L2_MEMORY_USERPTR:
+               if ((length & (~(PAGE_SIZE - 1))) != length)
+                       mfld_isp_dbg(KERN_ALERT, "user buffer's length"
+                                       " not page-aligned.\n");
+
+               pgnr = (length + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
+               mfld_isp_dbg(KERN_DEBUG, "buffer %d: addr = 0x%x,"
+                               " length = %d, pgnr = %d\n", index,
+                               (unsigned int)userptr, length, pgnr);
+
+               if ((ci->imagebuf[index]) &&
+                       (ci->imagebuf[index]->userptr) &&
+                       (ci->imagebuf[index]->userptr == userptr))
+                       break;
+
+               switch (ci->run_mode) {
+               case CI_MODE_STILL_CAPTURE:
+                       err = sh_css_capture_get_output_frame_info(&out_info);
+                       break;
+               case CI_MODE_PREVIEW:
+                       err = sh_css_preview_get_output_frame_info(&out_info);
+                       break;
+               case CI_MODE_VIDEO:
+                       err = sh_css_video_get_output_frame_info(&out_info);
+                       break;
+               }
+               if (err) {
+                       mfld_isp_dbg(KERN_ERR, "get_output_frame_info error\n");
+                       return -1;
+               }
+
+               if ((ci->imagebuf[index]) &&
+                       (ci->imagebuf[index]->userptr) &&
+                       (ci->imagebuf[index]->userptr != userptr)) {
+                       sh_css_frame_free(ci->imagebuf[index]->handle);
+                       free_buffer(ci->imagebuf[index]);
+               }
+
+               mfld_isp_dbg(KERN_DEBUG, "%s, %d\n", __func__, __LINE__);
+               hrt_isp_css_mm_set_user_ptr(userptr, pgnr);
+               sh_css_frame_allocate_from_info(&handle, &out_info);
+               hrt_isp_css_mm_set_user_ptr(0, 0);
+               mfld_isp_dbg(KERN_DEBUG, "%s, %d\n", __func__, __LINE__);
+               if (handle == NULL) {
+                       mfld_isp_dbg(KERN_ERR, "Error to allocate"
+                                       " frame for capture\n");
+                       return -1;
+               }
+
+               ci->imagebuf[index] = alloc_user_buffer(handle, userptr,
+                                                       pgnr, index);
+
+               break;
+       default:
+               mfld_isp_dbg(KERN_ERR, "unsupported memory type...\n");
+               return -EINVAL;
+       }
+
+       ci->buf_queue.info[index].state = S_QUEUED;
+       add_frame_to_queue(&ci->buf_queue, index);
+
+       buf->flags &= ~V4L2_BUF_FLAG_DONE;
+       buf->flags |= V4L2_BUF_FLAG_QUEUED;
+       buf->flags |= V4L2_BUF_FLAG_MAPPED;
+
+       return 0;
+}
+
+static int mfld_isp_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       struct ci_buffer *ci_buf;
+       unsigned int dvs_envelope_w, dvs_envelope_h;
+       struct sh_css_frame *raw_frame;
+       u32 msg_ret;
+       u32 term_en_count;
+       int ret;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_dqbuf\n");
+
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       if (ci->imagebuf == NULL) {
+               mfld_isp_dbg(KERN_ERR, "buffer not allocated\n");
+               return -EINVAL;
+       }
+
+
+       buf->index = remove_frame_from_queue(&ci->buf_queue);
+
+       mfld_isp_dbg(KERN_DEBUG, "dqueue 1 buf from buffer queue index %d...\n",
+                    buf->index);
+       ci_buf = ci->imagebuf[buf->index];
+       if (ci_buf == NULL) {
+               mfld_isp_dbg(KERN_ERR, "no available buffer in buffer queue\n");
+               return -EINVAL;
+       }
+
+       if (buf->memory != ci_buf->buf_type) {
+               mfld_isp_dbg(KERN_ERR, "buffer type is not the same as created"
+                               " buffer type.\n");
+               return -EINVAL;
+       }
+
+       /* fill user space struct */
+       buf->index = ci_buf->idx;
+       buf->bytesused = ci->framesize;
+       buf->length = ci->imagesize;
+
+       if (buf->memory == V4L2_MEMORY_MMAP) {
+               buf->m.offset = ci_buf->idx * ci->imagesize;
+       } else if (buf->memory == V4L2_MEMORY_USERPTR) {
+               buf->m.userptr = ci_buf->userptr;
+       } else {
+               mfld_isp_dbg(KERN_ERR, "unsupported buffer type.\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Kai:
+        *
+        * setup output_frame here.
+        */
+       ci->regular_output_frame = ci_buf->handle;
+
+#ifdef PUNIT_CAMERA_BUSY
+       u32 msg_ret;
+       /* Set camera_busy bit in Punit */
+       msg_ret = MSG_READ32(0x04, 0x72);
+       msg_ret |= 0x100;
+       MSG_WRITE32(0x04, 0x72, msg_ret);
+#endif
+       /* for 4-lane configuration */
+       msg_ret = MSG_READ32(0x09, 0x3);
+       term_en_count = (msg_ret & 0x00f00000) >> 20;
+       mfld_isp_dbg(KERN_DEBUG, "MSG_RET = %x, TERM_EN_COUNT = %x\n",
+                    msg_ret, term_en_count);
+       if (term_en_count != 0xF) {
+               term_en_count = 0xF;
+               msg_ret = (msg_ret & 0xff0fffff) |
+                   ((term_en_count & 0xf) << 20);
+               MSG_WRITE32(0x09, 0x3, msg_ret);
+       }
+
+       /* for 1-lane configuration */
+       msg_ret = MSG_READ32(0x09, 0x3);
+       term_en_count = (msg_ret & 0x000f0000) >> 16;
+       mfld_isp_dbg(KERN_DEBUG, "MSG_RET = %x, TERM_EN_COUNT = %x\n",
+                    msg_ret, term_en_count);
+       if (term_en_count != 0xF) {
+               term_en_count = 0xF;
+               msg_ret = (msg_ret & 0xfff0ffff) |
+                   ((term_en_count & 0xf) << 16);
+               MSG_WRITE32(0x09, 0x3, msg_ret);
+       }
+
+
+       switch (ci->run_mode) {
+       case CI_MODE_STILL_CAPTURE:
+               sh_css_capture_start(ci->regular_output_frame, ci->vf_frame);
+               break;
+       case CI_MODE_PREVIEW:
+               sh_css_preview_start(ci->regular_output_frame);
+               break;
+               /*case CI_MODE_VIDEO: */
+               /*sh_css_video_start(NULL, ci->regular_output_frame,
+                * ci->vf_frame); */
+               /*break; */
+       }
+
+       if (ci->run_mode == CI_MODE_VIDEO) {
+               if (ci->video_dis_en) {
+                       dvs_envelope_w = ci->width / 10;
+                       dvs_envelope_h = ci->height / 10;
+                       sh_css_video_set_dis_vector(ci->dis_x, ci->dis_y);
+                       sh_css_video_set_dis_envelope(dvs_envelope_w,
+                                                    dvs_envelope_h);
+               }
+               sh_css_video_start(NULL, ci->regular_output_frame,
+                                 ci->vf_frame);
+       }
+#if    (!defined(IMAGE_FROM_TPG))
+       mfld_isp_dbg(KERN_DEBUG, "Stream on camera sensor\n");
+       /* stream on the sensor */
+       if (ci->streaming != 1) {
+               ret = v4l2_subdev_call(ci->cameras[ci->camera_curr].camera,
+                              video, s_stream, 1);
+               if (ret) {
+                       mfld_isp_dbg(KERN_ERR, "stream on sensor err.\n");
+                       return ret;
+               }
+               ci->streaming = 1;
+       }
+#endif
+
+       sh_css_wait_for_completion();
+
+       buf->flags &= ~V4L2_BUF_FLAG_DONE;
+       buf->flags &= ~V4L2_BUF_FLAG_QUEUED;
+       buf->flags |= V4L2_BUF_FLAG_MAPPED;
+
+       if (ci->online_process == 0) {
+               raw_frame = sh_css_get_raw_frame();
+               mfld_isp_dbg(KERN_ERR, "The RAW virtual address is %x\n",
+                            (unsigned int)raw_frame);
+               sh_css_convert_raw_frame(raw_frame, ci->width,
+                                        (ci->height + 8));
+       }
+
+#ifdef PUNIT_CAMERA_BUSY
+       /* Free camera_busy bit */
+       msg_ret = MSG_READ32(0x04, 0x72);
+       msg_ret &= ~0x100;
+       MSG_WRITE32(0x04, 0x72, msg_ret);
+#endif
+
+       return 0;
+}
+
+static int mfld_isp_streamon(struct file *file, void *fh,
+                               enum v4l2_buf_type type)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_streamon\n");
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       if (ci->imagebuf == NULL) {
+               mfld_isp_dbg(KERN_ERR, "buffer not allocated\n");
+               return -EINVAL;
+       }
+
+#if    (!defined(IMAGE_FROM_TPG))
+       /*mfld_isp_dbg(KERN_INFO, "Stream on camera sensor\n");*/
+       /*[> stream on the sensor <]*/
+       /*ret = v4l2_subdev_call(ci->cameras[ci->camera_curr].camera,*/
+                              /*video, s_stream, 1);*/
+       /*if (ret) {*/
+               /*mfld_isp_dbg(KERN_ERR, "stream on sensor err.\n");*/
+               /*return ret;*/
+       /*}*/
+#endif
+
+       return 0;
+}
+
+static int mfld_isp_streamoff(struct file *file, void *fh,
+                               enum v4l2_buf_type type)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_streamoff\n");
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       if (!ci->streaming)
+               return -1;
+
+       ci->streaming = 0;
+
+#if (!defined(IMAGE_FROM_TPG))
+       v4l2_subdev_call(ci->cameras[ci->camera_curr].camera, video,
+                        s_stream, 0);
+#endif
+
+       return 0;
+}
+
+static int mfld_isp_g_ctrl(struct file *file, void *fh,
+                               struct v4l2_control *control)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       int i, ret = -EINVAL;
+
+       for (i = 0; i < SUPPORTED_CTRL_NUM; i++) {
+               if (ci_v4l2_controls[i].id == control->id) {
+                       ret = 0;
+                       goto next;
+               }
+       }
+
+next:
+       if (ret)
+               return ret;
+
+       switch (control->id) {
+       case V4L2_CID_COLORFX:
+               ret = mfld_isp_color_effect(ci, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION:
+               ret = mfld_isp_bad_pixel(ci, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC:
+               ret = mfld_isp_gdc_cac(ci, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_VIDEO_STABLIZATION:
+               ret = mfld_isp_video_stable(ci, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_FIXED_PATTERN_NR:
+               ret = mfld_isp_fixed_pattern(ci, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION:
+               ret = mfld_isp_false_color(ci, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_SHADING_CORRECTION:
+               ret = mfld_isp_shading_correction(ci, 0, &control->value);
+               break;
+       }
+
+       /* Right now we leave this contrl function null */
+       control->value = 0;
+       return ret;
+}
+
+static int mfld_isp_s_ctrl(struct file *file, void *fh,
+                               struct v4l2_control *control)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       int i, ret = -EINVAL;
+
+       for (i = 0; i < SUPPORTED_CTRL_NUM; i++) {
+               if (ci_v4l2_controls[i].id == control->id) {
+                       ret = 0;
+                       goto next;
+               }
+       }
+
+next:
+       if (ret)
+               return ret;
+
+       switch (control->id) {
+       case V4L2_CID_COLORFX:
+               ret = mfld_isp_color_effect(ci, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION:
+               ret = mfld_isp_bad_pixel(ci, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC:
+               ret = mfld_isp_gdc_cac(ci, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_VIDEO_STABLIZATION:
+               ret = mfld_isp_video_stable(ci, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_FIXED_PATTERN_NR:
+               ret = mfld_isp_fixed_pattern(ci, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION:
+               ret = mfld_isp_false_color(ci, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_SHADING_CORRECTION:
+               ret = mfld_isp_shading_correction(ci, 1, &control->value);
+               break;
+       }
+       /* Right now we leave this contrl function null */
+       return ret;
+}
+
+static int mfld_isp_queryctl(struct file *file, void *fh,
+                               struct v4l2_queryctrl *qc)
+{
+       int i;
+       int ret = -EINVAL;
+
+       if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL)
+               return ret;
+
+       for (i = 0; i < SUPPORTED_CTRL_NUM; i++) {
+               if (ci_v4l2_controls[i].id == qc->id) {
+                       memcpy(qc, &ci_v4l2_controls[i],
+                               sizeof(struct v4l2_queryctrl));
+                       qc->reserved[0] = 0;
+                       qc->flags = V4L2_CTRL_FLAG_DISABLED;
+                       ret = 0;
+                       goto exit;
+               }
+       }
+exit:
+       return ret;
+}
+
+static int mfld_isp_g_ext_ctrls(struct file *file, void *fh,
+                               struct v4l2_ext_controls *c)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       int i;
+       int ret = 0;
+
+       if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
+               for (i = 0; i < c->count; i++) {
+                       ctrl.id = c->controls[i].id;
+                       ctrl.value = c->controls[i].value;
+                       ret = mfld_isp_g_ctrl(file, fh, &ctrl);
+                       c->controls[i].value = ctrl.value;
+                       if (ret) {
+                               c->error_idx = i;
+                               break;
+                       }
+               }
+               return ret;
+       }
+
+       if (c->ctrl_class == V4L2_CTRL_CLASS_CAMERA) {
+               for (i = 0; i < c->count; i++) {
+                       ctrl.id = c->controls[i].id;
+                       ctrl.value = c->controls[i].value;
+                       switch (ctrl.id) {
+                       case V4L2_CID_EXPOSURE_ABSOLUTE:
+                       case V4L2_CID_ISO_ABSOLUTE:
+                       case V4L2_CID_APERTURE_ABSOLUTE:
+                       case V4L2_CID_SS_EXPOSURE_ABSOLUTE:
+                       case V4L2_CID_SS_ISO_ABSOLUTE:
+                       case V4L2_CID_SS_APERTURE_ABSOLUTE:
+                               ret =
+                                       v4l2_subdev_call(ci->cameras
+                                               [ci->camera_curr].camera,
+                                               core, g_ctrl, &ctrl);
+                               break;
+                       case V4L2_CID_FOCUS_ABSOLUTE:
+                       case V4L2_CID_FOCUS_AUTO:
+                               if (ci->cameras[ci->camera_curr].type ==
+                                       CAMERA_SENSOR_MOTOR)
+                                       ret =
+                                               v4l2_subdev_call(ci->cameras
+                                               [ci->camera_curr].motor,
+                                               core, g_ctrl,
+                                               &ctrl);
+                               else
+                                       ret =
+                                               v4l2_subdev_call(ci->cameras
+                                               [ci->camera_curr].camera,
+                                               core, g_ctrl,
+                                               &ctrl);
+                               break;
+                       case V4L2_CID_FLASH_DELAY:
+                       case V4L2_CID_FLASH_DURATION:
+                       case V4L2_CID_FLASH_STROBE:
+                       case V4L2_CID_FLASH_TIMEOUT:
+                       case V4L2_CID_FLASH_INTENSITY:
+                       case V4L2_CID_TORCH_INTENSITY:
+                       case V4L2_CID_INDICATOR_INTENSITY:
+                               if (ci->xenon_flash)
+                                       ret = v4l2_subdev_call(ci->xenon_flash,
+                                                       core, g_ctrl,
+                                                       &ctrl);
+                               else
+                                       ret = v4l2_subdev_call(ci->led_flash,
+                                                       core, g_ctrl,
+                                                       &ctrl);
+                               break;
+                       case V4L2_CID_ZOOM_ABSOLUTE:
+                               /* add digital zoom code here */
+                               ret = mfld_isp_digital_zoom(ci, 0, &ctrl.value);
+                               break;
+                       }
+                       c->controls[i].value = ctrl.value;
+                       if (ret) {
+                               c->error_idx = i;
+                               break;
+                       }
+               }
+               return ret;
+       }
+       return -EINVAL;
+}
+
+static int mfld_isp_s_ext_ctrls(struct file *file, void *fh,
+                               struct v4l2_ext_controls *c)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       int i;
+       int ret = 0;
+
+       if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
+               for (i = 0; i < c->count; i++) {
+                       ctrl.id = c->controls[i].id;
+                       ctrl.value = c->controls[i].value;
+                       ret = mfld_isp_s_ctrl(file, fh, &ctrl);
+                       c->controls[i].value = ctrl.value;
+                       if (ret) {
+                               c->error_idx = i;
+                               break;
+                       }
+               }
+               return ret;
+       }
+
+       if (c->ctrl_class == V4L2_CTRL_CLASS_CAMERA) {
+               for (i = 0; i < c->count; i++) {
+                       ctrl.id = c->controls[i].id;
+                       ctrl.value = c->controls[i].value;
+                       switch (ctrl.id) {
+                       case V4L2_CID_EXPOSURE_ABSOLUTE:
+                       case V4L2_CID_ISO_ABSOLUTE:
+                       case V4L2_CID_APERTURE_ABSOLUTE:
+                       case V4L2_CID_SS_EXPOSURE_ABSOLUTE:
+                       case V4L2_CID_SS_ISO_ABSOLUTE:
+                       case V4L2_CID_SS_APERTURE_ABSOLUTE:
+                               ret =
+                                       v4l2_subdev_call(ci->cameras
+                                               [ci->camera_curr].camera,
+                                               core, s_ctrl, &ctrl);
+                               break;
+                       case V4L2_CID_FOCUS_ABSOLUTE:
+                       case V4L2_CID_FOCUS_AUTO:
+                               if (ci->cameras[ci->camera_curr].type ==
+                                       CAMERA_SENSOR_MOTOR)
+                                       ret =
+                                       v4l2_subdev_call(ci->cameras
+                                               [ci->camera_curr].motor,
+                                               core, s_ctrl,
+                                               &ctrl);
+                               else
+                                       ret =
+                                       v4l2_subdev_call(ci->cameras
+                                               [ci->camera_curr].camera,
+                                               core, s_ctrl,
+                                               &ctrl);
+                               break;
+                       case V4L2_CID_FLASH_DELAY:
+                       case V4L2_CID_FLASH_DURATION:
+                       case V4L2_CID_FLASH_STROBE:
+                       case V4L2_CID_FLASH_TIMEOUT:
+                       case V4L2_CID_FLASH_INTENSITY:
+                       case V4L2_CID_TORCH_INTENSITY:
+                       case V4L2_CID_INDICATOR_INTENSITY:
+                               if (ci->xenon_flash)
+                                       ret = v4l2_subdev_call(ci->xenon_flash,
+                                                       core, s_ctrl,
+                                                       &ctrl);
+                               else
+                                       ret = v4l2_subdev_call(ci->led_flash,
+                                                       core, s_ctrl,
+                                                       &ctrl);
+                               break;
+                       case V4L2_CID_ZOOM_ABSOLUTE:
+                               ret = mfld_isp_digital_zoom(ci, 1,
+                                       &ctrl.value);
+                               /* add digital zoom code here */
+                               break;
+                       }
+                       c->controls[i].value = ctrl.value;
+                       if (ret) {
+                               c->error_idx = i;
+                               break;
+                       }
+               }
+               return ret;
+       }
+       return -EINVAL;
+}
+
+static int mfld_isp_g_parm(struct file *file, void *fh,
+                               struct v4l2_streamparm *parm)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_g_parm\n");
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupport v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       parm->parm.capture.capturemode = ci->run_mode;
+
+       return 0;
+}
+
+static int mfld_isp_s_parm(struct file *file, void *fh,
+                               struct v4l2_streamparm *parm)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       int ret = 0;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_s_parm\n");
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               mfld_isp_dbg(KERN_ERR, "unsupport v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       ci->run_mode = parm->parm.capture.capturemode;
+       mfld_isp_dbg(KERN_DEBUG, "Set ISP running mode to %d\n", ci->run_mode);
+
+       return ret;
+}
+
+static long mfld_isp_vidioc_default(struct file *file, void *fh,
+                                       int cmd, void *arg)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       switch (cmd) {
+       case ATOMISP_IOC_G_XNR:
+               return mfld_isp_xnr(ci, 0, arg);
+
+       case ATOMISP_IOC_S_XNR:
+               return mfld_isp_xnr(ci, 1, arg);
+
+       case ATOMISP_IOC_G_BAYER_NR:
+               return mfld_isp_bayer_nr(ci, 0,
+                                        (struct sh_css_isp_nr_config *)arg);
+
+       case ATOMISP_IOC_S_BAYER_NR:
+               return mfld_isp_bayer_nr(ci, 1,
+                                        (struct sh_css_isp_nr_config *)arg);
+
+       case ATOMISP_IOC_G_TNR:
+               return mfld_isp_tnr(ci, 0, (struct sh_css_isp_tnr_config *)arg);
+
+       case ATOMISP_IOC_S_TNR:
+               return mfld_isp_tnr(ci, 1, (struct sh_css_isp_tnr_config *)arg);
+
+       case ATOMISP_IOC_G_HISTOGRAM:
+               return mfld_isp_histogram(ci, 0, arg);
+
+       case ATOMISP_IOC_S_HISTOGRAM:
+               return mfld_isp_histogram(ci, 1, arg);
+
+       case ATOMISP_IOC_G_BLACK_LEVEL_COMP:
+               return mfld_isp_black_level(ci, 0,
+                                       (struct sh_css_isp_ob_config *)arg);
+
+       case ATOMISP_IOC_S_BLACK_LEVEL_COMP:
+               return mfld_isp_black_level(ci, 1,
+                                       (struct sh_css_isp_ob_config *)arg);
+
+       case ATOMISP_IOC_G_YCC_NR:
+               return mfld_isp_ycc_nr(ci, 0,
+                                       (struct sh_css_isp_nr_config *)arg);
+
+       case ATOMISP_IOC_S_YCC_NR:
+               return mfld_isp_ycc_nr(ci, 1,
+                                       (struct sh_css_isp_nr_config *)arg);
+
+       case ATOMISP_IOC_G_EE:
+               return mfld_isp_ee(ci, 0, (struct sh_css_isp_ee_config *)arg);
+
+       case ATOMISP_IOC_S_EE:
+               return mfld_isp_ee(ci, 1, (struct sh_css_isp_ee_config *)arg);
+
+       case ATOMISP_IOC_G_DIS_STAT:
+               return mfld_isp_dis_stat(ci, 0,
+                                        (struct mfld_isp_dis_config *)arg);
+
+       case ATOMISP_IOC_S_DIS_STAT:
+               return mfld_isp_dis_stat(ci, 1,
+                                        (struct mfld_isp_dis_config *)arg);
+
+       case ATOMISP_IOC_G_ISP_PARM:
+               return mfld_isp_param(ci, 0, (struct mfld_isp_parm *)arg);
+
+       case ATOMISP_IOC_S_ISP_PARM:
+               return mfld_isp_param(ci, 1, (struct mfld_isp_parm *)arg);
+
+       case ATOMISP_IOC_G_3A_STAT:
+               return mfld_isp_3a_stat(ci, 0, (struct mfld_3a_stat *)arg);
+
+       case ATOMISP_IOC_G_ISP_GAMMA:
+               return mfld_isp_get_gamma(ci, 0,
+                                         (struct mfld_isp_gamma_tbl *)arg);
+
+       case ATOMISP_IOC_S_ISP_GAMMA:
+               return mfld_isp_set_gamma(ci, 0,
+                                         (struct mfld_isp_gamma_tbl *)arg);
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static void mfld_isp_init_struct(struct ci_device *ci)
+{
+       if (ci == NULL)
+               return;
+
+       ci->width = ci->height = 0;
+       ci->framesize = ci->imagesize = 0;
+       ci->pixeldepth = 0;
+       ci->pixelformat = 0;
+       ci->imagebuf = NULL;
+       ci->bufnum = 0;
+       ci->sh_pixelformat = -1;
+       ci->streaming = 0;
+       ci->buf_allocated = 0;
+       ci->run_mode = CI_MODE_STILL_CAPTURE;
+       ci->color_effect = V4L2_COLORFX_NONE;
+       ci->bad_pixel_en = 1;
+       ci->gdc_cac_en = 0;
+       ci->video_dis_en = 0;
+       ci->sc_en = 0;
+       ci->fpn_en = 0;
+       ci->xnr_en = 0;
+       ci->false_color = 0;
+       ci->online_process = 1; /* By default we turn on online process */
+       ci->bayer_downscaling = 0; /* By default we turn on online process */
+
+       /* Add for channel */
+       if (ci->cameras[0].camera)
+               ci->camera_curr = 0;
+
+       /* TNR configure init */
+       sh_css_params_get_default_tnr_config
+               ((const struct sh_css_isp_tnr_config **)(&ci->tnr_config));
+       /* NR configure init */
+       sh_css_params_get_default_nr_config
+               ((const struct sh_css_isp_nr_config **)(&ci->nr_config));
+       /* EE configure init */
+       sh_css_params_get_default_ee_config
+               ((const struct sh_css_isp_ee_config **)(&ci->ee_config));
+       /* OB configure init */
+       sh_css_params_get_default_ob_config
+               ((const struct sh_css_isp_ob_config **)(&ci->ob_config));
+}
+
+#ifdef USE_DYNAMIC_BIN
+char *_hrt_blob_sp;
+char *_hrt_blob_isp_bayer_ds_var;
+char *_hrt_blob_isp_copy_var;
+char *_hrt_blob_isp_primary_16mp;
+char *_hrt_blob_isp_primary_14mp;
+char *_hrt_blob_isp_primary_var;
+char *_hrt_blob_isp_primary_ds;
+char *_hrt_blob_isp_primary_small;
+char *_hrt_blob_isp_preview_var;
+char *_hrt_blob_isp_preview_ds;
+char *_hrt_blob_isp_video_online;
+char *_hrt_blob_isp_video_online_nodz;
+char *_hrt_blob_isp_video_online_ds;
+char *_hrt_blob_isp_video_offline;
+char *_hrt_blob_isp_xnr_var;
+char *_hrt_blob_isp_pregdc_var;
+char *_hrt_blob_isp_gdc_var;
+char *_hrt_blob_isp_postgdc_var;
+char *_hrt_blob_isp_vf_pp;
+
+unsigned int _hrt_text_size_of_sp;
+unsigned int _hrt_size_of_sp;
+
+unsigned int _hrt_text_size_of_isp_bayer_ds_var;
+unsigned int _hrt_size_of_isp_bayer_ds_var;
+
+unsigned int _hrt_text_size_of_isp_copy_var;
+unsigned int _hrt_size_of_isp_copy_var;
+
+unsigned int _hrt_text_size_of_isp_gdc_var;
+unsigned int _hrt_size_of_isp_gdc_var;
+
+unsigned int _hrt_text_size_of_isp_postgdc_var;
+unsigned int _hrt_size_of_isp_postgdc_var;
+
+unsigned int _hrt_text_size_of_isp_pregdc_var;
+unsigned int _hrt_size_of_isp_pregdc_var;
+
+unsigned int _hrt_text_size_of_isp_preview_ds;
+unsigned int _hrt_size_of_isp_preview_ds;
+
+unsigned int _hrt_text_size_of_isp_preview_var;
+unsigned int _hrt_size_of_isp_preview_var;
+
+unsigned int _hrt_text_size_of_isp_primary_14mp;
+unsigned int _hrt_size_of_isp_primary_14mp;
+
+unsigned int _hrt_text_size_of_isp_primary_16mp;
+unsigned int _hrt_size_of_isp_primary_16mp;
+
+unsigned int _hrt_text_size_of_isp_primary_ds;
+unsigned int _hrt_size_of_isp_primary_ds;
+
+unsigned int _hrt_text_size_of_isp_primary_small;
+unsigned int _hrt_size_of_isp_primary_small;
+
+unsigned int _hrt_text_size_of_isp_primary_var;
+unsigned int _hrt_size_of_isp_primary_var;
+
+unsigned int _hrt_text_size_of_isp_vf_pp;
+unsigned int _hrt_size_of_isp_vf_pp;
+
+unsigned int _hrt_text_size_of_isp_video_offline;
+unsigned int _hrt_size_of_isp_video_offline;
+
+unsigned int _hrt_text_size_of_isp_video_online_ds;
+unsigned int _hrt_size_of_isp_video_online_ds;
+
+unsigned int _hrt_text_size_of_isp_video_online_nodz;
+unsigned int _hrt_size_of_isp_video_online_nodz;
+
+unsigned int _hrt_text_size_of_isp_video_online;
+unsigned int _hrt_size_of_isp_video_online;
+
+unsigned int _hrt_text_size_of_isp_xnr_var;
+unsigned int _hrt_size_of_isp_xnr_var;
+
+const struct firmware *isp_fw_loaded;
+struct bi_h *isp_fw[SUPPORTED_BIN];
+
+/*
+ * Setup the blob firmware to the loaded firmware
+ * replace the file such as isp_copy_5mp.blob.h
+ * Fixme: use micro to reduce the code lines
+ */
+
+/*Load the Binary Header*/
+static void mfld_isp_get_binary_header(const struct firmware *ci_fw)
+{
+       struct bi_h *bi;
+       struct bi_file_h bf;
+       int i, binary_nr = 0;
+
+       /*bf = (struct bi_file_h *)(ci_fw->data);*/
+       memcpy(&bf, ci_fw->data, sizeof(struct bi_file_h));
+       mfld_isp_dbg(KERN_INFO, "isp fw version %d\n", bf.version);
+       binary_nr = bf.binary_nr;
+       mfld_isp_dbg(KERN_DEBUG, "Binary find %d\n", binary_nr);
+       for (i = 0; i < binary_nr + 1; i++) {
+               bi = (struct bi_h *)(ci_fw->data + sizeof(struct bi_file_h) +
+                       sizeof(struct bi_h) *i);
+               mfld_isp_dbg(KERN_DEBUG, "Collect binary %d\n", i);
+               if ((bi->ID) >= 0) {
+                       mfld_isp_dbg(KERN_DEBUG, "Collect correct binary %d,"
+                               "binary %d\n", i, bi->ID);
+                       mfld_isp_dbg(KERN_DEBUG, "Size %x, offset %x\n",
+                               bi->size, bi->offset);
+                       isp_fw[bi->ID] = bi;
+               }
+       }
+}
+
+static void mfld_isp_setup_fw_size(void)
+{
+       /* This is for SP binary */
+       _hrt_text_size_of_sp = isp_fw[isp_bin_sp]->text_size;
+       _hrt_size_of_sp = isp_fw[isp_bin_sp]->size;
+
+       /* This is for ISP binary */
+       _hrt_text_size_of_isp_bayer_ds_var =
+           isp_fw[isp_bin_bayer_ds_var]->text_size;
+       _hrt_size_of_isp_bayer_ds_var = isp_fw[isp_bin_bayer_ds_var]->size;
+       _hrt_text_size_of_isp_copy_var = isp_fw[isp_bin_copy_var]->text_size;
+       _hrt_size_of_isp_copy_var = isp_fw[isp_bin_copy_var]->size;
+       _hrt_text_size_of_isp_gdc_var = isp_fw[isp_bin_gdc_var]->text_size;
+       _hrt_size_of_isp_gdc_var = isp_fw[isp_bin_gdc_var]->size;
+       _hrt_text_size_of_isp_postgdc_var =
+           isp_fw[isp_bin_postgdc_var]->text_size;
+       _hrt_size_of_isp_postgdc_var = isp_fw[isp_bin_postgdc_var]->size;
+       _hrt_text_size_of_isp_pregdc_var =
+           isp_fw[isp_bin_pregdc_var]->text_size;
+       _hrt_size_of_isp_pregdc_var = isp_fw[isp_bin_pregdc_var]->size;
+       _hrt_text_size_of_isp_preview_ds =
+           isp_fw[isp_bin_preview_ds]->text_size;
+       _hrt_size_of_isp_preview_ds = isp_fw[isp_bin_preview_ds]->size;
+       _hrt_text_size_of_isp_preview_var =
+           isp_fw[isp_bin_preview_var]->text_size;
+       _hrt_size_of_isp_preview_var = isp_fw[isp_bin_preview_var]->size;
+       _hrt_text_size_of_isp_primary_14mp =
+           isp_fw[isp_bin_primary_14mp]->text_size;
+       _hrt_size_of_isp_primary_14mp = isp_fw[isp_bin_primary_14mp]->size;
+       _hrt_text_size_of_isp_primary_16mp =
+           isp_fw[isp_bin_primary_16mp]->text_size;
+       _hrt_size_of_isp_primary_16mp = isp_fw[isp_bin_primary_16mp]->size;
+       _hrt_text_size_of_isp_primary_ds =
+           isp_fw[isp_bin_primary_ds]->text_size;
+       _hrt_size_of_isp_primary_ds = isp_fw[isp_bin_primary_ds]->size;
+       _hrt_text_size_of_isp_primary_small =
+           isp_fw[isp_bin_primary_small]->text_size;
+       _hrt_size_of_isp_primary_small = isp_fw[isp_bin_primary_small]->size;
+       _hrt_text_size_of_isp_primary_var =
+           isp_fw[isp_bin_primary_var]->text_size;
+       _hrt_size_of_isp_primary_var = isp_fw[isp_bin_primary_var]->size;
+       _hrt_text_size_of_isp_vf_pp = isp_fw[isp_bin_vf_pp]->text_size;
+       _hrt_size_of_isp_vf_pp = isp_fw[isp_bin_vf_pp]->size;
+       _hrt_text_size_of_isp_video_offline =
+           isp_fw[isp_bin_video_offline]->text_size;
+       _hrt_size_of_isp_video_offline = isp_fw[isp_bin_video_offline]->size;
+       _hrt_text_size_of_isp_video_online_ds =
+           isp_fw[isp_bin_video_online_ds]->text_size;
+       _hrt_size_of_isp_video_online_ds =
+           isp_fw[isp_bin_video_online_ds]->size;
+       _hrt_text_size_of_isp_video_online_nodz =
+           isp_fw[isp_bin_video_online_nodz]->text_size;
+       _hrt_size_of_isp_video_online_nodz =
+           isp_fw[isp_bin_video_online_nodz]->size;
+       _hrt_text_size_of_isp_video_online =
+           isp_fw[isp_bin_video_online]->text_size;
+       _hrt_size_of_isp_video_online = isp_fw[isp_bin_video_online]->size;
+       _hrt_text_size_of_isp_xnr_var = isp_fw[isp_bin_xnr_var]->text_size;
+       _hrt_size_of_isp_xnr_var = isp_fw[isp_bin_xnr_var]->size;
+}
+
+static void mfld_isp_setup_fw(const struct firmware *ci_fw)
+{
+       _hrt_blob_sp = (char *)
+               (isp_fw[isp_bin_sp]->offset + ci_fw->data);
+
+       _hrt_blob_isp_copy_var = (char *)
+               (isp_fw[isp_bin_copy_var]->offset + ci_fw->data);
+
+       _hrt_blob_isp_bayer_ds_var = (char *)
+               (isp_fw[isp_bin_bayer_ds_var]->offset + ci_fw->data);
+
+       _hrt_blob_isp_primary_16mp = (char *)
+               (isp_fw[isp_bin_primary_16mp]->offset + ci_fw->data);
+
+       _hrt_blob_isp_primary_14mp = (char *)
+               (isp_fw[isp_bin_primary_14mp]->offset + ci_fw->data);
+
+       _hrt_blob_isp_primary_var = (char *)
+               (isp_fw[isp_bin_primary_var]->offset + ci_fw->data);
+
+       _hrt_blob_isp_primary_ds = (char *)
+               (isp_fw[isp_bin_primary_ds]->offset + ci_fw->data);
+
+       _hrt_blob_isp_primary_small = (char *)
+               (isp_fw[isp_bin_primary_small]->offset + ci_fw->data);
+
+       _hrt_blob_isp_preview_var = (char *)
+               (isp_fw[isp_bin_preview_var]->offset + ci_fw->data);
+
+       _hrt_blob_isp_preview_ds = (char *)
+               (isp_fw[isp_bin_preview_ds]->offset + ci_fw->data);
+
+       _hrt_blob_isp_video_online = (char *)
+               (isp_fw[isp_bin_video_online]->offset + ci_fw->data);
+
+       _hrt_blob_isp_video_online_ds = (char *)
+               (isp_fw[isp_bin_video_online_ds]->offset + ci_fw->data);
+
+       _hrt_blob_isp_video_online_nodz = (char *)
+               (isp_fw[isp_bin_video_online_nodz]->offset + ci_fw->data);
+
+       _hrt_blob_isp_video_offline = (char *)
+               (isp_fw[isp_bin_video_offline]->offset + ci_fw->data);
+
+       _hrt_blob_isp_pregdc_var = (char *)
+               (isp_fw[isp_bin_pregdc_var]->offset + ci_fw->data);
+
+       _hrt_blob_isp_gdc_var = (char *)
+               (isp_fw[isp_bin_gdc_var]->offset + ci_fw->data);
+
+       _hrt_blob_isp_postgdc_var = (char *)
+               (isp_fw[isp_bin_postgdc_var]->offset + ci_fw->data);
+
+       _hrt_blob_isp_xnr_var = (char *)
+               (isp_fw[isp_bin_xnr_var]->offset + ci_fw->data);
+
+       _hrt_blob_isp_vf_pp = (char *)
+               (isp_fw[isp_bin_vf_pp]->offset + ci_fw->data);
+
+       mfld_isp_setup_fw_size();
+}
+
+/*
+ * Load the firmware from the User with the udev help
+ * Todo: Do we need to save the loaded firmware to some where else?
+ */
+/*static struct platform_device *ci_pdev;*/
+static int mfld_isp_load_all_firmwares(struct device *dev)
+{
+       int rc = 0;
+       mfld_isp_dbg(KERN_INFO, "loading isp firmware ...\n");
+
+       rc = request_firmware(&isp_fw_loaded, FW_PATH, dev);
+       if (rc < 0) {
+               if (rc == -ENOENT)
+                       mfld_isp_dbg(KERN_INFO,
+                       "atomisp: Error firmware %s not found.\n", FW_PATH);
+               else
+                       mfld_isp_dbg(KERN_INFO,
+                       "atomisp: Error %d while requesting firmware %s\n",
+                                    rc, FW_PATH);
+               /*platform_device_unregister(ci_pdev);*/
+               return rc;
+       }
+       mfld_isp_dbg(KERN_DEBUG,
+                    "isp_fw_file info: file:%p, size:%x\n",
+                    isp_fw_loaded->data,
+                    isp_fw_loaded->size);
+       mfld_isp_get_binary_header(isp_fw_loaded);
+       mfld_isp_setup_fw(isp_fw_loaded);
+       /*mfld_isp_setup_parm(isp_fw_loaded);*/
+       mfld_isp_dbg(KERN_INFO, "loading isp firmware ... done\n");
+       return rc;
+}
+
+static void mfld_isp_release_firmware(void)
+{
+       if (isp_fw_loaded != NULL) {
+               release_firmware(isp_fw_loaded);
+               isp_fw_loaded = NULL;
+       }
+}
+#endif
+
+static void *kernel_malloc(size_t bytes)
+{
+       return kmalloc(bytes, GFP_KERNEL);
+}
+
+/* kfree is declared with const void * argument even though it's
+       clearly not const. We work around this here. */
+static void kernel_free(void *ptr)
+{
+       kfree(ptr);
+}
+
+int myprintk(const char *fmt, ...)
+{
+       va_list args;
+       int printed;
+
+       va_start(args, fmt);
+       printed = vprintk(fmt, args);
+       va_end(args);
+
+       return printed;
+}
+
+/*
+ * file operation functions
+ */
+static int mfld_isp_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       int ret;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_open\n");
+       if (isp_probe == 0)
+               return -1;
+
+       if (ci->open) {
+               mfld_isp_dbg(KERN_ERR, "Can only open once now\n");
+               return -EBUSY;
+       }
+
+       /* runtime power management, turn on ISP */
+       ret = pm_runtime_get_sync(vdev->v4l2_dev->dev);
+       if (ret < 0) {
+               mfld_isp_dbg(KERN_ERR, "Failed to power on device\n");
+               return -EINVAL;
+       }
+
+       ci->open++;
+
+       mfld_isp_init_struct(ci);
+
+#ifdef USE_DYNAMIC_BIN
+       /* Load firmware from user space */
+       ret = v4l2_subdev_call(ci->cameras[ci->camera_curr].camera,
+                              core, init, 1);
+
+       if (ret == -1 || ret == -EINVAL) {
+               mfld_isp_dbg(KERN_ERR, "sensor firmware failed\n");
+               return ret;
+       }
+
+       if (mfld_isp_load_all_firmwares(&vdev->dev) < 0) {
+               mfld_isp_dbg(KERN_ERR, "Load firmwares failed\n");
+               ci->open--;
+               pm_runtime_put(vdev->v4l2_dev->dev);
+               return -1;
+       }
+#endif
+       /* Init ISP */
+       return_on_css_error(sh_css_init
+                           (kernel_malloc, kernel_free,
+                            sh_css_interrupt_setting_disabled));
+       return_on_css_error(sh_css_set_print_function(myprintk));
+
+       return_on_css_error(sh_css_params_allocate(&ci->isp_params));
+       /* now set the default parameters. */
+       return_on_css_error(sh_css_params_default(ci->isp_params));
+
+       mfld_isp_dbg(KERN_DEBUG, "open done\n");
+
+       return 0;
+}
+
+static int mfld_isp_close(struct ci_device *ci)
+{
+       int i;
+       int ret;
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_close\n");
+
+       if (ci == NULL)
+               return -EBADF;
+
+       if (ci->open <= 0) {
+               mfld_isp_dbg(KERN_ALERT, "device already closed\n");
+               return -EBADF;
+       }
+       /* in case image buf is not freed */
+       if (ci->buf_allocated) {
+               for (i = 0; i < ci->bufnum; i++)
+                       free_buffer(ci->imagebuf[i]);
+               kfree(ci->imagebuf);
+               ci->imagebuf = NULL;
+               if (ci->vf_frame)
+                       sh_css_frame_free(ci->vf_frame);
+               ci->vf_frame = NULL;
+               ci->buf_allocated = 0;
+       }
+#ifdef USE_DYNAMIC_BIN
+       mfld_isp_release_firmware();
+#endif
+
+       ret = v4l2_subdev_call(ci->cameras[ci->camera_curr].camera,
+                              core, init, 0);
+
+       if (ret == -1 || ret == -EINVAL) {
+               mfld_isp_dbg(KERN_ERR, "sensor firmware failed\n");
+               return ret;
+       }
+
+       ci->open--;
+
+       sh_css_uninit();
+
+       /* uninit ISP parameter */
+       sh_css_params_free(ci->isp_params);
+       return 0;
+}
+
+static int mfld_isp_release(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+       int ret;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_release\n");
+
+       ret = mfld_isp_close(ci);
+       if (!ret)
+               pm_runtime_put(vdev->v4l2_dev->dev);
+
+       return ret;
+}
+
+static int __do_isp_mm_remap(struct vm_area_struct *vma,
+                               void *isp_virt, __u32 host_virt, __u32 pgnr)
+{
+       __u32 pfn;
+
+       while (pgnr) {
+               pfn = hmm_virt_to_phys(isp_virt) >> PAGE_SHIFT;
+               if (remap_pfn_range(vma, host_virt, pfn,
+                                       PAGE_SIZE, PAGE_SHARED)) {
+                       mfld_isp_dbg(KERN_ERR, "remap_pfn_range err.\n");
+                       return -1;
+               }
+
+               isp_virt += PAGE_SIZE;
+               host_virt += PAGE_SIZE;
+               pgnr--;
+       }
+
+       return 0;
+}
+
+static int frame_mmap(const struct sh_css_frame *frame,
+                       struct vm_area_struct *vma)
+{
+       void *isp_virt;
+       __u32 host_virt;
+       __u32 pgnr;
+
+       if (!frame) {
+               mfld_isp_dbg(KERN_ERR, "NULL frame pointer.\n");
+               return -EINVAL;
+       }
+
+       host_virt = vma->vm_start;
+       isp_virt = frame->data;
+       get_frame_pgnr(frame, &pgnr);
+
+       if (__do_isp_mm_remap(vma, isp_virt, host_virt, pgnr))
+               return -1;
+
+       return 0;
+}
+
+static int __mmap_image_frame(struct vm_area_struct *vma, struct ci_buffer *buf,
+                               __u32 vm_flags)
+{
+       __u32 pgnr;
+       __u32 start, end;
+       __u32 size;
+
+       start = vma->vm_start;
+       end = vma->vm_end;
+       size = buf->size;
+
+       if (PAGE_ALIGN(size) != (end - start)) {
+               mfld_isp_dbg(KERN_ERR, "vma size is not equal to memory size: "
+                               "vma_size = 0x%x, mem_size = 0x%x\n",
+                               (end - start), PAGE_ALIGN(size));
+               return -1;
+       }
+
+       pgnr = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+       if (frame_mmap(buf->handle, vma)) {
+               mfld_isp_dbg(KERN_ERR, "frame_mmap failed.\n");
+               return -1;
+       }
+       vma->vm_flags |= vm_flags;
+
+       return 0;
+}
+
+static int mfld_isp_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       __u32 start = vma->vm_start;
+       __u32 end = vma->vm_end;
+       __u32 offset = vma->vm_pgoff << PAGE_SHIFT;
+       __u32 size = end - start;
+       struct sh_css_frame *raw_virt_addr;
+       int buf_idx;
+
+       mfld_isp_dbg(KERN_DEBUG, "mfld_isp_mmap\n");
+
+       if (!(vma->vm_flags & (VM_WRITE | VM_READ)))
+               return -EACCES;
+
+       if (!(vma->vm_flags & VM_SHARED))
+               return -EINVAL;
+
+       /*
+        * mmap for ISP parameter structure
+        */
+       if (vma->vm_pgoff == (ISP_PARAM_MMAP_OFFSET >> PAGE_SHIFT)) {
+               if (ci->online_process != 0)
+                       return -EINVAL;
+
+               raw_virt_addr = sh_css_get_raw_frame();
+               if (raw_virt_addr == NULL) {
+                       mfld_isp_dbg(KERN_ERR, "Failed to request RAW frame\n");
+                       return -EINVAL;
+               }
+
+               mfld_isp_dbg(KERN_DEBUG, "raw = %x, size = %d, ALIGN = %d\n",
+                            (unsigned int)raw_virt_addr, size,
+                            PAGE_ALIGN(raw_virt_addr->data_bytes));
+               if (size != PAGE_ALIGN(raw_virt_addr->data_bytes)) {
+                       mfld_isp_dbg(KERN_ERR, "incorrect size for mmap ISP"
+                                    " Raw Frame\n");
+                       return -EINVAL;
+               }
+
+               /*ci->online_process = 0;*/
+               /*return_on_css_error(sh_css_capture_enable_online*/
+                                   /*(ci->online_process));*/
+               if (frame_mmap(raw_virt_addr, vma)) {
+                       mfld_isp_dbg(KERN_ERR, "frame_mmap failed.\n");
+                       return -1;
+               }
+               vma->vm_flags |= VM_RESERVED;
+               return 0;
+       }
+
+       /*
+        * mmap for NORMAL frames
+        */
+       if (offset >= ci->bufnum * ci->imagesize) {
+               mfld_isp_dbg(KERN_ERR, "offset extends max buffer size:"
+                            " bufsize = %d, offset = %d\n",
+                            ci->bufnum * ci->imagesize, offset);
+               return -EINVAL;
+       }
+
+       if (size != ci->imagesize) {
+               mfld_isp_dbg(KERN_ERR, "user space virtual address space range"
+                            " for mmap is not the same as frame buffer size:"
+                            " %d, %d", size, ci->imagesize);
+               return -EINVAL;
+       }
+
+       if (ci->imagebuf == NULL) {
+               mfld_isp_dbg(KERN_ERR, "buffer not allocated\n");
+               return -EINVAL;
+       }
+
+       buf_idx = offset / ci->imagesize;
+
+       mfld_isp_dbg(KERN_DEBUG, "try to mmap buffer: %d\n", buf_idx);
+
+       return __mmap_image_frame(vma, ci->imagebuf[buf_idx], VM_RESERVED);
+}
+
+static unsigned int mfld_isp_poll(struct file *file,
+                                       struct poll_table_struct *pt)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct ci_device *ci = video_get_drvdata(vdev);
+
+       if (ci->streaming != 1)
+               return POLLERR;
+
+       /* Without videobuf enabled, we just return */
+       return POLLIN | POLLRDNORM;
+}
+
+static const struct v4l2_file_operations mfld_isp_fops = {
+       .owner = THIS_MODULE,
+       .open = mfld_isp_open,
+       .release = mfld_isp_release,
+       .mmap = mfld_isp_mmap,
+       .ioctl = video_ioctl2,
+       .poll = mfld_isp_poll,
+};
+
+static const struct v4l2_ioctl_ops mfld_isp_ioctl_ops = {
+       .vidioc_querycap = mfld_isp_querycap,
+       .vidioc_enum_input = mfld_isp_enum_input,
+       .vidioc_g_input = mfld_isp_g_input,
+       .vidioc_s_input = mfld_isp_s_input,
+       .vidioc_queryctrl = mfld_isp_queryctl,
+       .vidioc_s_ctrl = mfld_isp_s_ctrl,
+       .vidioc_g_ctrl = mfld_isp_g_ctrl,
+       .vidioc_s_ext_ctrls = mfld_isp_s_ext_ctrls,
+       .vidioc_g_ext_ctrls = mfld_isp_g_ext_ctrls,
+       .vidioc_enum_fmt_vid_cap = mfld_isp_enum_fmt_cap,
+       .vidioc_try_fmt_vid_cap = mfld_isp_try_fmt_cap,
+       .vidioc_g_fmt_vid_cap = mfld_isp_g_fmt_cap,
+       .vidioc_s_fmt_vid_cap = mfld_isp_s_fmt_cap,
+       .vidioc_s_fmt_type_private = mfld_isp_s_fmt_cap,
+       .vidioc_reqbufs = mfld_isp_reqbufs,
+       .vidioc_querybuf = mfld_isp_querybuf,
+       .vidioc_qbuf = mfld_isp_qbuf,
+       .vidioc_dqbuf = mfld_isp_dqbuf,
+       .vidioc_streamon = mfld_isp_streamon,
+       .vidioc_streamoff = mfld_isp_streamoff,
+       .vidioc_default = mfld_isp_vidioc_default,
+       .vidioc_cropcap = mfld_isp_cropcap,
+       .vidioc_enum_framesizes = mfld_isp_enum_framesizes,
+       .vidioc_enum_frameintervals = mfld_isp_enum_frameintervals,
+       .vidioc_s_parm = mfld_isp_s_parm,
+       .vidioc_g_parm = mfld_isp_g_parm,
+       .vidioc_g_std = mfld_isp_g_std,
+       .vidioc_s_std = mfld_isp_s_std,
+       .vidioc_g_crop = mfld_isp_g_crop,
+       .vidioc_s_crop = mfld_isp_s_crop,
+};
+
+static const struct video_device mfld_isp_video_dev = {
+       .name = "mfld_ci",
+       .minor = -1,
+       .fops = &mfld_isp_fops,
+       .release = video_device_release,
+       .ioctl_ops = &mfld_isp_ioctl_ops
+};
+
+#ifdef CONFIG_PM
+static int ospm_power_island_down(struct ci_device *);
+static int ospm_power_island_up(struct ci_device *);
+
+static int mfld_isp_runtime_suspend(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct ci_device *ci = (struct ci_device *)pci_get_drvdata(pdev);
+       int ret;
+
+       mfld_isp_dbg(KERN_DEBUG, "Get into runtime suspend function\n");
+
+       ret = pci_save_state(pdev);
+       if (ret) {
+               mfld_isp_dbg(KERN_ERR, "pci_save_state failed %d\n", ret);
+               return ret;
+       }
+
+       pci_disable_device(pdev);
+       ret += pci_set_power_state(pdev, PCI_D3hot);
+       if (ret) {
+               mfld_isp_dbg(KERN_ERR, "fail to set power state\n");
+               return ret;
+       }
+
+       ospm_power_island_down(ci);
+
+       mfld_isp_dbg(KERN_DEBUG, "Leave runtime suspend function\n");
+       return 0;
+}
+
+static int mfld_isp_runtime_resume(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct ci_device *ci = (struct ci_device *)pci_get_drvdata(pdev);
+       int ret;
+
+       mfld_isp_dbg(KERN_DEBUG, "Get into runtime resume function\n");
+
+       pci_set_power_state(pdev, PCI_D0);
+       ospm_power_island_up(ci);
+       pci_restore_state(pdev);
+
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               mfld_isp_dbg(KERN_ERR, "fail to enable device in resume\n");
+               return ret;
+       }
+
+       mfld_isp_dbg(KERN_DEBUG, "Leave runtime resume function\n");
+       return 0;
+}
+
+static int mfld_isp_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       struct ci_device *ci = (struct ci_device *)pci_get_drvdata(dev);
+       int ret;
+
+       mfld_isp_dbg(KERN_DEBUG, "Get into suspend function\n");
+
+#if (!defined(IMAGE_FROM_TPG))
+       ret = v4l2_subdev_call(ci->cameras[ci->camera_curr].camera, core,
+                               s_power, 0);
+       if (ret) {
+               mfld_isp_dbg(KERN_ERR, "Fail to suspend sensor\n");
+               return ret;
+       }
+#endif
+
+       ret = pci_save_state(dev);
+       if (ret) {
+               mfld_isp_dbg(KERN_ERR, "pci_save_state failed %d\n", ret);
+               return ret;
+       }
+
+       pci_disable_device(dev);
+       ret += pci_set_power_state(dev, pci_choose_state(dev, state));
+       if (ret) {
+               mfld_isp_dbg(KERN_ERR, "fail to set power state\n");
+               return ret;
+       }
+
+       ospm_power_island_down(ci);
+
+       mfld_isp_dbg(KERN_DEBUG, "Leave suspend function\n");
+       return 0;
+}
+
+static int mfld_isp_pci_resume(struct pci_dev *dev)
+{
+       struct ci_device *ci = (struct ci_device *)pci_get_drvdata(dev);
+       int ret;
+
+       mfld_isp_dbg(KERN_DEBUG, "Get into resume function\n");
+
+       pci_set_power_state(dev, PCI_D0);
+       ospm_power_island_up(ci);
+       pci_restore_state(dev);
+
+       ret = pci_enable_device(dev);
+       if (ret) {
+               mfld_isp_dbg(KERN_ERR, "fail to enable device in resume\n");
+               return ret;
+       }
+#if (!defined(IMAGE_FROM_TPG))
+       ret = v4l2_subdev_call(ci->cameras[ci->camera_curr].camera, core,
+                               s_power, 1);
+       if (ret) {
+               mfld_isp_dbg(KERN_ERR, "Fail to resume sensor\n");
+               return ret;
+       }
+#endif
+
+       mfld_isp_dbg(KERN_DEBUG, "Leave resume function\n");
+       return 0;
+}
+#endif
+
+#ifdef PNW_B0
+static void set_alt_fn_for_i2c4_5(void)
+{
+       void __iomem *gpio1_base;
+       u32 gafr4_l;
+
+       gpio1_base = ioremap_nocache(0xff12c800, 0x74);
+       if (!gpio1_base)
+               mfld_isp_dbg(KERN_DEBUG, "gpio1_base mapped failed\n");
+
+       mfld_isp_dbg(KERN_DEBUG, "try to set alt fn for i2c4\n");
+
+       /* GPIO O/P Enable */
+       writel(0xffe80303, gpio1_base + 0x10);
+       mfld_isp_dbg(KERN_DEBUG, "(0xffe80303)0x%x\n",
+                    readl(gpio1_base + 0x10));
+       gafr4_l = readl(gpio1_base + 0x5c);
+       mfld_isp_dbg(KERN_DEBUG, "orig vale- 0x%x", gafr4_l);
+       writel((gafr4_l | 0x00055000), gpio1_base + 0x5c);
+
+       gafr4_l = readl(gpio1_base + 0x5c);
+       mfld_isp_dbg(KERN_DEBUG, "change val - 0x%x", gafr4_l);
+
+       mfld_isp_dbg(KERN_DEBUG, "done set alt fn for i2c4\n");
+
+}
+
+/*
+ * port: 0 is 4 Lane port and 1 is 1 Lane port
+ * flag: 0 is off and 1 is on
+ */
+static int mfld_isp_camera_flis_clock(int port, int flag)
+{
+       u32 *ipc_wbuf;
+       u8 cbuf[16] = { '\0' };
+       int ipc_ret = 0;
+
+       ipc_wbuf = (u32 *)&cbuf;
+       cbuf[0] = port;         /* 0 - 14MP camera, 1 - 2MP camera */
+       cbuf[1] = flag;         /* 0 - off, 1 - on */
+       /* is this correct for sub type */
+       ipc_ret = intel_scu_ipc_command(0xE7, 0,
+                                       ipc_wbuf, 2, NULL, 0);
+
+       if (ipc_ret != 0)
+               mfld_isp_dbg(KERN_CRIT, "Error Setting Camera FLIS Clock %x\n",
+                               ipc_ret);
+
+       return ipc_ret;
+
+}
+#endif
+
+static int mfld_isp_subdev_probe(struct ci_device *ci_dev)
+{
+       struct v4l2_subdev *subdev = NULL;
+       struct v4l2_subdev *motor_sd = NULL;
+       struct i2c_adapter *adapter = NULL;
+       char *name;
+       u8 addr;
+       int i2c_id;
+       int i;
+       int j = 0;
+
+       /* This Code is for Penwell B0 ES2 board only */
+       /* turn on vprog2 and vpro1 power */
+       __u16 ipc_addr = 0xd6;
+       __u8 ipc_data = 0xff;
+       intel_scu_ipc_iowrite8(ipc_addr, ipc_data);
+       mfld_isp_dbg(KERN_DEBUG, "turn on vprog2 power\n");
+
+       ipc_addr = 0xd7;
+       ipc_data = 0xff;
+       intel_scu_ipc_iowrite8(ipc_addr, ipc_data);
+       mfld_isp_dbg(KERN_DEBUG, "turn on vprog1 power\n");
+
+       /* turn on camera flis registers */
+       mfld_isp_camera_flis_clock(0, 1);       /* primary camera */
+       mfld_isp_camera_flis_clock(1, 1);       /* secondary camera */
+       mfld_isp_dbg(KERN_INFO, "turn on camera clock flis\n");
+       set_alt_fn_for_i2c4_5();
+
+       /* NOTE: Add some GPIO control here */
+       /* Add power control here for sensor */
+       /* FIXME: Need to double confirm with Prajnesh */
+
+       for (i = 0; i < N_SUBDEV; i++) {
+               switch (mfld_isp_subdev_table[i].subdev_type) {
+               case CAMERA_SENSOR:
+                       /*handle camera sensor first */
+                       name = mfld_isp_subdev_table[i].camera.name;
+                       addr = mfld_isp_subdev_table[i].camera.i2c_addr;
+                       i2c_id = mfld_isp_subdev_table[i].camera.i2c_id;
+
+                       adapter = i2c_get_adapter(i2c_id);
+                       if (adapter == NULL) {
+                               mfld_isp_dbg(KERN_ERR,
+                                               "Failed to find i2c adapter for"
+                                               " subdev %s\n", name);
+                               break;
+                       }
+                       mfld_isp_dbg(KERN_INFO,
+                                       "Found adapter %s for subdev %s\n",
+                                       adapter->name, name);
+
+                       subdev = v4l2_i2c_new_subdev(&ci_dev->v4l2_dev, adapter,
+                                                       name, name, addr, NULL);
+                       if (subdev == NULL) {
+                               mfld_isp_dbg(KERN_WARNING, "Camera %s not"
+                                               " found\n", name);
+                               break;
+                       }
+
+                       for (j = 0; j < N_SUBDEV; j++)
+                               if (!ci_dev->cameras[j].camera) {
+                                       ci_dev->cameras[j].camera = subdev;
+                                       ci_dev->cameras[j].type = CAMERA_SENSOR;
+                                       ci_dev->camera_curr = j;
+                                       break;
+                               }
+                       if (j >= N_SUBDEV) {
+                               mfld_isp_dbg(KERN_WARNING, "Already found %d "
+                                               "cameras\n", 4);
+                               break;
+                       }
+                       mfld_isp_dbg(KERN_INFO,
+                               "Subdev %s successfully register\n", name);
+                       break;
+
+               case CAMERA_SENSOR_MOTOR:
+                               /*handle camera motor then */
+                               name = mfld_isp_subdev_table[i].motor.name;
+                               addr = mfld_isp_subdev_table[i].motor.i2c_addr;
+                               i2c_id = mfld_isp_subdev_table[i].motor.i2c_id;
+
+                               adapter = i2c_get_adapter(i2c_id);
+                               if (adapter == NULL) {
+                                       mfld_isp_dbg(KERN_ERR,
+                                               "Failed to find i2c "
+                                               "adapter for subdev %s\n",
+                                               name);
+                                       break;
+                               }
+                               mfld_isp_dbg(KERN_INFO, "Found adapter %s for"
+                                               " subdev %s\n",
+                                               adapter->name, name);
+
+                               motor_sd =
+                                       v4l2_i2c_new_subdev(&ci_dev->v4l2_dev,
+                                                       adapter, name, name,
+                                                       addr, NULL);
+                               if (motor_sd == NULL) {
+                                       mfld_isp_dbg(KERN_INFO,
+                                               "Motor %s not found\n", name);
+                                       break;
+                               }
+
+                               if (ci_dev->cameras[j].motor == NULL) {
+                                       ci_dev->cameras[j].motor = motor_sd;
+                                       ci_dev->cameras[j].type =
+                                               CAMERA_SENSOR_MOTOR;
+                               }
+                               mfld_isp_dbg(KERN_INFO,
+                                       "Subdev %s successfully register\n",
+                                       name);
+                       break;
+               case LED_FLASH:
+               case XENON_FLASH:
+                       name = mfld_isp_subdev_table[i].flash.name;
+                       addr = mfld_isp_subdev_table[i].flash.i2c_addr;
+                       i2c_id = mfld_isp_subdev_table[i].flash.i2c_id;
+
+                       adapter = i2c_get_adapter(i2c_id);
+                       if (adapter == NULL) {
+                               mfld_isp_dbg(KERN_ERR,
+                                               "Failed to find i2c adapter for"
+                                               "subdev %s\n", name);
+                               break;
+                       }
+                       mfld_isp_dbg(KERN_INFO, "Found adapter %s for"
+                                       "subdev %s\n", adapter->name, name);
+
+                       subdev = v4l2_i2c_new_subdev(&ci_dev->v4l2_dev, adapter,
+                                                       name, name, addr, NULL);
+                       if (subdev == NULL) {
+                               mfld_isp_dbg(KERN_WARNING,
+                                               "Flash %s not found\n", name);
+                               break;
+                       }
+
+                       if (mfld_isp_subdev_table[i].subdev_type == LED_FLASH)
+                               ci_dev->led_flash = subdev;
+                       else
+                               ci_dev->xenon_flash = subdev;
+
+                       mfld_isp_dbg(KERN_INFO,
+                               "Subdev %s successfully register\n", name);
+                       break;
+               }
+
+       }
+
+       /*Check camera for at least one subdev in it */
+       if (!ci_dev->cameras[0].camera) {
+               printk(KERN_INFO "atomisp: "
+                      "no camera attached or fail to detect\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static inline u32 MSG_READ32(uint port, uint offset)
+{
+       int mcr = (0x10 << 24) | (port << 16) | (offset << 8);
+       outl(0x800000D0, 0xCF8);
+       outl(mcr, 0xCFC);
+       outl(0x800000D4, 0xCF8);
+       return inl(0xcfc);
+}
+
+static inline void MSG_WRITE32(uint port, uint offset, u32 value)
+{
+       int mcr = (0x11 << 24) | (port << 16) | (offset << 8) | 0xF0;
+       outl(0x800000D4, 0xCF8);
+       outl(value, 0xcfc);
+       outl(0x800000D0, 0xCF8);
+       outl(mcr, 0xCFC);
+}
+
+#define OSPM_ISP_D3_MASK       0x300
+#define OSPM_CAMERA_D3_MASK    0xC00
+#define OSPM_PUNIT_APM_STS     0x4
+static int ospm_power_island_down(struct ci_device *ci_dev)
+{
+       u32 pwr_cnt = 0;
+       u32 pwr_mask = 0;
+       u32 pwr_sts = 0;
+       int count = 0;
+
+       mfld_isp_dbg(KERN_INFO, "Entry %s\n", __func__);
+
+       pwr_cnt |= OSPM_ISP_D3_MASK;
+       pwr_mask |= OSPM_ISP_D3_MASK;
+
+       pwr_cnt |= inl(ci_dev->apm_base);
+       mfld_isp_dbg(KERN_INFO, "%s, set pwr_cnt = %x\n", __func__, pwr_cnt);
+       outl(pwr_cnt, ci_dev->apm_base);
+
+       pwr_cnt = inl(ci_dev->apm_base);
+       mfld_isp_dbg(KERN_INFO, "%s, get pwr_cnt = %x\n", __func__, pwr_cnt);
+       while (true) {
+               pwr_sts = inl(ci_dev->apm_base + OSPM_PUNIT_APM_STS);
+               if ((pwr_sts & pwr_mask) == pwr_mask)
+                       break;
+               else {
+                       mfld_isp_dbg(KERN_INFO,
+                                    "Checking APM_STS register pwr_sts = %x\n",
+                                    pwr_sts);
+                       if (count++ > 500)
+                               break;
+                       udelay(10);
+               }
+       }
+#ifdef ISP_CTRL_DPHY
+       /* Workaround to poweroff Iunitphy when no sensor attched */
+       pwr_cnt = MSG_READ32(0x09, 0x03);
+       pwr_cnt |= 0x300;
+       MSG_WRITE32(0x09, 0x03, pwr_cnt);
+#endif
+
+       mfld_isp_dbg(KERN_INFO, "Exit %s\n", __func__);
+       return 0;
+}
+
+static int ospm_power_island_up(struct ci_device *ci_dev)
+{
+       u32 pwr_cnt = 0;
+       u32 pwr_mask = 0;
+       u32 pwr_sts = 0;
+       int count = 0;
+
+       mfld_isp_dbg(KERN_INFO, "Entry %s\n", __func__);
+
+       pwr_cnt |= inl(ci_dev->apm_base);
+
+       pwr_cnt &= ~OSPM_ISP_D3_MASK;
+       pwr_mask |= OSPM_ISP_D3_MASK;
+
+       outl(pwr_cnt, ci_dev->apm_base);
+       while (true) {
+               pwr_sts = inl(ci_dev->apm_base + OSPM_PUNIT_APM_STS);
+               if ((pwr_sts & pwr_mask) == 0)
+                       break;
+               else {
+                       mfld_isp_dbg(KERN_INFO, "Checking APM_STS register\n");
+                       if (count++ > 500)
+                               break;
+                       udelay(10);
+               }
+       }
+#ifdef ISP_CTRL_DPHY
+       /* Workaround to power-on Iunitphy when no sensor attched */
+       pwr_cnt = MSG_READ32(0x09, 0x03);
+       pwr_cnt &= ~0x300;
+       MSG_WRITE32(0x09, 0x03, pwr_cnt);
+#endif
+
+       mfld_isp_dbg(KERN_INFO, "Exit %s\n", __func__);
+       return 0;
+}
+
+static int mfld_isp_ospm_init(struct ci_device *ci_dev)
+{
+       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+
+       pci_write_config_dword(pci_root, 0xD0, 0x10047800);
+       pci_read_config_dword(pci_root, 0xD4, &ci_dev->ospm_base);
+       ci_dev->ospm_base &= 0xffff;
+       ci_dev->apm_reg = MSG_READ32(0x04, 0x7A);
+       ci_dev->apm_base = ci_dev->apm_reg & 0xffff;
+
+       mfld_isp_dbg(KERN_INFO, "OSPM_BASE = %x, APM_BASE = %x\n",
+                       ci_dev->ospm_base, ci_dev->apm_base);
+       return 0;
+}
+
+static struct pci_driver mfld_isp_pci_driver;
+static int __devinit mfld_isp_pci_probe(struct pci_dev *dev,
+                                       const struct pci_device_id *id)
+{
+       struct ci_device *ci_dev;
+       struct video_device *vdev;
+       unsigned int start, len;
+       void __iomem *base = NULL;
+       int err;
+
+       isp_probe = 0;
+
+       ci_dev = kmalloc(sizeof(struct ci_device), GFP_KERNEL);
+       if (!dev) {
+               dev_err(&dev->dev, "Failed to alloc CI ISP structure\n");
+               err = -ENOMEM;
+               goto kmalloc_fail1;
+       }
+       memset(ci_dev, 0, sizeof(struct ci_device));
+
+       err = v4l2_device_register(&dev->dev, &ci_dev->v4l2_dev);
+       if (err) {
+               mfld_isp_dbg(KERN_ERR, "v4l2_device_register err.\n");
+               return err;
+       }
+
+       mfld_isp_dbg(KERN_INFO, "Initialising driver...\n");
+       err = pci_enable_device(dev);
+       if (err) {
+               mfld_isp_dbg(KERN_ERR, "Failed to enable CI ISP device\n");
+               goto exit;
+       }
+
+       start = pci_resource_start(dev, 0);
+       len = pci_resource_len(dev, 0);
+
+       if (!start || len <= 0) {
+               start = 0xDF800000;
+               len = 0x400000;
+       }
+       mfld_isp_dbg(KERN_INFO, "MFLD ISP resource start 0x%x, len %d\n",
+                       start, len);
+
+       err = pci_request_region(dev, 0, mfld_isp_pci_driver.name);
+       if (err) {
+               mfld_isp_dbg(KERN_ERR, "Failed to request region 0x%1x-0x%Lx\n",
+                               start, (unsigned long long)pci_resource_end(dev,
+                                                                        0));
+               goto exit;
+       }
+
+       base = ioremap_nocache(start, len);
+       if (!base) {
+               mfld_isp_dbg(KERN_ERR, "Failed to I/O memory remapping\n");
+               err = -ENOMEM;
+               goto ioremap_fail;
+       }
+       mfld_isp_dbg(KERN_INFO, "MFLD ISP base address 0x%8x\n",
+                       (unsigned int)base);
+
+       pci_set_master(dev);
+
+       vdev = video_device_alloc();
+       if (!vdev) {
+               mfld_isp_dbg(KERN_ERR, "Failed to alloc video device\n");
+               err = -ENOMEM;
+               goto alloc_vdev_fail;
+       }
+       memcpy(vdev, &mfld_isp_video_dev, sizeof(struct video_device));
+       video_set_drvdata(vdev, ci_dev);
+
+       if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) != 0) {
+               mfld_isp_dbg(KERN_ERR, "Failed to register video device\n");
+               err = -EINVAL;
+               goto register_fail;
+       }
+
+       snprintf(vdev->name, sizeof(vdev->name), "%s (%i)",
+                mfld_isp_video_dev.name, vdev->minor);
+
+       nr = vdev->minor;
+       mfld_isp_dbg(KERN_INFO, "Set nr to %d\n", nr);
+       ci_dev->vdev = vdev;
+       ci_dev->open = 0;
+       ci_dev->tvnorm = tvnorms;
+       ci_dev->input = 0;
+       ci_dev->base = base;
+       CI_DEV = ci_dev;
+       io_base = base;
+       VDEV = vdev;
+
+       /*init OSPM related varible */
+       mfld_isp_dbg(KERN_INFO, "Init OSPM for ISP\n");
+       mfld_isp_ospm_init(ci_dev);
+
+       pci_set_drvdata(dev, ci_dev);
+
+#if (!defined(IMAGE_FROM_TPG))
+       err = mfld_isp_subdev_probe(ci_dev);
+       if (err) {
+               mfld_isp_dbg(KERN_ERR,
+                               "Failed to probe camera subdev module\n");
+               goto subdev_probe_fail;
+       }
+#endif
+
+       mfld_isp_dbg(KERN_INFO, "rumtime power management init\n");
+       pm_runtime_set_active(&dev->dev);
+       pm_runtime_enable(&dev->dev);
+       /*pm_rumtime_suspend(&dev->dev); */
+
+       mfld_isp_dbg(KERN_INFO, "Initialising atom isp driver done...\n");
+       isp_probe = 1;
+
+       return 0;
+
+#if (!defined(IMAGE_FROM_TPG))
+subdev_probe_fail:
+       pci_set_drvdata(dev, NULL);
+#endif
+
+register_fail:
+       video_device_release(vdev);
+alloc_vdev_fail:
+       kfree(ci_dev);
+kmalloc_fail1:
+       iounmap(base);
+ioremap_fail:
+       pci_release_region(dev, 0);
+exit:
+       return err;
+}
+
+static void __devexit mfld_isp_pci_remove(struct pci_dev *dev)
+{
+       struct ci_device *ci_dev = (struct ci_device *)pci_get_drvdata(dev);
+       mfld_isp_dbg(KERN_INFO, "remove driver...\n");
+
+       if (ci_dev->vdev != VDEV) {
+               mfld_isp_dbg(KERN_WARNING, "VDEV has been changed\n");
+               ci_dev->vdev = VDEV;
+       }
+
+       if (ci_dev->vdev->minor != nr) {
+               mfld_isp_dbg(KERN_WARNING, "NOTE, set the minor number back"
+                               "to it's real value %d\n", nr);
+               ci_dev->vdev->minor = nr;
+       }
+       video_unregister_device(ci_dev->vdev);
+       video_device_release(ci_dev->vdev);
+       /* in case user forget to close */
+       if (ci_dev->open > 0)
+               mfld_isp_close(ci_dev);
+
+       pci_set_drvdata(dev, NULL);
+       iounmap(ci_dev->base);
+       kfree(ci_dev);
+       pci_release_region(dev, 0);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(mfld_isp_pci_tbl) = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0148)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0149)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014A)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014B)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014C)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014D)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014E)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014F)},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, mfld_isp_pci_tbl);
+
+static const struct dev_pm_ops mfld_isp_pm_ops = {
+       .runtime_suspend = mfld_isp_runtime_suspend,
+       .runtime_resume = mfld_isp_runtime_resume,
+};
+
+static struct pci_driver mfld_isp_pci_driver = {
+       .driver = {
+               .pm = &mfld_isp_pm_ops,
+       },
+       .name = "atomisp",
+       .id_table = mfld_isp_pci_tbl,
+       .probe = mfld_isp_pci_probe,
+       .remove = mfld_isp_pci_remove,
+#ifdef CONFIG_PM
+       .suspend = mfld_isp_pci_suspend,
+       .resume = mfld_isp_pci_resume,
+#endif
+};
+
+static int __init mfld_isp_init(void)
+{
+       mfld_isp_dbg(KERN_INFO, "Init ATOM ISP device driver,"
+                    " version: %s\n", DRIVER_VERSION_STR);
+       return pci_register_driver(&mfld_isp_pci_driver);
+}
+
+static void __exit mfld_isp_exit(void)
+{
+       mfld_isp_dbg(KERN_INFO, "Exit ATOM ISP device driver\n");
+       pci_unregister_driver(&mfld_isp_pci_driver);
+}
+
+module_init(mfld_isp_init);
+module_exit(mfld_isp_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel ATOM Platform ISP Driver");
--
1.6.2.5

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-ISP-v4l2-driver-based-on-v4l2-API-and-framework-impl.patch
Type: application/octet-stream
Size: 146681 bytes
Desc: 0003-ISP-v4l2-driver-based-on-v4l2-API-and-framework-impl.patch
URL: <http://lists.meego.com/pipermail/meego-kernel/attachments/20101202/2b6558ec/attachment-0001.obj>


More information about the MeeGo-kernel mailing list