Split patch nokia-20094803.3+0m5.diff into more nokia versions
[kernel-power] / kernel-power-2.6.28 / debian / patches / nokia-20094803.3+0m5.diff
1 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/configs/rx51_defconfig kernel-2.6.28-20094803.3+0m5/arch/arm/configs/rx51_defconfig
2 --- kernel-2.6.28-20094102.6+0m5/arch/arm/configs/rx51_defconfig        2011-09-04 11:36:23.000000000 +0200
3 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/configs/rx51_defconfig        2011-09-04 11:37:54.000000000 +0200
4 @@ -319,7 +319,7 @@ CONFIG_ALIGNMENT_TRAP=y
5  #
6  CONFIG_ZBOOT_ROM_TEXT=0x0
7  CONFIG_ZBOOT_ROM_BSS=0x0
8 -CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs rootflags=bulk_read,no_chk_data_crc rw console=ttyMTD,log console=tty0"
9 +CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs rootflags=bulk_read,no_chk_data_crc rw console=ttyMTD,log console=tty0 snd-soc-rx51.hp_lim=42 snd-soc-tlv320aic3x.hp_dac_lim=6"
10  # CONFIG_XIP_KERNEL is not set
11  CONFIG_KEXEC=y
12  CONFIG_ATAGS_PROC=y
13 @@ -689,6 +689,8 @@ CONFIG_OMAP_SSI=m
14  CONFIG_SSI_MCSAAB_IMP=m
15  CONFIG_SSI_CMT_SPEECH=m
16  # CONFIG_SSI_CMT_SPEECH_DEBUG is not set
17 +CONFIG_SSI_CHAR=m
18 +# CONFIG_SSI_CHAR_DEBUG is not set
19  CONFIG_HAVE_IDE=y
20  # CONFIG_IDE is not set
21  
22 @@ -1884,6 +1886,7 @@ CONFIG_FRAME_POINTER=y
23  # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
24  # CONFIG_LKDTM is not set
25  # CONFIG_FAULT_INJECTION is not set
26 +CONFIG_PANIC_INFO_BUFF=m
27  # CONFIG_LATENCYTOP is not set
28  # CONFIG_SYSCTL_SYSCALL_CHECK is not set
29  CONFIG_HAVE_FUNCTION_TRACER=y
30 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/configs/rx51_tiny_defconfig kernel-2.6.28-20094803.3+0m5/arch/arm/configs/rx51_tiny_defconfig
31 --- kernel-2.6.28-20094102.6+0m5/arch/arm/configs/rx51_tiny_defconfig   2011-09-04 11:36:23.000000000 +0200
32 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/configs/rx51_tiny_defconfig   2011-09-04 11:37:54.000000000 +0200
33 @@ -304,7 +304,7 @@ CONFIG_ALIGNMENT_TRAP=y
34  #
35  CONFIG_ZBOOT_ROM_TEXT=0x0
36  CONFIG_ZBOOT_ROM_BSS=0x0
37 -CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs rootflags=bulk_read,no_chk_data_crc rw console=ttyMTD,log"
38 +CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs rootflags=bulk_read,no_chk_data_crc rw console=ttyMTD,log snd-soc-rx51.hp_lim=42 snd-soc-tlv320aic3x.hp_dac_lim=6"
39  # CONFIG_XIP_KERNEL is not set
40  CONFIG_KEXEC=y
41  CONFIG_ATAGS_PROC=y
42 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/board-rx51.c kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/board-rx51.c
43 --- kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/board-rx51.c       2011-09-04 11:36:23.000000000 +0200
44 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/board-rx51.c       2011-09-04 11:37:54.000000000 +0200
45 @@ -84,11 +84,16 @@ static void __init rx51_init_irq(void)
46  static void __init rx51_pm_init(void)
47  {
48         struct prm_setup_times prm_setup = {
49 -               .clksetup = 81,
50 +               .clksetup = 111, /* must equal Volt offset + voltsetup2 */
51                 .voltsetup_time1 = 270,
52                 .voltsetup_time2 = 150,
53 -               .voltoffset = 17,
54 -               .voltsetup2 = 37,
55 +               /* Time between wakeup event to when the sysoff goes high */
56 +               .voltoffset = 16,
57 +                /* The following is for a 2.25ms ramp time of the oscillator
58 +                 * Documented 2ms, added .25 as margin. NOTE: scripts
59 +                 * change as oscillator changes
60 +                 */
61 +               .voltsetup2 = 95,
62         };
63  
64         omap3_set_prm_setup_times(&prm_setup);
65 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/board-rx51-peripherals.c kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/board-rx51-peripherals.c
66 --- kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/board-rx51-peripherals.c   2011-09-04 11:36:23.000000000 +0200
67 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/board-rx51-peripherals.c   2011-09-04 11:37:54.000000000 +0200
68 @@ -415,8 +415,16 @@ static struct twl4030_gpio_platform_data
69  static struct twl4030_ins sleep_on_seq[] = {
70  /*
71   * Turn off everything.
72 +#define MSG_BROADCAST(devgrp, grp, type, type2, state) \
73 +       ( (devgrp) << 13 | 1 << 12 | (grp) << 9 | (type2) << 7 \
74 +       | (type) << 4 | (state))
75 +#define MSG_SINGULAR(devgrp, id, state) \
76 +       ((devgrp) << 13 | 0 << 12 | (id) << 4 | (state))
77 +       0x14 - Corresponds to 500uSec
78   */
79 -       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_SLEEP), 2},
80 +       {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_SLEEP), 0x14},
81 +       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 4, 1, RES_STATE_SLEEP), 2},
82 +       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 4, 2, RES_STATE_SLEEP), 2},
83  };
84  
85  static struct twl4030_script sleep_on_script = {
86 @@ -433,7 +441,10 @@ static struct twl4030_ins wakeup_seq[] =
87  /*
88   * Reenable everything.
89   */
90 -       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_ACTIVE), 2},
91 +       /* 0x32= 2.25 max(32khz) delay */
92 +       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 2, RES_STATE_ACTIVE), 0x32},
93 +       {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_ACTIVE), 1},
94 +       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 1, RES_STATE_ACTIVE), 2},
95  };
96  
97  static struct twl4030_script wakeup_script = {
98 @@ -461,14 +472,10 @@ static struct twl4030_ins wrst_seq[] = {
99   * Enable sysclk output.
100   * Reenable twl4030.
101   */
102 -       {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 2},
103 -       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 0, 1, RES_STATE_ACTIVE),
104 -               0x13},
105 -       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_PP, 0, 3, RES_STATE_OFF), 0x13},
106 -       {MSG_SINGULAR(DEV_GRP_NULL, RES_VDD1, RES_STATE_WRST), 0x13},
107 -       {MSG_SINGULAR(DEV_GRP_NULL, RES_VDD2, RES_STATE_WRST), 0x13},
108 -       {MSG_SINGULAR(DEV_GRP_NULL, RES_VPLL1, RES_STATE_WRST), 0x35},
109 -       {MSG_SINGULAR(DEV_GRP_P3, RES_HFCLKOUT, RES_STATE_ACTIVE), 2},
110 +       {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 1},
111 +       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 0, 2, RES_STATE_WRST), 1},
112 +       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_PP, 0, 3, RES_STATE_OFF), 0x34},
113 +       {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 0, 1, RES_STATE_WRST), 1},
114         {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 2},
115  };
116  
117 @@ -490,54 +497,31 @@ static struct twl4030_script *twl4030_sc
118  
119  static struct twl4030_resconfig twl4030_rconfig[] = {
120  
121 -       { .resource = RES_VDD1, .devgroup = -1, .type = 1, .type2 = -1,
122 -               .remap = 0 },
123 -       { .resource = RES_VDD2, .devgroup = -1, .type = 1, .type2 = -1,
124 -               .remap = 0 },
125 -       { .resource = RES_VPLL1, .devgroup = -1, .type = 1, .type2 = -1,
126 -               .remap = 0 },
127 -       { .resource = RES_VPLL2, .devgroup = -1, .type = -1, .type2 = 3,
128 -               .remap = -1 },
129 -       { .resource = RES_VAUX1, .devgroup = -1, .type = -1, .type2 = 3,
130 -               .remap = -1 },
131 -       { .resource = RES_VAUX2, .devgroup = -1, .type = -1, .type2 = 3,
132 -               .remap = -1 },
133 -       { .resource = RES_VAUX3, .devgroup = -1, .type = -1, .type2 = 3,
134 -               .remap = -1 },
135 -       { .resource = RES_VAUX4, .devgroup = -1, .type = -1, .type2 = 3,
136 -               .remap = -1 },
137 -       { .resource = RES_VMMC1, .devgroup = -1, .type = -1, .type2 = 3,
138 -               .remap = -1 },
139 -       { .resource = RES_VMMC2, .devgroup = -1, .type = -1, .type2 = 3,
140 -               .remap = -1 },
141 -       { .resource = RES_VDAC, .devgroup = -1, .type = -1, .type2 = 3,
142 -               .remap = -1 },
143 -       { .resource = RES_VSIM, .devgroup = -1, .type = -1, .type2 = 3,
144 -               .remap = -1 },
145 -       { .resource = RES_VINTANA1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
146 -               .type = -1, .type2 = -1, .remap = -1 },
147 -       { .resource = RES_VINTANA2, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
148 -               .type = 1, .type2 = -1, .remap = -1 },
149 -       { .resource = RES_VINTDIG, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
150 -               .type = -1, .type2 = -1, .remap = -1 },
151 -       { .resource = RES_VIO, .devgroup = DEV_GRP_P3,
152 -               .type = 1, .type2 = -1, .remap = -1 },
153 -       { .resource = RES_CLKEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
154 -               .type = 1, .type2 = -1 , .remap = -1 },
155 -       { .resource = RES_REGEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
156 -               .type = 1, .type2 = -1, .remap = -1 },
157 -       { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
158 -               .type = 1, .type2 = -1, .remap = -1 },
159 -       { .resource = RES_SYSEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
160 -               .type = 1, .type2 = -1, .remap = -1 },
161 -       { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3, .type = 1,
162 -               .type2 = -1, .remap = -1 },
163 -       { .resource = RES_32KCLKOUT, .devgroup = -1, .type = 1, .type2 = -1,
164 -               .remap = -1 },
165 -       { .resource = RES_RESET, .devgroup = -1, .type = 1, .type2 = -1,
166 -               .remap = -1 },
167 -       { .resource = RES_Main_Ref, .devgroup = -1, .type = 1, .type2 = -1,
168 -               .remap = -1 },
169 +       /* Default p1*/
170 +       { .resource = RES_VDD1,         .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 4, .type2 =  1, .remap =  0 },
171 +       { .resource = RES_VDD2,         .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 3, .type2 =  1, .remap =  0 },
172 +       { .resource = RES_VPLL1,        .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 3, .type2 =  1, .remap =  0 },
173 +       { .resource = RES_VPLL2,        .devgroup = -1,                         .type = 0, .type2 =  3, .remap =  8 },
174 +       { .resource = RES_VAUX1,        .devgroup = -1,                         .type = 0, .type2 =  3, .remap =  8 },
175 +       { .resource = RES_VAUX2,        .devgroup = -1,                         .type = 0, .type2 =  3, .remap =  8 },
176 +       { .resource = RES_VAUX3,        .devgroup = -1,                         .type = 0, .type2 =  3, .remap =  8 },
177 +       { .resource = RES_VAUX4,        .devgroup = -1,                         .type = 0, .type2 =  3, .remap =  8 },
178 +       { .resource = RES_VMMC1,        .devgroup = -1,                         .type = 0, .type2 =  3, .remap =  8 },
179 +       { .resource = RES_VMMC2,        .devgroup = -1,                         .type = 0, .type2 =  3, .remap =  8 },
180 +       { .resource = RES_VDAC,         .devgroup = -1,                         .type = 0, .type2 =  3, .remap =  8 },
181 +       { .resource = RES_VSIM,         .devgroup = -1,                         .type = 0, .type2 =  3, .remap =  8 },
182 +       { .resource = RES_VINTANA1,     .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 1, .type2 =  2, .remap =  8 },
183 +       { .resource = RES_VINTANA2,     .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 0, .type2 =  2, .remap =  8 },
184 +       { .resource = RES_VINTDIG,      .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 1, .type2 =  2, .remap =  8 },
185 +       { .resource = RES_VIO,          .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 2, .type2 =  2, .remap =  8 },
186 +       { .resource = RES_CLKEN,        .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 3, .type2 =  2, .remap =  8 },
187 +       { .resource = RES_REGEN,        .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 2, .type2 =  1, .remap =  8 },
188 +       { .resource = RES_NRES_PWRON,   .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 0, .type2 =  1, .remap =  8 },
189 +       { .resource = RES_SYSEN,        .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 6, .type2 =  1, .remap =  8 },
190 +       { .resource = RES_HFCLKOUT,     .devgroup = DEV_GRP_P1 | DEV_GRP_P3,    .type = 0, .type2 =  1, .remap =  8 },
191 +       { .resource = RES_32KCLKOUT,    .devgroup = DEV_GRP_P1 | DEV_GRP_P2 | DEV_GRP_P3,       .type = 0, .type2 =  0, .remap =  8 },
192 +       { .resource = RES_RESET,        .devgroup = DEV_GRP_P1 | DEV_GRP_P2 | DEV_GRP_P3,       .type = 6, .type2 =  0, .remap =  8 },
193 +       { .resource = RES_Main_Ref,     .devgroup = DEV_GRP_P1 | DEV_GRP_P2 | DEV_GRP_P3,       .type = 0, .type2 =  0, .remap =  8 },
194         { 0, 0},
195  };
196  
197 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/cpuidle34xx.c kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/cpuidle34xx.c
198 --- kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/cpuidle34xx.c      2011-09-04 11:36:23.000000000 +0200
199 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/cpuidle34xx.c      2011-09-04 11:37:54.000000000 +0200
200 @@ -180,8 +180,8 @@ void omap_init_power_states(void)
201         /* C1 . MPU WFI + Core active */
202         omap3_power_states[OMAP3_STATE_C1].valid = 1;
203         omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1;
204 -       omap3_power_states[OMAP3_STATE_C1].sleep_latency = 58;
205 -       omap3_power_states[OMAP3_STATE_C1].wakeup_latency = 52;
206 +       omap3_power_states[OMAP3_STATE_C1].sleep_latency = 110;
207 +       omap3_power_states[OMAP3_STATE_C1].wakeup_latency = 162;
208         omap3_power_states[OMAP3_STATE_C1].threshold = 5;
209         omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON;
210         omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON;
211 @@ -190,9 +190,9 @@ void omap_init_power_states(void)
212         /* C2 . MPU WFI + Core inactive */
213         omap3_power_states[OMAP3_STATE_C2].valid = 1;
214         omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2;
215 -       omap3_power_states[OMAP3_STATE_C2].sleep_latency = 73;
216 -       omap3_power_states[OMAP3_STATE_C2].wakeup_latency = 164;
217 -       omap3_power_states[OMAP3_STATE_C2].threshold = 30;
218 +       omap3_power_states[OMAP3_STATE_C2].sleep_latency = 106;
219 +       omap3_power_states[OMAP3_STATE_C2].wakeup_latency = 180;
220 +       omap3_power_states[OMAP3_STATE_C2].threshold = 309;
221         omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
222         omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
223         omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
224 @@ -201,9 +201,9 @@ void omap_init_power_states(void)
225         /* C3 . MPU CSWR + Core inactive */
226         omap3_power_states[OMAP3_STATE_C3].valid = 0;
227         omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3;
228 -       omap3_power_states[OMAP3_STATE_C3].sleep_latency = 90;
229 -       omap3_power_states[OMAP3_STATE_C3].wakeup_latency = 267;
230 -       omap3_power_states[OMAP3_STATE_C3].threshold = 113872; /* vs. C2 */
231 +       omap3_power_states[OMAP3_STATE_C3].sleep_latency = 107;
232 +       omap3_power_states[OMAP3_STATE_C3].wakeup_latency = 410;
233 +       omap3_power_states[OMAP3_STATE_C3].threshold = 46057;
234         omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET;
235         omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
236         omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
237 @@ -212,9 +212,9 @@ void omap_init_power_states(void)
238         /* C4 . MPU OFF + Core inactive */
239         omap3_power_states[OMAP3_STATE_C4].valid = 0;
240         omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4;
241 -       omap3_power_states[OMAP3_STATE_C4].sleep_latency = 4130;
242 -       omap3_power_states[OMAP3_STATE_C4].wakeup_latency = 2130;
243 -       omap3_power_states[OMAP3_STATE_C4].threshold = 619328; /* vs. C2 */
244 +       omap3_power_states[OMAP3_STATE_C4].sleep_latency = 121;
245 +       omap3_power_states[OMAP3_STATE_C4].wakeup_latency = 3374;
246 +       omap3_power_states[OMAP3_STATE_C4].threshold = 46057;
247         omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF;
248         omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
249         omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
250 @@ -223,9 +223,9 @@ void omap_init_power_states(void)
251         /* C5 . MPU CSWR + Core CSWR*/
252         omap3_power_states[OMAP3_STATE_C5].valid = 1;
253         omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5;
254 -       omap3_power_states[OMAP3_STATE_C5].sleep_latency = 596;
255 -       omap3_power_states[OMAP3_STATE_C5].wakeup_latency = 1000;
256 -       omap3_power_states[OMAP3_STATE_C5].threshold = 7971;
257 +       omap3_power_states[OMAP3_STATE_C5].sleep_latency = 855;
258 +       omap3_power_states[OMAP3_STATE_C5].wakeup_latency = 1146;
259 +       omap3_power_states[OMAP3_STATE_C5].threshold = 46057;
260         omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_RET;
261         omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET;
262         omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID |
263 @@ -234,9 +234,9 @@ void omap_init_power_states(void)
264         /* C6 . MPU OFF + Core CSWR */
265         omap3_power_states[OMAP3_STATE_C6].valid = 0;
266         omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6;
267 -       omap3_power_states[OMAP3_STATE_C6].sleep_latency = 4600;
268 -       omap3_power_states[OMAP3_STATE_C6].wakeup_latency = 2850;
269 -       omap3_power_states[OMAP3_STATE_C6].threshold = 2801100; /* vs. C5 */
270 +       omap3_power_states[OMAP3_STATE_C6].sleep_latency = 7580;
271 +       omap3_power_states[OMAP3_STATE_C6].wakeup_latency = 4134;
272 +       omap3_power_states[OMAP3_STATE_C6].threshold = 484329;
273         omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF;
274         omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET;
275         omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID |
276 @@ -245,9 +245,9 @@ void omap_init_power_states(void)
277         /* C7 . MPU OFF + Core OFF */
278         omap3_power_states[OMAP3_STATE_C7].valid = 1;
279         omap3_power_states[OMAP3_STATE_C7].type = OMAP3_STATE_C7;
280 -       omap3_power_states[OMAP3_STATE_C7].sleep_latency = 4760;
281 -       omap3_power_states[OMAP3_STATE_C7].wakeup_latency = 7780;
282 -       omap3_power_states[OMAP3_STATE_C7].threshold = 610082;
283 +       omap3_power_states[OMAP3_STATE_C7].sleep_latency = 7505;
284 +       omap3_power_states[OMAP3_STATE_C7].wakeup_latency = 15274;
285 +       omap3_power_states[OMAP3_STATE_C7].threshold = 484329;
286         omap3_power_states[OMAP3_STATE_C7].mpu_state = PWRDM_POWER_OFF;
287         omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF;
288         omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID |
289 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/mmc-twl4030.c kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/mmc-twl4030.c
290 --- kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/mmc-twl4030.c      2011-09-04 11:36:23.000000000 +0200
291 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/mmc-twl4030.c      2011-09-04 11:37:54.000000000 +0200
292 @@ -36,6 +36,12 @@
293  #define MMCHS_SYSSTATUS                        0x0014
294  #define MMCHS_SYSSTATUS_RESETDONE      (1 << 0)
295  
296 +#define OMAP343X_PADCONF_MMC2_CMD      (OMAP2_CONTROL_PADCONFS + 0x12A)
297 +#define OMAP343X_PADCONF_MMC2_DAT0     (OMAP2_CONTROL_PADCONFS + 0x12C)
298 +#define OMAP343X_PADCONF_MMC2_DAT2     (OMAP2_CONTROL_PADCONFS + 0x130)
299 +#define OMAP343X_PADCONF_MMC2_DAT4     (OMAP2_CONTROL_PADCONFS + 0x134)
300 +#define OMAP343X_PADCONF_MMC2_DAT6     (OMAP2_CONTROL_PADCONFS + 0x138)
301 +
302  static struct platform_device dummy_pdev = {
303         .dev = {
304                 .bus = &platform_bus_type,
305 @@ -599,6 +605,14 @@ static int twl_mmc2_set_power(struct dev
306          * transceiver is used, DAT3..7 are muxed as transceiver control pins.
307          */
308         if (power_on) {
309 +               if (!cpu_is_omap2430()) {
310 +                       /* Pull up */
311 +                       omap_ctrl_writew(    0x118, OMAP343X_PADCONF_MMC2_CMD);
312 +                       omap_ctrl_writel(0x1180118, OMAP343X_PADCONF_MMC2_DAT0);
313 +                       omap_ctrl_writel(0x1180118, OMAP343X_PADCONF_MMC2_DAT2);
314 +                       omap_ctrl_writel(0x1180118, OMAP343X_PADCONF_MMC2_DAT4);
315 +                       omap_ctrl_writel(0x1180118, OMAP343X_PADCONF_MMC2_DAT6);
316 +               }
317                 if (mmc->slots[0].internal_clock) {
318                         u32 reg;
319  
320 @@ -608,6 +622,14 @@ static int twl_mmc2_set_power(struct dev
321                 }
322                 ret = twl_mmc_set_voltage(c, vdd);
323         } else {
324 +               if (!cpu_is_omap2430()) {
325 +                       /* Pull down */
326 +                       omap_ctrl_writew(    0x108, OMAP343X_PADCONF_MMC2_CMD);
327 +                       omap_ctrl_writel(0x1080108, OMAP343X_PADCONF_MMC2_DAT0);
328 +                       omap_ctrl_writel(0x1080108, OMAP343X_PADCONF_MMC2_DAT2);
329 +                       omap_ctrl_writel(0x1080108, OMAP343X_PADCONF_MMC2_DAT4);
330 +                       omap_ctrl_writel(0x1080108, OMAP343X_PADCONF_MMC2_DAT6);
331 +               }
332                 ret = twl_mmc_set_voltage(c, 0);
333         }
334  
335 @@ -649,12 +671,14 @@ static int twl_mmc2_set_sleep(struct dev
336                 return twl_mmc_regulator_set_mode(c->twl_vmmc_dev_grp, sleep);
337  
338         if (cardsleep) {
339 +               struct twl_mmc_controller *c = &hsmmc[1];
340 +
341                 /* VCC can be turned off if card is asleep */
342                 c->vsim_18v = 0;
343                 if (sleep)
344 -                       err = twl_mmc2_set_power(dev, slot, 0, 0);
345 +                       err = twl_mmc_set_voltage(c, 0);
346                 else
347 -                       err = twl_mmc2_set_power(dev, slot, 1, vdd);
348 +                       err = twl_mmc_set_voltage(c, vdd);
349                 c->vsim_18v = 1;
350         } else
351                 err = twl_mmc_regulator_set_mode(c->twl_vmmc_dev_grp, sleep);
352 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/pm-debug.c kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/pm-debug.c
353 --- kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/pm-debug.c 2011-09-04 11:36:23.000000000 +0200
354 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/pm-debug.c 2011-09-04 11:37:54.000000000 +0200
355 @@ -169,7 +169,8 @@ static int pm_dbg_init_done;
356  enum {
357         DEBUG_FILE_COUNTERS = 0,
358         DEBUG_FILE_TIMERS,
359 -       DEBUG_FILE_RESOURCES
360 +       DEBUG_FILE_RESOURCES,
361 +       DEBUG_FILE_WAIT_SDRC_COUNT
362  };
363  
364  struct pm_module_def {
365 @@ -428,9 +429,21 @@ static int pm_dbg_show_timers(struct seq
366         return 0;
367  }
368  
369 +static int pm_dbg_show_sdrc_wait_count(struct seq_file *s, void *unused)
370 +{
371 +       unsigned int *sdrc_counters = omap3_get_sdrc_counters();
372 +
373 +       seq_printf(s, "dll kick count: %u\n", sdrc_counters[0]);
374 +       seq_printf(s, "wait dll lock count: %u\n", sdrc_counters[1]);
375 +
376 +       return 0;
377 +}
378  static int pm_dbg_open(struct inode *inode, struct file *file)
379  {
380         switch ((int)inode->i_private) {
381 +       case DEBUG_FILE_WAIT_SDRC_COUNT:
382 +               return single_open(file, pm_dbg_show_sdrc_wait_count,
383 +                       &inode->i_private);
384         case DEBUG_FILE_COUNTERS:
385                 return single_open(file, pm_dbg_show_counters,
386                         &inode->i_private);
387 @@ -548,6 +561,8 @@ static int __init pm_dbg_init(void)
388                 d, (void *)DEBUG_FILE_TIMERS, &debug_fops);
389         (void) debugfs_create_file("resources", S_IRUGO,
390                 d, (void *)DEBUG_FILE_RESOURCES, &debug_fops);
391 +       (void) debugfs_create_file("wait_sdrc_count", S_IRUGO,
392 +               d, (void *)DEBUG_FILE_WAIT_SDRC_COUNT, &debug_fops);
393  
394         pwrdm_for_each(pwrdms_setup, (void *)d);
395  
396 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/pm.h kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/pm.h
397 --- kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/pm.h       2011-09-04 11:36:23.000000000 +0200
398 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/pm.h       2011-09-04 11:37:54.000000000 +0200
399 @@ -50,6 +50,7 @@ extern void omap3_pm_off_mode_enable(int
400  extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm);
401  extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);
402  extern void omap3_set_prm_setup_times(struct prm_setup_times *setup_times);
403 +extern unsigned int *omap3_get_sdrc_counters(void);
404  #else
405  #define omap3_pm_off_mode_enable(int) do {} while (0);
406  #define omap3_pm_get_suspend_state(pwrdm) do {} while (0);
407 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/pm34xx.c kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/pm34xx.c
408 --- kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/pm34xx.c   2011-09-04 11:36:23.000000000 +0200
409 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/pm34xx.c   2011-09-04 11:37:54.000000000 +0200
410 @@ -127,6 +127,9 @@ static int (*_omap_save_secure_sram)(u32
411  
412  static void (*saved_idle)(void);
413  
414 +static unsigned int *_sdrc_counters;
415 +static unsigned int save_sdrc_counters[2];
416 +
417  static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
418  static struct powerdomain *core_pwrdm, *per_pwrdm;
419  static struct powerdomain *cam_pwrdm, *iva2_pwrdm, *dss_pwrdm, *usb_pwrdm;
420 @@ -301,7 +304,15 @@ static void omap3_core_save_context(void
421         /* wait for the save to complete */
422         while (!(omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
423                         & PADCONF_SAVE_DONE))
424 -               ;
425 +               udelay(1);
426 +
427 +       /*
428 +        * Force write last pad into memory, as this can fail in some
429 +        * cases according to errata XYZ
430 +        */
431 +       omap_ctrl_writel(omap_ctrl_readl(OMAP343X_PADCONF_ETK_D14),
432 +               OMAP343X_CONTROL_MEM_WKUP + 0x2a0);
433 +
434         /* Save the Interrupt controller context */
435         omap3_intc_save_context();
436         /* Save the GPMC context */
437 @@ -668,6 +679,8 @@ void omap_sram_idle(void)
438                                   OMAP3_PRM_CLKSETUP_OFFSET);
439         }
440  
441 +       memcpy(save_sdrc_counters, _sdrc_counters, sizeof(save_sdrc_counters));
442 +
443         /*
444          * omap3_arm_context is the location where ARM registers
445          * get saved. The restore path then reads from this
446 @@ -697,6 +710,7 @@ void omap_sram_idle(void)
447                         omap3_sram_restore_context();
448                         omap2_sms_restore_context();
449                         reset_ssi();
450 +                       memcpy(_sdrc_counters, save_sdrc_counters, sizeof(save_sdrc_counters));
451                 }
452                 omap_uart_resume_idle(0);
453                 omap_uart_resume_idle(1);
454 @@ -802,6 +816,12 @@ err:
455         return ret;
456  }
457  
458 +/* return a pointer to the sdrc counters */
459 +unsigned int *omap3_get_sdrc_counters(void)
460 +{
461 +       return _sdrc_counters;
462 +}
463 +
464  static void omap3_pm_idle(void)
465  {
466         local_irq_disable();
467 @@ -1251,6 +1271,10 @@ void omap_push_sram_idle(void)
468  {
469         _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
470                                         omap34xx_cpu_suspend_sz);
471 +       /* the sdrc counters are always at the end of the omap34xx_cpu_suspend
472 +        * block */
473 +       _sdrc_counters = (unsigned *)((u8 *)_omap_sram_idle + omap34xx_cpu_suspend_sz - 8);
474 +
475         if (omap_type() != OMAP2_DEVICE_TYPE_GP)
476                 _omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
477                                 save_secure_ram_context_sz);
478 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/sleep34xx.S kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/sleep34xx.S
479 --- kernel-2.6.28-20094102.6+0m5/arch/arm/mach-omap2/sleep34xx.S        2011-09-04 11:36:23.000000000 +0200
480 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/mach-omap2/sleep34xx.S        2011-09-04 11:37:54.000000000 +0200
481 @@ -40,6 +40,7 @@
482  #define PM_PREPWSTST_MPU_V     OMAP34XX_PRM_REGADDR(MPU_MOD, \
483                                 OMAP3430_PM_PREPWSTST)
484  #define CM_IDLEST1_CORE_V      IO_ADDRESS(OMAP3430_CM_BASE + 0x220)
485 +#define CM_IDLEST_CKGEN_V      IO_ADDRESS(OMAP3430_CM_BASE + 0x520)
486  
487  /*
488   * This is the physical address of the register as specified
489 @@ -703,35 +704,70 @@ skip_l2_inval:
490  
491  /* Make sure SDRC accesses are ok */
492  wait_sdrc_ok:
493 +
494 +/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this. */
495 +       ldr     r4, cm_idlest_ckgen
496 +wait_dpll3_lock:
497 +       ldr     r5, [r4]
498 +       tst     r5, #1
499 +       beq     wait_dpll3_lock
500 +
501          ldr     r4, cm_idlest1_core
502 +wait_sdrc_ready:
503          ldr     r5, [r4]
504 -        and     r5, r5, #0x2
505 -        cmp     r5, #0
506 -        bne     wait_sdrc_ok
507 +        tst     r5, #0x2
508 +        bne     wait_sdrc_ready
509 +       /* allow DLL powerdown upon hw idle req */
510          ldr     r4, sdrc_power
511          ldr     r5, [r4]
512          bic     r5, r5, #0x40
513          str     r5, [r4]
514 -wait_dll_lock:
515 -        /* Is dll in lock mode? */
516 +is_dll_in_lock_mode:
517          ldr     r4, sdrc_dlla_ctrl
518          ldr     r5, [r4]
519          tst     r5, #0x4
520          bxne    lr
521          /* wait till dll locks */
522 +wait_dll_lock_timed:
523 +       ldr     r4, wait_dll_lock_counter
524 +       add     r4, r4, #1
525 +       str     r4, wait_dll_lock_counter
526          ldr     r4, sdrc_dlla_status
527 +        mov     r6, #8                         /* Wait 20uS for lock */
528 +wait_dll_lock:
529 +        subs    r6, r6, #0x1
530 +        beq     kick_dll
531          ldr     r5, [r4]
532          and     r5, r5, #0x4
533          cmp     r5, #0x4
534          bne     wait_dll_lock
535          bx      lr
536  
537 +        /* disable/reenable DLL if locked */
538 +kick_dll:
539 +       ldr     r4, sdrc_dlla_ctrl      /* get dlla addr */
540 +       ldr     r5, [r4]                /* grab value */
541 +       mov     r6, r5                  /* save value */
542 +       bic     r6, #(1<<3)             /* disable dll */
543 +       str     r6, [r4]
544 +       dsb
545 +       orr     r6, r6, #(1<<3)         /* enable dll */
546 +       str     r6, [r4]
547 +       dsb
548 +       str     r5, [r4]                /* restore old value */
549 +       ldr     r4, kick_counter
550 +       add     r4, r4, #1
551 +       str     r4, kick_counter
552 +       b       wait_dll_lock_timed
553 +
554  phys_offset:
555         .word   PHYS_OFFSET
556  page_offset:
557         .word   PAGE_OFFSET
558  cm_idlest1_core:
559         .word   CM_IDLEST1_CORE_V
560 +cm_idlest_ckgen:
561 +       .word   CM_IDLEST_CKGEN_V
562  sdrc_dlla_status:
563         .word   SDRC_DLLA_STATUS_V
564  sdrc_dlla_ctrl:
565 @@ -766,5 +802,10 @@ cache_pred_disable_mask:
566         .word   0xFFFFE7FB
567  control_stat:
568         .word   CONTROL_STAT
569 +       /* these 2 words need to be at the end !!! */
570 +kick_counter:
571 +       .word   0
572 +wait_dll_lock_counter:
573 +       .word   0
574  ENTRY(omap34xx_cpu_suspend_sz)
575         .word   . - omap34xx_cpu_suspend
576 diff -Nurp kernel-2.6.28-20094102.6+0m5/arch/arm/plat-omap/iovmm.c kernel-2.6.28-20094803.3+0m5/arch/arm/plat-omap/iovmm.c
577 --- kernel-2.6.28-20094102.6+0m5/arch/arm/plat-omap/iovmm.c     2011-09-04 11:36:23.000000000 +0200
578 +++ kernel-2.6.28-20094803.3+0m5/arch/arm/plat-omap/iovmm.c     2011-09-04 11:37:54.000000000 +0200
579 @@ -47,7 +47,7 @@
580   *     'va':   mpu virtual address
581   *
582   *     'c':    contiguous memory area
583 - *     'd':    dicontiguous memory area
584 + *     'd':    discontiguous memory area
585   *     'a':    anonymous memory allocation
586   *     '()':   optional feature
587   *
588 @@ -385,14 +385,13 @@ static void sgtable_fill_vmalloc(struct
589         }
590  
591         va_end = _va + PAGE_SIZE * i;
592 -       flush_cache_vmap(_va, va_end);
593  }
594  
595  static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
596  {
597         /*
598          * Actually this is not necessary at all, just exists for
599 -        * consistency of the code readibility.
600 +        * consistency of the code readability.
601          */
602         BUG_ON(!sgt);
603  }
604 @@ -420,15 +419,13 @@ static void sgtable_fill_kmalloc(struct
605                 len -= bytes;
606         }
607         BUG_ON(len);
608 -
609 -       clean_dcache_area(va, len);
610  }
611  
612  static inline void sgtable_drain_kmalloc(struct sg_table *sgt)
613  {
614         /*
615          * Actually this is not necessary at all, just exists for
616 -        * consistency of the code readibility
617 +        * consistency of the code readability
618          */
619         BUG_ON(!sgt);
620  }
621 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/dsp/bridge/rmgr/proc.c kernel-2.6.28-20094803.3+0m5/drivers/dsp/bridge/rmgr/proc.c
622 --- kernel-2.6.28-20094102.6+0m5/drivers/dsp/bridge/rmgr/proc.c 2011-09-04 11:36:23.000000000 +0200
623 +++ kernel-2.6.28-20094803.3+0m5/drivers/dsp/bridge/rmgr/proc.c 2011-09-04 11:37:54.000000000 +0200
624 @@ -159,6 +159,8 @@
625  #define PWR_TIMEOUT     500    /* Sleep/wake timout in msec */
626  #define EXTEND       "_EXT_END"        /* Extmem end addr in DSP binary */
627  
628 +#define DSP_CACHE_LINE 128
629 +
630  extern char *iva_img;
631  
632  /*  ----------------------------------- Globals */
633 @@ -679,8 +681,48 @@ DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR
634         return status;
635  }
636  
637 +/* Cache operation against kernel address instead of users */
638 +static int memory_sync_page(struct vm_area_struct *vma, unsigned long start,
639 +                           ssize_t len, enum DSP_FLUSHTYPE ftype)
640 +{
641 +       struct page *page;
642 +       void *kaddr;
643 +       unsigned long offset;
644 +       ssize_t rest;
645 +
646 +#ifdef CHECK_DSP_CACHE_LINE
647 +       if ((start & DSP_CACHE_LINE) || (len & DSP_CACHE_LINE))
648 +               pr_warning("%s: not aligned: %08lx(%d)\n", __func__,
649 +                          start, len);
650 +#endif
651 +       while (len) {
652 +               page = follow_page(vma, start, FOLL_GET);
653 +               if (!page) {
654 +                       pr_err("%s: no page for %08lx\n", __func__, start);
655 +                       return -EINVAL;
656 +               } else if (IS_ERR(page)) {
657 +                       pr_err("%s: err page for %08lx(%lu)\n", __func__, start,
658 +                              IS_ERR(page));
659 +                       return IS_ERR(page);
660 +               }
661 +
662 +               offset = start & ~PAGE_MASK;
663 +               kaddr = page_address(page) + offset;
664 +               rest = min_t(ssize_t, PAGE_SIZE - offset, len);
665 +
666 +               MEM_FlushCache(kaddr, rest, ftype);
667 +
668 +               put_page(page);
669 +               len -= rest;
670 +               start += rest;
671 +       }
672 +
673 +       return 0;
674 +}
675 +
676  /* Check if the given area blongs to process virtul memory address space */
677 -static int memory_check_vma(unsigned long start, u32 len)
678 +static int memory_sync_vma(unsigned long start, u32 len,
679 +                          enum DSP_FLUSHTYPE ftype)
680  {
681         int err = 0;
682         unsigned long end;
683 @@ -690,14 +732,19 @@ static int memory_check_vma(unsigned lon
684         if (end <= start)
685                 return -EINVAL;
686  
687 -       down_read(&current->mm->mmap_sem);
688 -
689         while ((vma = find_vma(current->mm, start)) != NULL) {
690 +               ssize_t size;
691 +
692 +               if (vma->vm_flags & (VM_IO | VM_PFNMAP))
693 +                       return -EINVAL;
694 +
695 +               if (vma->vm_start > start)
696 +                       return -EINVAL;
697  
698 -               if (vma->vm_start > start) {
699 -                       err = -EINVAL;
700 +               size = min_t(ssize_t, vma->vm_end - start, len);
701 +               err = memory_sync_page(vma, start, size, ftype);
702 +               if (err)
703                         break;
704 -               }
705  
706                 if (end <= vma->vm_end)
707                         break;
708 @@ -708,8 +755,6 @@ static int memory_check_vma(unsigned lon
709         if (!vma)
710                 err = -EINVAL;
711  
712 -       up_read(&current->mm->mmap_sem);
713 -
714         return err;
715  }
716  
717 @@ -734,18 +779,15 @@ static DSP_STATUS proc_memory_sync(DSP_H
718                 goto err_out;
719         }
720  
721 -       if (memory_check_vma((u32)pMpuAddr, ulSize)) {
722 -               GT_3trace(PROC_DebugMask, GT_7CLASS,
723 -                         "%s: InValid address parameters\n",
724 -                         __func__, pMpuAddr, ulSize);
725 +       down_read(&current->mm->mmap_sem);
726 +
727 +       if (memory_sync_vma((u32)pMpuAddr, ulSize, FlushMemType)) {
728 +               pr_err("%s: InValid address parameters %p %x\n",
729 +                      __func__, pMpuAddr, ulSize);
730                 status = DSP_EHANDLE;
731 -               goto err_out;
732         }
733  
734 -       (void)SYNC_EnterCS(hProcLock);
735 -       MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
736 -       (void)SYNC_LeaveCS(hProcLock);
737 -
738 +       up_read(&current->mm->mmap_sem);
739  err_out:
740         GT_2trace(PROC_DebugMask, GT_ENTER,
741                   "Leaving %s [0x%x]", __func__, status);
742 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/bridged_pvr_bridge.c kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/bridged_pvr_bridge.c
743 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/bridged_pvr_bridge.c   2011-09-04 11:36:23.000000000 +0200
744 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/bridged_pvr_bridge.c   2011-09-04 11:37:54.000000000 +0200
745 @@ -791,25 +791,25 @@ PVRSRVUnmapDeviceMemoryBW(IMG_UINT32 ui3
746  }
747  
748  static int
749 -FlushCacheDRI(IMG_UINT32 ui32Type, IMG_UINT32 ui32Virt, IMG_UINT32 ui32Length)
750 +FlushCacheDRI(IMG_UINT32 ui32Type, IMG_VOID *pvVirt, IMG_UINT32 ui32Length)
751  {
752         switch (ui32Type) {
753         case DRM_PVR2D_CFLUSH_FROM_GPU:
754                 PVR_DPF((PVR_DBG_MESSAGE,
755                          "DRM_PVR2D_CFLUSH_FROM_GPU 0x%08x, length 0x%08x\n",
756 -                        ui32Virt, ui32Length));
757 +                        pvVirt, ui32Length));
758  #ifdef CONFIG_ARM
759 -               dmac_inv_range((const void *)ui32Virt,
760 -                              (const void *)(ui32Virt + ui32Length));
761 +               dmac_inv_range((const void *)pvVirt,
762 +                              (const void *)(pvVirt + ui32Length));
763  #endif
764                 return 0;
765         case DRM_PVR2D_CFLUSH_TO_GPU:
766                 PVR_DPF((PVR_DBG_MESSAGE,
767                          "DRM_PVR2D_CFLUSH_TO_GPU 0x%08x, length 0x%08x\n",
768 -                        ui32Virt, ui32Length));
769 +                        pvVirt, ui32Length));
770  #ifdef CONFIG_ARM
771 -               dmac_clean_range((const void *)ui32Virt,
772 -                                (const void *)(ui32Virt + ui32Length));
773 +               dmac_clean_range((const void *)pvVirt,
774 +                                (const void *)(pvVirt + ui32Length));
775  #endif
776                 return 0;
777         default:
778 @@ -821,18 +821,51 @@ FlushCacheDRI(IMG_UINT32 ui32Type, IMG_U
779         return 0;
780  }
781  
782 +PVRSRV_ERROR
783 +PVRSRVIsWrappedExtMemoryBW(PVRSRV_PER_PROCESS_DATA *psPerProc,
784 +                          PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER *psCacheFlushIN)
785 +{
786 +       PVRSRV_ERROR eError;
787 +       IMG_HANDLE hDevCookieInt;
788 +
789 +       PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
790 +                                                  psCacheFlushIN->hDevCookie,
791 +                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
792 +
793 +       eError = PVRSRVIsWrappedExtMemoryKM(
794 +                                       hDevCookieInt,
795 +                                       psPerProc,
796 +                                       &(psCacheFlushIN->ui32Length),
797 +                                       &(psCacheFlushIN->pvVirt));
798 +
799 +       return eError;
800 +}
801 +
802  static int
803  PVRSRVCacheFlushDRIBW(IMG_UINT32 ui32BridgeID,
804                       PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER * psCacheFlushIN,
805                       PVRSRV_BRIDGE_RETURN * psRetOUT,
806                       PVRSRV_PER_PROCESS_DATA * psPerProc)
807  {
808 +       PVRSRV_ERROR eError;
809         PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CACHE_FLUSH_DRM);
810  
811 -       psRetOUT->eError = FlushCacheDRI(psCacheFlushIN->ui32Type,
812 -                                        psCacheFlushIN->ui32Virt,
813 -                                        psCacheFlushIN->ui32Length);
814 +       down_read(&current->mm->mmap_sem);
815 +
816 +       eError = PVRSRVIsWrappedExtMemoryBW(psPerProc, psCacheFlushIN);
817 +
818 +       if (eError == PVRSRV_OK) {
819 +               psRetOUT->eError = FlushCacheDRI(psCacheFlushIN->ui32Type,
820 +                                                                                       psCacheFlushIN->pvVirt,
821 +                                                                                       psCacheFlushIN->ui32Length);
822 +       } else {
823 +               printk(KERN_WARNING
824 +                       ": PVRSRVCacheFlushDRIBW: Start address 0x%08x and length 0x%08x not wrapped \n",
825 +                       (unsigned int)(psCacheFlushIN->pvVirt),
826 +                       (unsigned int)(psCacheFlushIN->ui32Length));
827 +       }
828  
829 +       up_read(&current->mm->mmap_sem);
830         return 0;
831  }
832  
833 @@ -987,7 +1020,7 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32Bri
834         IMG_HANDLE hDevCookieInt;
835         PVRSRV_KERNEL_MEM_INFO *psMemInfo;
836         IMG_UINT32 ui32PageTableSize = 0;
837 -       IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;;
838 +       IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;
839  
840         PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_WRAP_EXT_MEMORY);
841  
842 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/buffer_manager.c kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/buffer_manager.c
843 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/buffer_manager.c       2011-09-04 11:36:23.000000000 +0200
844 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/buffer_manager.c       2011-09-04 11:37:54.000000000 +0200
845 @@ -30,6 +30,8 @@
846  #include "ra.h"
847  #include "pdump_km.h"
848  
849 +#include <linux/kernel.h>
850 +
851  #define MIN(a,b)       (a > b ? b : a)
852  
853  static IMG_BOOL
854 @@ -988,6 +990,34 @@ BM_IsWrapped(IMG_HANDLE hDevMemHeap,
855  }
856  
857  IMG_BOOL
858 +BM_IsWrappedCheckSize(IMG_HANDLE hDevMemHeap,
859 +                IMG_UINT32 ui32Offset,
860 +                IMG_SYS_PHYADDR sSysAddr,
861 +                IMG_UINT32 ui32ByteSize)
862 +{
863 +       BM_BUF *pBuf;
864 +       BM_CONTEXT *psBMContext;
865 +       BM_HEAP *psBMHeap;
866 +
867 +       IMG_BOOL ret = IMG_FALSE;
868 +
869 +       psBMHeap = (BM_HEAP *) hDevMemHeap;
870 +       psBMContext = psBMHeap->pBMContext;
871 +       sSysAddr.uiAddr += ui32Offset;
872 +       pBuf = (BM_BUF *) HASH_Retrieve(psBMContext->pBufferHash,
873 +                       (IMG_UINTPTR_T) sSysAddr.uiAddr);
874 +
875 +       if (pBuf != NULL) {
876 +               if (pBuf->pMapping->uSize >= ui32ByteSize)
877 +                       ret = IMG_TRUE;
878 +               else
879 +                       ret = IMG_FALSE;
880 +       }
881 +
882 +       return ret;
883 +}
884 +
885 +IMG_BOOL
886  BM_Wrap(IMG_HANDLE hDevMemHeap,
887         IMG_UINT32 ui32Size,
888         IMG_UINT32 ui32Offset,
889 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/buffer_manager.h kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/buffer_manager.h
890 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/buffer_manager.h       2011-09-04 11:36:23.000000000 +0200
891 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/buffer_manager.h       2011-09-04 11:37:54.000000000 +0200
892 @@ -138,6 +138,12 @@
893                          IMG_UINT32 ui32Offset, IMG_SYS_PHYADDR sSysAddr);
894  
895          IMG_BOOL
896 +           BM_IsWrappedCheckSize(IMG_HANDLE hDevMemHeap,
897 +                        IMG_UINT32 ui32Offset,
898 +                        IMG_SYS_PHYADDR sSysAddr,
899 +                        IMG_UINT32 ui32ByteSize);
900 +
901 +        IMG_BOOL
902             BM_Wrap(IMG_HANDLE hDevMemHeap,
903                     IMG_UINT32 ui32Size,
904                     IMG_UINT32 ui32Offset,
905 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/devicemem.c kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/devicemem.c
906 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/devicemem.c    2011-09-04 11:36:23.000000000 +0200
907 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/devicemem.c    2011-09-04 11:37:54.000000000 +0200
908 @@ -34,6 +34,7 @@
909  #include "pvr_bridge_km.h"
910  
911  #include "linux/kernel.h"
912 +#include "linux/pagemap.h"
913  
914  static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
915                                    IMG_HANDLE hDevMemHeap,
916 @@ -595,13 +596,92 @@ static PVRSRV_ERROR UnwrapExtMemoryCallB
917         }
918  
919         if (hOSWrapMem) {
920 -               OSReleasePhysPageAddr(hOSWrapMem);
921 +               OSReleasePhysPageAddr(hOSWrapMem, IMG_TRUE);
922         }
923  
924         return eError;
925  }
926  
927  IMG_EXPORT
928 +    PVRSRV_ERROR IMG_CALLCONV PVRSRVIsWrappedExtMemoryKM(IMG_HANDLE hDevCookie,
929 +                                                          PVRSRV_PER_PROCESS_DATA
930 +                                                          *psPerProc,
931 +                                                          IMG_UINT32
932 +                                                          *pui32ByteSize,
933 +                                                          IMG_VOID
934 +                                                          **pvLinAddr)
935 +{
936 +       DEVICE_MEMORY_INFO *psDevMemoryInfo;
937 +       IMG_UINT32 ui32HostPageSize = HOST_PAGESIZE();
938 +       PVRSRV_DEVICE_NODE *psDeviceNode;
939 +       PVRSRV_ERROR eError;
940 +       IMG_SYS_PHYADDR sIntSysPAddr;
941 +       IMG_HANDLE hOSWrapMem = IMG_NULL;
942 +       IMG_HANDLE hDevMemHeap;
943 +       IMG_UINT32 ui32PageOffset = 0;
944 +
945 +       IMG_UINT32 ui32ReturnedByteSize = *pui32ByteSize;
946 +
947 +       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
948 +
949 +       psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
950 +       PVR_ASSERT(psDeviceNode != IMG_NULL);
951 +       psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
952 +
953 +       hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].hDevMemHeap;
954 +
955 +       if (pvLinAddr) {
956 +               ui32PageOffset = ((IMG_UINT32)*pvLinAddr) & ~PAGE_MASK;
957 +               *pvLinAddr = (IMG_VOID *)((IMG_UINT32)*pvLinAddr & PAGE_MASK);
958 +               ui32ReturnedByteSize += ui32PageOffset;
959 +
960 +               /* let's start by getting the address of the first page */
961 +               eError = OSAcquirePhysPageAddr(*pvLinAddr,
962 +                                                                               ui32HostPageSize,
963 +                                                                               &sIntSysPAddr,
964 +                                                                               &hOSWrapMem,
965 +                                                                               IMG_FALSE);
966 +               if (eError != PVRSRV_OK) {
967 +                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVIsWrappedExtMemoryKM: Failed to alloc memory for block"));
968 +                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
969 +                       goto ErrorExitPhase1;
970 +               }
971 +
972 +               OSReleasePhysPageAddr(hOSWrapMem, IMG_FALSE);
973 +               hOSWrapMem = IMG_NULL;
974 +
975 +               /* now check if this memory address is already wrapped */
976 +               if (BM_IsWrappedCheckSize(hDevMemHeap,
977 +                                                       ui32PageOffset,
978 +                                                       sIntSysPAddr,
979 +                                                       *pui32ByteSize)) {
980 +                       /* already wrapped */
981 +                       eError = PVRSRV_OK;
982 +               } else {
983 +                       /* not mapped in this heap */
984 +                       /* try the alternative heap */
985 +                       hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].hDevMemHeap;
986 +
987 +                       if (BM_IsWrappedCheckSize(hDevMemHeap,
988 +                                                               ui32PageOffset,
989 +                                                               sIntSysPAddr,
990 +                                                               *pui32ByteSize)) {
991 +                               /* already wrapped */
992 +                               eError = PVRSRV_OK;
993 +                       } else {
994 +                               eError = PVRSRV_ERROR_BAD_MAPPING;
995 +                       }
996 +               }
997 +       }
998 +
999 +ErrorExitPhase1:
1000 +
1001 +       *pui32ByteSize = ui32ReturnedByteSize;
1002 +
1003 +       return eError;
1004 +}
1005 +
1006 +IMG_EXPORT
1007      PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
1008                                                     PVRSRV_PER_PROCESS_DATA *
1009                                                     psPerProc,
1010 @@ -631,6 +711,13 @@ IMG_EXPORT
1011         IMG_SYS_PHYADDR *pPageList = psExtSysPAddr;
1012         IMG_UINT32 ui32PageCount;
1013  
1014 +       IMG_UINT32 ui32CalculatedPageOffset = ((IMG_UINT32)pvLinAddr) & ~PAGE_MASK;
1015 +       if (ui32CalculatedPageOffset != ui32PageOffset) {
1016 +               PVR_DPF((PVR_DBG_ERROR,
1017 +                       "PVRSRVWrapExtMemoryKM: offset from address not match offset param"));
1018 +               return PVRSRV_ERROR_BAD_MAPPING;
1019 +       }
1020 +
1021         psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
1022         PVR_ASSERT(psDeviceNode != IMG_NULL);
1023         psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
1024 @@ -657,7 +744,7 @@ IMG_EXPORT
1025                 /* let's start by getting the address of the first page */
1026                 eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
1027                                                ui32HostPageSize,
1028 -                                              psIntSysPAddr, &hOSWrapMem);
1029 +                                              psIntSysPAddr, &hOSWrapMem, IMG_TRUE);
1030                 if (eError != PVRSRV_OK) {
1031                         PVR_DPF((PVR_DBG_ERROR,
1032                                  "PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
1033 @@ -667,10 +754,10 @@ IMG_EXPORT
1034                 /* now check if this memory address is already wrapped */
1035                 if (BM_IsWrapped(hDevMemHeap, ui32PageOffset, psIntSysPAddr[0])) {
1036                         /* already wrapped */
1037 -                       OSReleasePhysPageAddr(hOSWrapMem);
1038 +                       OSReleasePhysPageAddr(hOSWrapMem, IMG_TRUE);
1039                         hOSWrapMem = IMG_NULL;
1040                 } else if (ui32PageCount > 1) {
1041 -                       OSReleasePhysPageAddr(hOSWrapMem);
1042 +                       OSReleasePhysPageAddr(hOSWrapMem, IMG_TRUE);
1043                         hOSWrapMem = IMG_NULL;
1044                         /* the memory is going to wrapped for the first time,
1045                          * so we need full page list */
1046 @@ -678,7 +765,8 @@ IMG_EXPORT
1047                                                        ui32PageCount *
1048                                                        ui32HostPageSize,
1049                                                        psIntSysPAddr,
1050 -                                                      &hOSWrapMem);
1051 +                                                      &hOSWrapMem,
1052 +                                                      IMG_TRUE);
1053                         if (eError != PVRSRV_OK) {
1054                                 PVR_DPF((PVR_DBG_ERROR,
1055                                          "PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
1056 @@ -783,7 +871,7 @@ ErrorExitPhase2:
1057         }
1058  
1059         if (hOSWrapMem)
1060 -               OSReleasePhysPageAddr(hOSWrapMem);
1061 +               OSReleasePhysPageAddr(hOSWrapMem, IMG_TRUE);
1062  ErrorExitPhase1:
1063         if (psIntSysPAddr) {
1064                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
1065 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/osfunc.c kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/osfunc.c
1066 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/osfunc.c       2011-09-04 11:36:23.000000000 +0200
1067 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/osfunc.c       2011-09-04 11:37:54.000000000 +0200
1068 @@ -1126,6 +1126,7 @@ PVRSRV_ERROR OSEnableTimer(IMG_HANDLE hT
1069  
1070         psTimerCBData->bActive = IMG_TRUE;
1071  
1072 +       psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
1073         add_timer(&psTimerCBData->sTimer);
1074  
1075         return PVRSRV_OK;
1076 @@ -1400,7 +1401,8 @@ exit_unlock:
1077         return psPage;
1078  }
1079  
1080 -PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
1081 +PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem,
1082 +                                                          IMG_BOOL bUseLock)
1083  {
1084         sWrapMemInfo *psInfo = (sWrapMemInfo *) hOSWrapMem;
1085         unsigned ui;
1086 @@ -1415,7 +1417,8 @@ PVRSRV_ERROR OSReleasePhysPageAddr(IMG_H
1087                 {
1088                         struct vm_area_struct *psVMArea;
1089  
1090 -                       down_read(&current->mm->mmap_sem);
1091 +                       if (bUseLock)
1092 +                               down_read(&current->mm->mmap_sem);
1093  
1094                         psVMArea = find_vma(current->mm, psInfo->ulStartAddr);
1095                         if (psVMArea == NULL) {
1096 @@ -1423,7 +1426,9 @@ PVRSRV_ERROR OSReleasePhysPageAddr(IMG_H
1097                                        ": OSCpuVToPageListRelease: Couldn't find memory region containing start address %lx",
1098                                        psInfo->ulStartAddr);
1099  
1100 -                               up_read(&current->mm->mmap_sem);
1101 +                               if (bUseLock)
1102 +                                       up_read(&current->mm->mmap_sem);
1103 +
1104                                 break;
1105                         }
1106  
1107 @@ -1459,7 +1464,9 @@ PVRSRV_ERROR OSReleasePhysPageAddr(IMG_H
1108                                        psVMArea->vm_flags);
1109                         }
1110  
1111 -                       up_read(&current->mm->mmap_sem);
1112 +                       if (bUseLock)
1113 +                               up_read(&current->mm->mmap_sem);
1114 +
1115                         break;
1116                 }
1117         default:
1118 @@ -1514,10 +1521,11 @@ PVRSRV_ERROR OSReleasePhysPageAddr(IMG_H
1119         return PVRSRV_OK;
1120  }
1121  
1122 -PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID * pvCPUVAddr,
1123 +PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
1124                                    IMG_UINT32 ui32Bytes,
1125 -                                  IMG_SYS_PHYADDR * psSysPAddr,
1126 -                                  IMG_HANDLE * phOSWrapMem)
1127 +                                  IMG_SYS_PHYADDR *psSysPAddr,
1128 +                                  IMG_HANDLE *phOSWrapMem,
1129 +                                  IMG_BOOL bUseLock)
1130  {
1131         unsigned long ulStartAddrOrig = (unsigned long)pvCPUVAddr;
1132         unsigned long ulAddrRangeOrig = (unsigned long)ui32Bytes;
1133 @@ -1538,7 +1546,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1134         psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
1135         if (psInfo == NULL) {
1136                 printk(KERN_WARNING
1137 -                      ": OSCpuVToPageList: Couldn't allocate information structure");
1138 +                      ": OSCpuVToPageList: Couldn't allocate information structure\n");
1139                 return PVRSRV_ERROR_OUT_OF_MEMORY;
1140         }
1141         memset(psInfo, 0, sizeof(*psInfo));
1142 @@ -1556,7 +1564,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1143                     GFP_KERNEL);
1144         if (psInfo->psPhysAddr == NULL) {
1145                 printk(KERN_WARNING
1146 -                      ": OSCpuVToPageList: Couldn't allocate page array");
1147 +                      ": OSCpuVToPageList: Couldn't allocate page array\n");
1148                 goto error_free;
1149         }
1150  
1151 @@ -1564,21 +1572,26 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1152             kmalloc(psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL);
1153         if (psInfo->ppsPages == NULL) {
1154                 printk(KERN_WARNING
1155 -                      ": OSCpuVToPageList: Couldn't allocate page array");
1156 +                      ": OSCpuVToPageList: Couldn't allocate page array\n");
1157                 goto error_free;
1158         }
1159  
1160 -       down_read(&current->mm->mmap_sem);
1161 +       if (bUseLock)
1162 +               down_read(&current->mm->mmap_sem);
1163 +
1164         iNumPagesMapped =
1165             get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages,
1166                            1, 0, psInfo->ppsPages, NULL);
1167 -       up_read(&current->mm->mmap_sem);
1168 +
1169 +       if (bUseLock)
1170 +               up_read(&current->mm->mmap_sem);
1171 +
1172  
1173         if (iNumPagesMapped >= 0) {
1174  
1175                 if (iNumPagesMapped != psInfo->iNumPages) {
1176                         printk(KERN_WARNING
1177 -                              ": OSCpuVToPageList: Couldn't map all the pages needed (wanted: %d, got %d)",
1178 +                              ": OSCpuVToPageList: Couldn't map all the pages needed (wanted: %d, got %d \n)",
1179                                psInfo->iNumPages, iNumPagesMapped);
1180  
1181                         for (ui = 0; ui < iNumPagesMapped; ui++) {
1182 @@ -1605,15 +1618,16 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1183         }
1184  
1185         printk(KERN_WARNING
1186 -              ": OSCpuVToPageList: get_user_pages failed (%d), trying something else",
1187 +              ": OSCpuVToPageList: get_user_pages failed (%d), trying something else \n",
1188                iNumPagesMapped);
1189  
1190 -       down_read(&current->mm->mmap_sem);
1191 +       if (bUseLock)
1192 +               down_read(&current->mm->mmap_sem);
1193  
1194         psVMArea = find_vma(current->mm, ulStartAddrOrig);
1195         if (psVMArea == NULL) {
1196                 printk(KERN_WARNING
1197 -                      ": OSCpuVToPageList: Couldn't find memory region containing start address %lx",
1198 +                      ": OSCpuVToPageList: Couldn't find memory region containing start address %lx \n",
1199                        ulStartAddrOrig);
1200  
1201                 goto error_release_mmap_sem;
1202 @@ -1624,14 +1638,14 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1203  
1204         if (ulStartAddrOrig < psVMArea->vm_start) {
1205                 printk(KERN_WARNING
1206 -                      ": OSCpuVToPageList: Start address %lx is outside of the region returned by find_vma",
1207 +                      ": OSCpuVToPageList: Start address %lx is outside of the region returned by find_vma\n",
1208                        ulStartAddrOrig);
1209                 goto error_release_mmap_sem;
1210         }
1211  
1212         if (ulBeyondEndAddrOrig > psVMArea->vm_end) {
1213                 printk(KERN_WARNING
1214 -                      ": OSCpuVToPageList: End address %lx is outside of the region returned by find_vma",
1215 +                      ": OSCpuVToPageList: End address %lx is outside of the region returned by find_vma\n",
1216                        ulBeyondEndAddrOrig);
1217                 goto error_release_mmap_sem;
1218         }
1219 @@ -1639,14 +1653,14 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1220         if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) !=
1221             (VM_IO | VM_RESERVED)) {
1222                 printk(KERN_WARNING
1223 -                      ": OSCpuVToPageList: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)",
1224 +                      ": OSCpuVToPageList: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)\n",
1225                        psVMArea->vm_flags);
1226                 goto error_release_mmap_sem;
1227         }
1228  
1229         if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE)) {
1230                 printk(KERN_WARNING
1231 -                      ": OSCpuVToPageList: No read/write access to memory region (VMA flags: 0x%lx)",
1232 +                      ": OSCpuVToPageList: No read/write access to memory region (VMA flags: 0x%lx)\n",
1233                        psVMArea->vm_flags);
1234                 goto error_release_mmap_sem;
1235         }
1236 @@ -1662,7 +1676,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1237                         unsigned uj;
1238  
1239                         printk(KERN_WARNING
1240 -                              ": OSCpuVToPageList: Couldn't lookup page structure for address 0x%lx, trying something else",
1241 +                              ": OSCpuVToPageList: Couldn't lookup page structure for address 0x%lx, trying something else\n",
1242                                ulAddr);
1243  
1244                         for (uj = 0; uj < ui; uj++) {
1245 @@ -1693,7 +1707,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1246  
1247                 if ((psVMArea->vm_flags & VM_PFNMAP) == 0) {
1248                         printk(KERN_WARNING
1249 -                              ": OSCpuVToPageList: Region isn't a raw PFN mapping.  Giving up.");
1250 +                              ": OSCpuVToPageList: Region isn't a raw PFN mapping.  Giving up.\n");
1251                         goto error_release_mmap_sem;
1252                 }
1253  
1254 @@ -1714,10 +1728,11 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1255                 psInfo->eType = WRAP_TYPE_FIND_VMA_PFN;
1256  
1257                 printk(KERN_WARNING
1258 -                      ": OSCpuVToPageList: Region can't be locked down");
1259 +                      ": OSCpuVToPageList: Region can't be locked down\n");
1260         }
1261  
1262 -       up_read(&current->mm->mmap_sem);
1263 +       if (bUseLock)
1264 +               up_read(&current->mm->mmap_sem);
1265  
1266  exit_check:
1267         CheckPagesContiguous(psInfo);
1268 @@ -1727,9 +1742,11 @@ exit_check:
1269         return PVRSRV_OK;
1270  
1271  error_release_mmap_sem:
1272 -       up_read(&current->mm->mmap_sem);
1273 +       if (bUseLock)
1274 +               up_read(&current->mm->mmap_sem);
1275 +
1276  error_free:
1277         psInfo->eType = WRAP_TYPE_CLEANUP;
1278 -       OSReleasePhysPageAddr((IMG_HANDLE) psInfo);
1279 +       OSReleasePhysPageAddr((IMG_HANDLE) psInfo, bUseLock);
1280         return PVRSRV_ERROR_GENERIC;
1281  }
1282 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/osfunc.h kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/osfunc.h
1283 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/osfunc.h       2011-09-04 11:36:23.000000000 +0200
1284 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/osfunc.h       2011-09-04 11:37:54.000000000 +0200
1285 @@ -291,8 +291,10 @@
1286         PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID * pvCPUVAddr,
1287                                            IMG_UINT32 ui32Bytes,
1288                                            IMG_SYS_PHYADDR * psSysPAddr,
1289 -                                          IMG_HANDLE * phOSWrapMem);
1290 -       PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem);
1291 +                                          IMG_HANDLE * phOSWrapMem,
1292 +                                          IMG_BOOL bUseLock);
1293 +       PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem,
1294 +                                          IMG_BOOL bUseLock);
1295  
1296  
1297  #endif
1298 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/power.c kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/power.c
1299 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/power.c        2011-09-04 11:36:23.000000000 +0200
1300 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/power.c        2011-09-04 11:37:54.000000000 +0200
1301 @@ -106,12 +106,16 @@ IMG_EXPORT IMG_VOID PVRSRVDvfsUnlock(IMG
1302         mutex_unlock(&hPowerAndFreqLock);
1303  }
1304  
1305 +static IMG_BOOL IsPowerLocked(void)
1306 +{
1307 +       return mutex_is_locked(&hPowerAndFreqLock) || gbDvfsActive;
1308 +}
1309 +
1310  IMG_EXPORT
1311      PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
1312                                  IMG_BOOL bSystemPowerEvent)
1313  {
1314 -       if ((ui32CallerID == TIMER_ID) &&
1315 -           (mutex_is_locked(&hPowerAndFreqLock) || gbDvfsActive))
1316 +       if ((ui32CallerID == TIMER_ID) && IsPowerLocked())
1317                 return PVRSRV_ERROR_RETRY;
1318         mutex_lock(&hPowerAndFreqLock);
1319         while (gbDvfsActive) {
1320 @@ -553,11 +557,8 @@ IMG_EXPORT IMG_BOOL PVRSRVIsDevicePowere
1321                 return IMG_FALSE;
1322         }
1323  
1324 -       if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID)
1325 -           || OSIsResourceLocked(&psSysData->sPowerStateChangeResource,
1326 -                                 ISR_ID)) {
1327 +       if (IsPowerLocked())
1328                 return IMG_FALSE;
1329 -       }
1330  
1331         psPowerDevice = psSysData->psPowerDeviceList;
1332         while (psPowerDevice) {
1333 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/pvr_bridge.h kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/pvr_bridge.h
1334 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/pvr_bridge.h   2011-09-04 11:36:23.000000000 +0200
1335 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/pvr_bridge.h   2011-09-04 11:37:54.000000000 +0200
1336 @@ -307,8 +307,9 @@
1337  
1338         typedef struct PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER_TAG {
1339                 IMG_UINT32 ui32BridgeFlags;
1340 +               IMG_HANDLE hDevCookie;
1341                 IMG_UINT32 ui32Type;
1342 -               IMG_UINT32 ui32Virt;
1343 +               IMG_VOID *pvVirt;
1344                 IMG_UINT32 ui32Length;
1345  
1346         } PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER;
1347 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/pvr_bridge_km.h kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/pvr_bridge_km.h
1348 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/pvr_bridge_km.h        2011-09-04 11:36:23.000000000 +0200
1349 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/pvr_bridge_km.h        2011-09-04 11:37:54.000000000 +0200
1350 @@ -186,6 +186,13 @@
1351  
1352          IMG_IMPORT
1353             PVRSRV_ERROR IMG_CALLCONV
1354 +           PVRSRVIsWrappedExtMemoryKM(IMG_HANDLE hDevCookie,
1355 +                                                 PVRSRV_PER_PROCESS_DATA *psPerProc,
1356 +                                                 IMG_UINT32 *pui32ByteSize,
1357 +                                                 IMG_VOID **pvLinAddr);
1358 +
1359 +        IMG_IMPORT
1360 +           PVRSRV_ERROR IMG_CALLCONV
1361             PVRSRVUnwrapExtMemoryKM(PVRSRV_KERNEL_MEM_INFO * psMemInfo);
1362  
1363          IMG_IMPORT
1364 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/sgxconfig.h kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/sgxconfig.h
1365 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/sgxconfig.h    2011-09-04 11:36:23.000000000 +0200
1366 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/sgxconfig.h    2011-09-04 11:37:54.000000000 +0200
1367 @@ -44,10 +44,10 @@
1368  #define SGX_GENERAL_HEAP_SIZE          (0x05000000-0x00401000)
1369  
1370  #define SGX_GENERAL_MAPPING_HEAP_BASE  0x05000000
1371 -#define SGX_GENERAL_MAPPING_HEAP_SIZE  (0x06C00000-0x05001000)
1372 +#define SGX_GENERAL_MAPPING_HEAP_SIZE  (0x06800000-0x05001000)
1373  
1374 -#define SGX_FB_MAPPING_HEAP_BASE       0x06C00000
1375 -#define SGX_FB_MAPPING_HEAP_SIZE       (0x07000000-0x06C01000)
1376 +#define SGX_FB_MAPPING_HEAP_BASE       0x06800000
1377 +#define SGX_FB_MAPPING_HEAP_SIZE       (0x07000000-0x06801000)
1378  
1379  #define SGX_TADATA_HEAP_BASE                           0x07000000
1380  #define SGX_TADATA_HEAP_SIZE                           (0x01000000-0x00001000)
1381 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/sgxinit.c kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/sgxinit.c
1382 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/sgxinit.c      2011-09-04 11:36:23.000000000 +0200
1383 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/sgxinit.c      2011-09-04 11:37:54.000000000 +0200
1384 @@ -225,8 +225,12 @@ static IMG_VOID SGXGetTimingInfo(PVRSRV_
1385                 }
1386                 if (psDevInfo->hTimer == IMG_NULL) {
1387  
1388 +                       /*
1389 +                        * the magic calculation below sets the hardware lock-up
1390 +                        * detection and recovery timer interval to ~150msecs
1391 +                        */
1392                         psDevInfo->hTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
1393 -                                                      1000 * 50 /
1394 +                                                      1000 * 150 /
1395                                                        psSGXTimingInfo->
1396                                                        ui32uKernelFreq);
1397                         if (psDevInfo->hTimer == IMG_NULL) {
1398 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/sysconfig.h kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/sysconfig.h
1399 --- kernel-2.6.28-20094102.6+0m5/drivers/gpu/pvr/sysconfig.h    2011-09-04 11:36:23.000000000 +0200
1400 +++ kernel-2.6.28-20094803.3+0m5/drivers/gpu/pvr/sysconfig.h    2011-09-04 11:37:54.000000000 +0200
1401 @@ -34,7 +34,7 @@
1402  #define SYS_SGX_CLOCK_SPEED    110666666
1403  #define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ                (100)
1404  #define SYS_SGX_PDS_TIMER_FREQ                 (1000)
1405 -#define SYS_SGX_ACTIVE_POWER_LATENCY_MS                (500)
1406 +#define SYS_SGX_ACTIVE_POWER_LATENCY_MS                (100)
1407  
1408  #define        SYS_OMAP3430_VDD2_OPP3_SGX_CLOCK_SPEED SYS_SGX_CLOCK_SPEED
1409  #define SYS_OMAP3430_VDD2_OPP2_SGX_CLOCK_SPEED (SYS_SGX_CLOCK_SPEED / 2)
1410 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/et8ek8.c kernel-2.6.28-20094803.3+0m5/drivers/media/video/et8ek8.c
1411 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/et8ek8.c   2011-09-04 11:36:23.000000000 +0200
1412 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/et8ek8.c   2011-09-04 11:37:54.000000000 +0200
1413 @@ -777,10 +777,11 @@ static int et8ek8_ioctl_s_power(struct v
1414                                 enum v4l2_power new_state)
1415  {
1416         struct et8ek8_sensor *sensor = s->priv;
1417 +       enum v4l2_power old_state = sensor->power;
1418         int rval = 0;
1419  
1420         /* If we are already in this mode, do nothing */
1421 -       if (sensor->power == new_state)
1422 +       if (old_state == new_state)
1423                 return 0;
1424  
1425         /* Disable power if so requested (it was enabled) */
1426 @@ -796,7 +797,7 @@ static int et8ek8_ioctl_s_power(struct v
1427         /* Either STANDBY or ON requested */
1428  
1429         /* Enable power and move to standby if it was off */
1430 -       if (sensor->power == V4L2_POWER_OFF) {
1431 +       if (old_state == V4L2_POWER_OFF) {
1432                 rval = et8ek8_power_on(s);
1433                 if (rval)
1434                         goto out;
1435 @@ -806,10 +807,11 @@ static int et8ek8_ioctl_s_power(struct v
1436  
1437         if (new_state == V4L2_POWER_ON) {
1438                 /* Standby -> streaming */
1439 +               sensor->power = V4L2_POWER_ON;
1440                 rval = et8ek8_configure(s);
1441                 if (rval) {
1442                         et8ek8_stream_off(s);
1443 -                       if (sensor->power == V4L2_POWER_OFF)
1444 +                       if (old_state == V4L2_POWER_OFF)
1445                                 et8ek8_power_off(s);
1446                         goto out;
1447                 }
1448 @@ -820,9 +822,7 @@ static int et8ek8_ioctl_s_power(struct v
1449         }
1450  
1451  out:
1452 -       if (rval == 0)
1453 -               sensor->power = new_state;
1454 -
1455 +       sensor->power = (rval == 0) ? new_state : old_state;
1456         return rval;
1457  }
1458  
1459 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isp_af.c kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isp_af.c
1460 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isp_af.c       2011-09-04 11:36:23.000000000 +0200
1461 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isp_af.c       2011-09-04 11:37:54.000000000 +0200
1462 @@ -194,6 +194,7 @@ void isp_af_config_registers(struct isp_
1463                        ~AF_PCR_MASK, pcr);
1464  
1465         isp_af->update = 0;
1466 +       isp_af->stat.config_counter++;
1467         ispstat_bufs_set_size(&isp_af->stat, isp_af->buf_size);
1468  
1469         spin_unlock_irqrestore(isp_af->lock, irqflags);
1470 @@ -299,8 +300,8 @@ void isp_af_try_enable(struct isp_af_dev
1471  }
1472  
1473  /* Function to perform hardware set up */
1474 -int omap34xx_isp_af_config(struct isp_af_device *isp_af,
1475 -                          struct af_configuration *afconfig)
1476 +int isp_af_config(struct isp_af_device *isp_af,
1477 +                 struct af_configuration *afconfig)
1478  {
1479         struct device *dev = to_device(isp_af);
1480         int result;
1481 @@ -337,14 +338,14 @@ int omap34xx_isp_af_config(struct isp_af
1482         /* Success */
1483         return 0;
1484  }
1485 -EXPORT_SYMBOL(omap34xx_isp_af_config);
1486 +EXPORT_SYMBOL(isp_af_config);
1487  
1488  /*
1489   * This API allows the user to update White Balance gains, as well as
1490   * exposure time and analog gain. It is also used to request frame
1491   * statistics.
1492   */
1493 -int omap34xx_isp_af_request_statistics(struct isp_af_device *isp_af,
1494 +int isp_af_request_statistics(struct isp_af_device *isp_af,
1495                               struct isp_af_data *afdata)
1496  {
1497         struct device *dev = to_device(isp_af);
1498 @@ -374,7 +375,7 @@ int omap34xx_isp_af_request_statistics(s
1499  
1500         return 0;
1501  }
1502 -EXPORT_SYMBOL(omap34xx_isp_af_request_statistics);
1503 +EXPORT_SYMBOL(isp_af_request_statistics);
1504  
1505  /* This function will handle the AF buffer. */
1506  int isp_af_buf_process(struct isp_af_device *isp_af)
1507 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isp_af.h kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isp_af.h
1508 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isp_af.h       2011-09-04 11:36:23.000000000 +0200
1509 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isp_af.h       2011-09-04 11:37:54.000000000 +0200
1510 @@ -131,9 +131,8 @@ void isp_af_suspend(struct isp_af_device
1511  void isp_af_resume(struct isp_af_device *);
1512  int isp_af_busy(struct isp_af_device *);
1513  void isp_af_config_registers(struct isp_af_device *isp_af);
1514 -int omap34xx_isp_af_request_statistics(struct isp_af_device *,
1515 -                                      struct isp_af_data *afdata);
1516 -int omap34xx_isp_af_config(struct isp_af_device *,
1517 -                          struct af_configuration *afconfig);
1518 +int isp_af_request_statistics(struct isp_af_device *,
1519 +                             struct isp_af_data *afdata);
1520 +int isp_af_config(struct isp_af_device *, struct af_configuration *afconfig);
1521  
1522  #endif /* OMAP_ISP_AF_H */
1523 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isp.c kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isp.c
1524 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isp.c  2011-09-04 11:36:23.000000000 +0200
1525 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isp.c  2011-09-04 11:37:54.000000000 +0200
1526 @@ -294,7 +294,7 @@ static void isp_enable_interrupts(struct
1527         u32 irq0enable;
1528  
1529         irq0enable = IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ
1530 -               | IRQ0ENABLE_CCDC_VD0_IRQ
1531 +               | IRQ0ENABLE_CCDC_VD0_IRQ | IRQ0ENABLE_HS_VS_IRQ
1532                 | IRQ0ENABLE_CSIA_IRQ
1533                 | IRQ0ENABLE_CSIB_IRQ | IRQ0ENABLE_HIST_DONE_IRQ
1534                 | IRQ0ENABLE_H3A_AWB_DONE_IRQ | IRQ0ENABLE_H3A_AF_DONE_IRQ
1535 @@ -711,7 +711,7 @@ int isp_configure_interface(struct devic
1536  }
1537  EXPORT_SYMBOL(isp_configure_interface);
1538  
1539 -void omap34xx_isp_hist_dma_done(struct device *dev)
1540 +void isp_hist_dma_done(struct device *dev)
1541  {
1542         struct isp_device *isp = dev_get_drvdata(dev);
1543         struct isp_irq *irqdis = &isp->irq;
1544 @@ -734,7 +734,7 @@ void omap34xx_isp_hist_dma_done(struct d
1545  static void isp_buf_process(struct device *dev, struct isp_bufs *bufs);
1546  
1547  /**
1548 - * omap34xx_isp_isr - Interrupt Service Routine for Camera ISP module.
1549 + * isp_isr - Interrupt Service Routine for Camera ISP module.
1550   * @irq: Not used currently.
1551   * @ispirq_disp: Pointer to the object that is passed while request_irq is
1552   *               called. This is the isp->irq object containing info on the
1553 @@ -745,7 +745,7 @@ static void isp_buf_process(struct devic
1554   * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
1555   * IRQ wasn't handled.
1556   **/
1557 -static irqreturn_t omap34xx_isp_isr(int irq, void *_pdev)
1558 +static irqreturn_t isp_isr(int irq, void *_pdev)
1559  {
1560         struct device *dev = &((struct platform_device *)_pdev)->dev;
1561         struct isp_device *isp = dev_get_drvdata(dev);
1562 @@ -755,7 +755,7 @@ static irqreturn_t omap34xx_isp_isr(int
1563         unsigned long flags;
1564         u32 irqstatus = 0;
1565         u32 sbl_pcr;
1566 -       int wait_hs_vs = 0;
1567 +       int wait_hs_vs;
1568         int ret;
1569  
1570         if (isp->running == ISP_STOPPED)
1571 @@ -773,6 +773,8 @@ static irqreturn_t omap34xx_isp_isr(int
1572         wait_hs_vs = bufs->wait_hs_vs;
1573         if (irqstatus & CCDC_VD0 && bufs->wait_hs_vs)
1574                 bufs->wait_hs_vs--;
1575 +       if (irqstatus & HS_VS && bufs->wait_stats && !bufs->wait_hs_vs)
1576 +               bufs->wait_stats = 0;
1577         /*
1578          * We need to wait for the first HS_VS interrupt from CCDC.
1579          * Otherwise our frame (and everything else) might be bad.
1580 @@ -783,12 +785,18 @@ static irqreturn_t omap34xx_isp_isr(int
1581                  * Enable preview for the first time. We just have
1582                  * missed the start-of-frame so we can do it now.
1583                  */
1584 -               if (irqstatus & CCDC_VD0 &&
1585 -                   !RAW_CAPTURE(isp) &&
1586 -                   !(isp_reg_readl(dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR) &
1587 -                     (ISPPRV_PCR_BUSY | ISPPRV_PCR_EN))) {
1588 -                       isppreview_config_shadow_registers(&isp->isp_prev);
1589 -                       isppreview_enable(&isp->isp_prev, 1);
1590 +               if (irqstatus & CCDC_VD0) {
1591 +                       isp_af_try_enable(&isp->isp_af);
1592 +                       isph3a_aewb_try_enable(&isp->isp_h3a);
1593 +                       isp_hist_try_enable(&isp->isp_hist);
1594 +                       if (!RAW_CAPTURE(isp) &&
1595 +                           !(isp_reg_readl(dev, OMAP3_ISP_IOMEM_PREV,
1596 +                                           ISPPRV_PCR) &
1597 +                             (ISPPRV_PCR_BUSY | ISPPRV_PCR_EN))) {
1598 +                               isppreview_config_shadow_registers(
1599 +                                                               &isp->isp_prev);
1600 +                               isppreview_enable(&isp->isp_prev, 1);
1601 +                       }
1602                 }
1603         default:
1604                 /*
1605 @@ -811,6 +819,13 @@ static irqreturn_t omap34xx_isp_isr(int
1606  
1607                 goto out_ignore_buff;
1608         case 0:
1609 +               if (bufs->wait_stats) {
1610 +                       if (irqstatus & (H3A_AWB_DONE | H3A_AF_DONE))
1611 +                               irqstatus &= ~(H3A_AWB_DONE | H3A_AF_DONE);
1612 +                       if (irqstatus & HIST_DONE)
1613 +                               isp_hist_mark_invalid_buf(&isp->isp_hist);
1614 +               }
1615 +
1616                 break;
1617         }
1618  
1619 @@ -965,7 +980,6 @@ static irqreturn_t omap34xx_isp_isr(int
1620                                      "busy.\n");
1621                         /* current and next buffer might have invalid data */
1622                         isp_hist_mark_invalid_buf(&isp->isp_hist);
1623 -                       irqstatus &= ~HIST_DONE;
1624                         ret = HIST_NO_BUF;
1625                 }
1626                 if (ret != HIST_BUF_WAITING_DMA)
1627 @@ -974,7 +988,7 @@ static irqreturn_t omap34xx_isp_isr(int
1628                         irqstatus &= ~HIST_DONE;
1629         }
1630  
1631 -       if (irqdis->isp_callbk[CBK_CATCHALL]) {
1632 +       if (irqdis->isp_callbk[CBK_CATCHALL] && irqstatus) {
1633                 irqdis->isp_callbk[CBK_CATCHALL](
1634                         irqstatus,
1635                         irqdis->isp_callbk_arg1[CBK_CATCHALL],
1636 @@ -1123,6 +1137,11 @@ static int __isp_disable_modules(struct
1637                 isp_af_enable(&isp->isp_af, 0);
1638                 isph3a_aewb_enable(&isp->isp_h3a, 0);
1639                 isp_hist_enable(&isp->isp_hist, 0);
1640 +
1641 +               /* FIXME: find me a better interface */
1642 +               isp->isp_af.config.af_config = 0;
1643 +               isp->isp_h3a.aewb_config_local.aewb_enable = 0;
1644 +               isp->isp_hist.config.enable = 0;
1645         }
1646         ispresizer_enable(&isp->isp_res, 0);
1647         isppreview_enable(&isp->isp_prev, 0);
1648 @@ -1424,6 +1443,7 @@ static void isp_buf_init(struct device *
1649         bufs->queue = 0;
1650         bufs->done = 0;
1651         bufs->wait_hs_vs = isp->config->wait_hs_vs;
1652 +       bufs->wait_stats = bufs->wait_hs_vs;
1653         for (sg = 0; sg < NUM_BUFS; sg++) {
1654                 if (bufs->buf[sg].vb) {
1655                         bufs->buf[sg].vb->state = VIDEOBUF_ERROR;
1656 @@ -1528,11 +1548,9 @@ int isp_buf_queue(struct device *dev, st
1657                  * receiving a frame.
1658                  */
1659                 bufs->wait_hs_vs++;
1660 +               bufs->wait_stats = 1;
1661                 isp_enable_interrupts(dev, RAW_CAPTURE(isp));
1662                 isp_set_buf(dev, buf);
1663 -               isp_af_try_enable(&isp->isp_af);
1664 -               isph3a_aewb_try_enable(&isp->isp_h3a);
1665 -               isp_hist_try_enable(&isp->isp_hist);
1666                 ispccdc_enable(&isp->isp_ccdc, 1);
1667         }
1668  
1669 @@ -1814,48 +1832,48 @@ int isp_handle_private(struct device *de
1670  
1671         switch (cmd) {
1672         case VIDIOC_PRIVATE_ISP_CCDC_CFG:
1673 -               rval = omap34xx_isp_ccdc_config(&isp->isp_ccdc, arg);
1674 +               rval = ispccdc_config(&isp->isp_ccdc, arg);
1675                 break;
1676         case VIDIOC_PRIVATE_ISP_PRV_CFG:
1677 -               rval = omap34xx_isp_preview_config(&isp->isp_prev, arg);
1678 +               rval = isppreview_config(&isp->isp_prev, arg);
1679                 break;
1680         case VIDIOC_PRIVATE_ISP_AEWB_CFG: {
1681                 struct isph3a_aewb_config *params;
1682                 params = (struct isph3a_aewb_config *)arg;
1683 -               rval = omap34xx_isph3a_aewb_config(&isp->isp_h3a, params);
1684 +               rval = isph3a_aewb_config(&isp->isp_h3a, params);
1685         }
1686                 break;
1687         case VIDIOC_PRIVATE_ISP_AEWB_REQ: {
1688                 struct isph3a_aewb_data *data;
1689                 data = (struct isph3a_aewb_data *)arg;
1690 -               rval = omap34xx_isph3a_aewb_request_statistics(&isp->isp_h3a,
1691 +               rval = isph3a_aewb_request_statistics(&isp->isp_h3a,
1692                                                                data);
1693         }
1694                 break;
1695         case VIDIOC_PRIVATE_ISP_HIST_CFG: {
1696                 struct isp_hist_config *params;
1697                 params = (struct isp_hist_config *)arg;
1698 -               rval = omap34xx_isp_hist_config(&isp->isp_hist, params);
1699 +               rval = isp_hist_config(&isp->isp_hist, params);
1700         }
1701                 break;
1702         case VIDIOC_PRIVATE_ISP_HIST_REQ: {
1703                 struct isp_hist_data *data;
1704                 data = (struct isp_hist_data *)arg;
1705 -               rval = omap34xx_isp_hist_request_statistics(&isp->isp_hist,
1706 +               rval = isp_hist_request_statistics(&isp->isp_hist,
1707                                                             data);
1708         }
1709                 break;
1710         case VIDIOC_PRIVATE_ISP_AF_CFG: {
1711                 struct af_configuration *params;
1712                 params = (struct af_configuration *)arg;
1713 -               rval = omap34xx_isp_af_config(&isp->isp_af, params);
1714 +               rval = isp_af_config(&isp->isp_af, params);
1715  
1716         }
1717                 break;
1718         case VIDIOC_PRIVATE_ISP_AF_REQ: {
1719                 struct isp_af_data *data;
1720                 data = (struct isp_af_data *)arg;
1721 -               rval = omap34xx_isp_af_request_statistics(&isp->isp_af, data);
1722 +               rval = isp_af_request_statistics(&isp->isp_af, data);
1723         }
1724                 break;
1725         default:
1726 @@ -2029,7 +2047,7 @@ static void isp_save_ctx(struct device *
1727         ispccdc_save_context(dev);
1728         if (isp->iommu)
1729                 iommu_save_ctx(isp->iommu);
1730 -       isphist_save_context(dev);
1731 +       isp_hist_save_context(dev);
1732         isph3a_save_context(dev);
1733         isppreview_save_context(dev);
1734         ispresizer_save_context(dev);
1735 @@ -2049,7 +2067,7 @@ static void isp_restore_ctx(struct devic
1736         ispccdc_restore_context(dev);
1737         if (isp->iommu)
1738                 iommu_restore_ctx(isp->iommu);
1739 -       isphist_restore_context(dev);
1740 +       isp_hist_restore_context(dev);
1741         isph3a_restore_context(dev);
1742         isppreview_restore_context(dev);
1743         ispresizer_restore_context(dev);
1744 @@ -2389,7 +2407,7 @@ static int isp_probe(struct platform_dev
1745                 goto out_clk_get_l3_ick;
1746         }
1747  
1748 -       if (request_irq(isp->irq_num, omap34xx_isp_isr, IRQF_SHARED,
1749 +       if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED,
1750                         "Omap 3 Camera ISP", pdev)) {
1751                 dev_err(isp->dev, "could not install isr\n");
1752                 ret_err = -EINVAL;
1753 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/ispccdc.c kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/ispccdc.c
1754 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/ispccdc.c      2011-09-04 11:36:23.000000000 +0200
1755 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/ispccdc.c      2011-09-04 11:37:54.000000000 +0200
1756 @@ -29,6 +29,7 @@
1757  #include "ispccdc.h"
1758  
1759  #define LSC_TABLE_INIT_SIZE    50052
1760 +#define PTR_FREE               ((u32)(-ENOMEM))
1761  
1762  /* Structure for saving/restoring CCDC module registers*/
1763  static struct isp_reg ispccdc_reg_list[] = {
1764 @@ -76,1008 +77,905 @@ static struct isp_reg ispccdc_reg_list[]
1765  };
1766  
1767  /**
1768 - * omap34xx_isp_ccdc_config - Sets CCDC configuration from userspace
1769 - * @userspace_add: Structure containing CCDC configuration sent from userspace.
1770 + * ispccdc_print_status - Prints the values of the CCDC Module registers
1771   *
1772 - * Returns 0 if successful, -EINVAL if the pointer to the configuration
1773 - * structure is null, or the copy_from_user function fails to copy user space
1774 - * memory to kernel space memory.
1775 + * Also prints other debug information stored in the CCDC module.
1776   **/
1777 -int omap34xx_isp_ccdc_config(struct isp_ccdc_device *isp_ccdc,
1778 -                            void *userspace_add)
1779 +static void ispccdc_print_status(struct isp_ccdc_device *isp_ccdc,
1780 +                                struct isp_pipeline *pipe)
1781  {
1782 -       struct isp_device *isp = to_isp_device(isp_ccdc);
1783 -       struct ispccdc_bclamp bclamp_t;
1784 -       struct ispccdc_blcomp blcomp_t;
1785 -       struct ispccdc_fpc fpc_t;
1786 -       struct ispccdc_culling cull_t;
1787 -       struct ispccdc_update_config *ccdc_struct;
1788 -
1789 -       if (userspace_add == NULL)
1790 -               return -EINVAL;
1791 -
1792 -       ccdc_struct = userspace_add;
1793 -
1794 -       if (ISP_ABS_CCDC_ALAW & ccdc_struct->flag) {
1795 -               if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
1796 -                       ispccdc_config_alaw(isp_ccdc, ccdc_struct->alawip);
1797 -               ispccdc_enable_alaw(isp_ccdc, 1);
1798 -       } else if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
1799 -               ispccdc_enable_alaw(isp_ccdc, 0);
1800 -
1801 -       if (ISP_ABS_CCDC_LPF & ccdc_struct->flag)
1802 -               ispccdc_enable_lpf(isp_ccdc, 1);
1803 -       else
1804 -               ispccdc_enable_lpf(isp_ccdc, 0);
1805 -
1806 -       if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->flag) {
1807 -               if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
1808 -                       if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
1809 -                                          ccdc_struct->bclamp,
1810 -                                          sizeof(struct ispccdc_bclamp)))
1811 -                               goto copy_from_user_err;
1812 -
1813 -                       ispccdc_enable_black_clamp(isp_ccdc, 1);
1814 -                       ispccdc_config_black_clamp(isp_ccdc, bclamp_t);
1815 -               } else
1816 -                       ispccdc_enable_black_clamp(isp_ccdc, 1);
1817 -       } else {
1818 -               if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
1819 -                       if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
1820 -                                          ccdc_struct->bclamp,
1821 -                                          sizeof(struct ispccdc_bclamp)))
1822 -                               goto copy_from_user_err;
1823 -
1824 -                       ispccdc_enable_black_clamp(isp_ccdc, 0);
1825 -                       ispccdc_config_black_clamp(isp_ccdc, bclamp_t);
1826 -               }
1827 -       }
1828 -
1829 -       if (ISP_ABS_CCDC_BCOMP & ccdc_struct->update) {
1830 -               if (copy_from_user(&blcomp_t, (struct ispccdc_blcomp *)
1831 -                                  ccdc_struct->blcomp,
1832 -                                  sizeof(blcomp_t)))
1833 -                       goto copy_from_user_err;
1834 -
1835 -               ispccdc_config_black_comp(isp_ccdc, blcomp_t);
1836 -       }
1837 -
1838 -       if (ISP_ABS_CCDC_FPC & ccdc_struct->flag) {
1839 -               if (ISP_ABS_CCDC_FPC & ccdc_struct->update) {
1840 -                       if (copy_from_user(&fpc_t, (struct ispccdc_fpc *)
1841 -                                          ccdc_struct->fpc,
1842 -                                          sizeof(fpc_t)))
1843 -                               goto copy_from_user_err;
1844 -                       isp_ccdc->fpc_table_add = kmalloc(64 + fpc_t.fpnum * 4,
1845 -                                               GFP_KERNEL | GFP_DMA);
1846 -                       if (!isp_ccdc->fpc_table_add) {
1847 -                               dev_err(to_device(isp_ccdc),
1848 -                                       "ccdc: Cannot allocate memory for"
1849 -                                       " FPC table");
1850 -                               return -ENOMEM;
1851 -                       }
1852 -                       while (((unsigned long)isp_ccdc->fpc_table_add
1853 -                               & 0xFFFFFFC0)
1854 -                              != (unsigned long)isp_ccdc->fpc_table_add)
1855 -                               isp_ccdc->fpc_table_add++;
1856 -
1857 -                       isp_ccdc->fpc_table_add_m = iommu_kmap(
1858 -                               isp->iommu,
1859 -                               0,
1860 -                               virt_to_phys(isp_ccdc->fpc_table_add),
1861 -                               fpc_t.fpnum * 4,
1862 -                               IOMMU_FLAG);
1863 -                       /* FIXME: Correct unwinding */
1864 -                       BUG_ON(IS_ERR_VALUE(isp_ccdc->fpc_table_add_m));
1865 -
1866 -                       if (copy_from_user(isp_ccdc->fpc_table_add,
1867 -                                          (u32 *)fpc_t.fpcaddr,
1868 -                                          fpc_t.fpnum * 4))
1869 -                               goto copy_from_user_err;
1870 -
1871 -                       fpc_t.fpcaddr = isp_ccdc->fpc_table_add_m;
1872 -                       ispccdc_config_fpc(isp_ccdc, fpc_t);
1873 -               }
1874 -               ispccdc_enable_fpc(isp_ccdc, 1);
1875 -       } else if (ISP_ABS_CCDC_FPC & ccdc_struct->update)
1876 -               ispccdc_enable_fpc(isp_ccdc, 0);
1877 +       if (!is_ispccdc_debug_enabled())
1878 +               return;
1879  
1880 -       if (ISP_ABS_CCDC_CULL & ccdc_struct->update) {
1881 -               if (copy_from_user(&cull_t, (struct ispccdc_culling *)
1882 -                                  ccdc_struct->cull,
1883 -                                  sizeof(cull_t)))
1884 -                       goto copy_from_user_err;
1885 -               ispccdc_config_culling(isp_ccdc, cull_t);
1886 +       DPRINTK_ISPCCDC("Module in use =%d\n", isp_ccdc->ccdc_inuse);
1887 +       DPRINTK_ISPCCDC("Accepted CCDC Input (width = %d,Height = %d)\n",
1888 +                       isp_ccdc->ccdcin_w,
1889 +                       isp_ccdc->ccdcin_h);
1890 +       DPRINTK_ISPCCDC("Accepted CCDC Output (width = %d,Height = %d)\n",
1891 +                       isp_ccdc->ccdcout_w,
1892 +                       isp_ccdc->ccdcout_h);
1893 +       DPRINTK_ISPCCDC("###CCDC PCR=0x%x\n",
1894 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
1895 +                                     ISPCCDC_PCR));
1896 +       DPRINTK_ISPCCDC("ISP_CTRL =0x%x\n",
1897 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
1898 +                                     ISP_CTRL));
1899 +       switch (pipe->ccdc_in) {
1900 +       case CCDC_RAW:
1901 +               DPRINTK_ISPCCDC("ccdc input format is CCDC_RAW\n");
1902 +               break;
1903 +       case CCDC_YUV_SYNC:
1904 +               DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_SYNC\n");
1905 +               break;
1906 +       case CCDC_YUV_BT:
1907 +               DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_BT\n");
1908 +               break;
1909 +       default:
1910 +               break;
1911         }
1912  
1913 -       if (is_isplsc_activated()) {
1914 -               if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->flag) {
1915 -                       if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
1916 -                               if (copy_from_user(
1917 -                                           &isp_ccdc->lsc_config,
1918 -                                           (struct ispccdc_lsc_config *)
1919 -                                           ccdc_struct->lsc_cfg,
1920 -                                           sizeof(struct ispccdc_lsc_config)))
1921 -                                       goto copy_from_user_err;
1922 -                               ispccdc_config_lsc(isp_ccdc,
1923 -                                                  &isp_ccdc->lsc_config);
1924 -                       }
1925 -                       ispccdc_enable_lsc(isp_ccdc, 1);
1926 -               } else if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
1927 -                       ispccdc_enable_lsc(isp_ccdc, 0);
1928 -               }
1929 -               if (ISP_ABS_TBL_LSC & ccdc_struct->update) {
1930 -                       if (copy_from_user(isp_ccdc->lsc_gain_table,
1931 -                                          ccdc_struct->lsc,
1932 -                                          isp_ccdc->lsc_config.size))
1933 -                               goto copy_from_user_err;
1934 -                       ispccdc_load_lsc(isp_ccdc, isp_ccdc->lsc_gain_table,
1935 -                                        isp_ccdc->lsc_config.size);
1936 -               }
1937 +       switch (pipe->ccdc_out) {
1938 +       case CCDC_OTHERS_VP:
1939 +               DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_VP\n");
1940 +               break;
1941 +       case CCDC_OTHERS_MEM:
1942 +               DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_MEM\n");
1943 +               break;
1944 +       case CCDC_YUV_RSZ:
1945 +               DPRINTK_ISPCCDC("ccdc output format is CCDC_YUV_RSZ\n");
1946 +               break;
1947 +       default:
1948 +               break;
1949         }
1950  
1951 -       if (ISP_ABS_CCDC_COLPTN & ccdc_struct->update)
1952 -               ispccdc_config_imgattr(isp_ccdc, ccdc_struct->colptn);
1953 -
1954 -       return 0;
1955 -
1956 -copy_from_user_err:
1957 -       dev_err(isp->dev, "ccdc: Config: copy from user error");
1958 -       return -EINVAL ;
1959 -}
1960 -
1961 -/**
1962 - * Set the value to be used for CCDC_CFG.WENLOG.
1963 - *  w - Value of wenlog.
1964 - */
1965 -void ispccdc_set_wenlog(struct isp_ccdc_device *isp_ccdc, u32 wenlog)
1966 -{
1967 -       isp_ccdc->wenlog = wenlog;
1968 +       DPRINTK_ISPCCDC("###ISP_CTRL in ccdc =0x%x\n",
1969 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
1970 +                                     ISP_CTRL));
1971 +       DPRINTK_ISPCCDC("###ISP_IRQ0ENABLE in ccdc =0x%x\n",
1972 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
1973 +                                     ISP_IRQ0ENABLE));
1974 +       DPRINTK_ISPCCDC("###ISP_IRQ0STATUS in ccdc =0x%x\n",
1975 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
1976 +                                     ISP_IRQ0STATUS));
1977 +       DPRINTK_ISPCCDC("###CCDC SYN_MODE=0x%x\n",
1978 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
1979 +                                     ISPCCDC_SYN_MODE));
1980 +       DPRINTK_ISPCCDC("###CCDC HORZ_INFO=0x%x\n",
1981 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
1982 +                                     ISPCCDC_HORZ_INFO));
1983 +       DPRINTK_ISPCCDC("###CCDC VERT_START=0x%x\n",
1984 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
1985 +                                     ISPCCDC_VERT_START));
1986 +       DPRINTK_ISPCCDC("###CCDC VERT_LINES=0x%x\n",
1987 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
1988 +                                     ISPCCDC_VERT_LINES));
1989 +       DPRINTK_ISPCCDC("###CCDC CULLING=0x%x\n",
1990 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
1991 +                                     ISPCCDC_CULLING));
1992 +       DPRINTK_ISPCCDC("###CCDC HSIZE_OFF=0x%x\n",
1993 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
1994 +                                     ISPCCDC_HSIZE_OFF));
1995 +       DPRINTK_ISPCCDC("###CCDC SDOFST=0x%x\n",
1996 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
1997 +                                     ISPCCDC_SDOFST));
1998 +       DPRINTK_ISPCCDC("###CCDC SDR_ADDR=0x%x\n",
1999 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2000 +                                     ISPCCDC_SDR_ADDR));
2001 +       DPRINTK_ISPCCDC("###CCDC CLAMP=0x%x\n",
2002 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2003 +                                     ISPCCDC_CLAMP));
2004 +       DPRINTK_ISPCCDC("###CCDC COLPTN=0x%x\n",
2005 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2006 +                                     ISPCCDC_COLPTN));
2007 +       DPRINTK_ISPCCDC("###CCDC CFG=0x%x\n",
2008 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2009 +                                     ISPCCDC_CFG));
2010 +       DPRINTK_ISPCCDC("###CCDC VP_OUT=0x%x\n",
2011 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2012 +                                     ISPCCDC_VP_OUT));
2013 +       DPRINTK_ISPCCDC("###CCDC_SDR_ADDR= 0x%x\n",
2014 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2015 +                                     ISPCCDC_SDR_ADDR));
2016 +       DPRINTK_ISPCCDC("###CCDC FMTCFG=0x%x\n",
2017 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2018 +                                     ISPCCDC_FMTCFG));
2019 +       DPRINTK_ISPCCDC("###CCDC FMT_HORZ=0x%x\n",
2020 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2021 +                                     ISPCCDC_FMT_HORZ));
2022 +       DPRINTK_ISPCCDC("###CCDC FMT_VERT=0x%x\n",
2023 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2024 +                                     ISPCCDC_FMT_VERT));
2025 +       DPRINTK_ISPCCDC("###CCDC LSC_CONFIG=0x%x\n",
2026 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2027 +                                     ISPCCDC_LSC_CONFIG));
2028 +       DPRINTK_ISPCCDC("###CCDC LSC_INIT=0x%x\n",
2029 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2030 +                                     ISPCCDC_LSC_INITIAL));
2031 +       DPRINTK_ISPCCDC("###CCDC LSC_TABLE BASE=0x%x\n",
2032 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2033 +                                     ISPCCDC_LSC_TABLE_BASE));
2034 +       DPRINTK_ISPCCDC("###CCDC LSC TABLE OFFSET=0x%x\n",
2035 +                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2036 +                                     ISPCCDC_LSC_TABLE_OFFSET));
2037  }
2038  
2039  /**
2040 - * ispccdc_request - Reserves the CCDC module.
2041 - *
2042 - * Reserves the CCDC module and assures that is used only once at a time.
2043 + * ispccdc_config_black_clamp - Configures the clamp parameters in CCDC.
2044 + * @bclamp: Structure containing the optical black average gain, optical black
2045 + *          sample length, sample lines, and the start pixel position of the
2046 + *          samples w.r.t the HS pulse.
2047 + * Configures the clamp parameters in CCDC. Either if its being used the
2048 + * optical black clamp, or the digital clamp. If its a digital clamp, then
2049 + * assures to put a valid DC substraction level.
2050   *
2051 - * Returns 0 if successful, or -EBUSY if CCDC module is busy.
2052 + * Returns always 0 when completed.
2053   **/
2054 -int ispccdc_request(struct isp_ccdc_device *isp_ccdc)
2055 +static int ispccdc_config_black_clamp(struct isp_ccdc_device *isp_ccdc,
2056 +                                     struct ispccdc_bclamp bclamp)
2057  {
2058         struct device *dev = to_device(isp_ccdc);
2059 +       u32 bclamp_val = 0;
2060  
2061 -       mutex_lock(&isp_ccdc->mutexlock);
2062 -       if (isp_ccdc->ccdc_inuse) {
2063 -               mutex_unlock(&isp_ccdc->mutexlock);
2064 -               DPRINTK_ISPCCDC("ISP_ERR : CCDC Module Busy\n");
2065 -               return -EBUSY;
2066 +       if (isp_ccdc->obclamp_en) {
2067 +               bclamp_val |= bclamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
2068 +               bclamp_val |= bclamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
2069 +               bclamp_val |= bclamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
2070 +               bclamp_val |= bclamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
2071 +               isp_reg_writel(dev, bclamp_val,
2072 +                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP);
2073 +       } else {
2074 +               if (omap_rev() < OMAP3430_REV_ES2_0)
2075 +                       if (isp_ccdc->syncif_ipmod == YUV16 ||
2076 +                           isp_ccdc->syncif_ipmod == YUV8 ||
2077 +                           isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2078 +                                         ISPCCDC_REC656IF) &
2079 +                           ISPCCDC_REC656IF_R656ON)
2080 +                               bclamp.dcsubval = 0;
2081 +               isp_reg_writel(dev, bclamp.dcsubval,
2082 +                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB);
2083         }
2084 -
2085 -       isp_ccdc->ccdc_inuse = 1;
2086 -       mutex_unlock(&isp_ccdc->mutexlock);
2087 -       isp_reg_or(dev, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
2088 -                  ISPCTRL_CCDC_RAM_EN | ISPCTRL_CCDC_CLK_EN |
2089 -                  ISPCTRL_SBL_WR1_RAM_EN);
2090 -       isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
2091 -                  ISPCCDC_CFG_VDLC);
2092         return 0;
2093  }
2094  
2095  /**
2096 - * ispccdc_free - Frees the CCDC module.
2097 - *
2098 - * Frees the CCDC module so it can be used by another process.
2099 + * ispccdc_enable_black_clamp - Enables/Disables the optical black clamp.
2100 + * @enable: 0 Disables optical black clamp, 1 Enables optical black clamp.
2101   *
2102 - * Returns 0 if successful, or -EINVAL if module has been already freed.
2103 + * Enables or disables the optical black clamp. When disabled, the digital
2104 + * clamp operates.
2105   **/
2106 -int ispccdc_free(struct isp_ccdc_device *isp_ccdc)
2107 +static void ispccdc_enable_black_clamp(struct isp_ccdc_device *isp_ccdc,
2108 +                                      u8 enable)
2109  {
2110 -       mutex_lock(&isp_ccdc->mutexlock);
2111 -       if (!isp_ccdc->ccdc_inuse) {
2112 -               mutex_unlock(&isp_ccdc->mutexlock);
2113 -               DPRINTK_ISPCCDC("ISP_ERR: CCDC Module already freed\n");
2114 -               return -EINVAL;
2115 -       }
2116 +       struct device *dev = to_device(isp_ccdc);
2117  
2118 -       isp_ccdc->ccdc_inuse = 0;
2119 -       mutex_unlock(&isp_ccdc->mutexlock);
2120 -       isp_reg_and(to_device(isp_ccdc), OMAP3_ISP_IOMEM_MAIN,
2121 -                   ISP_CTRL, ~(ISPCTRL_CCDC_CLK_EN |
2122 -                               ISPCTRL_CCDC_RAM_EN |
2123 -                               ISPCTRL_SBL_WR1_RAM_EN));
2124 -       return 0;
2125 +       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
2126 +                      ~ISPCCDC_CLAMP_CLAMPEN,
2127 +                      enable ? ISPCCDC_CLAMP_CLAMPEN : 0);
2128 +       isp_ccdc->obclamp_en = enable;
2129  }
2130  
2131  /**
2132 - * ispccdc_free_lsc - Frees Lens Shading Compensation table
2133 + * ispccdc_config_fpc - Configures the Faulty Pixel Correction parameters.
2134 + * @fpc: Structure containing the number of faulty pixels corrected in the
2135 + *       frame, address of the FPC table.
2136   *
2137 - * Always returns 0.
2138 + * Returns 0 if successful, or -EINVAL if FPC Address is not on the 64 byte
2139 + * boundary.
2140   **/
2141 -static int ispccdc_free_lsc(struct isp_ccdc_device *isp_ccdc)
2142 +static int ispccdc_config_fpc(struct isp_ccdc_device *isp_ccdc,
2143 +                             struct ispccdc_fpc fpc)
2144  {
2145 -       struct isp_device *isp = to_isp_device(isp_ccdc);
2146 +       struct device *dev = to_device(isp_ccdc);
2147 +       u32 fpc_val = 0;
2148  
2149 -       if (!isp_ccdc->lsc_ispmmu_addr)
2150 -               return 0;
2151 +       fpc_val = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
2152  
2153 -       ispccdc_enable_lsc(isp_ccdc, 0);
2154 -       isp_ccdc->lsc_initialized = 0;
2155 -       isp_reg_writel(to_device(isp_ccdc), 0, OMAP3_ISP_IOMEM_CCDC,
2156 -                      ISPCCDC_LSC_TABLE_BASE);
2157 -       iommu_vfree(isp->iommu, isp_ccdc->lsc_ispmmu_addr);
2158 -       isp_ccdc->lsc_gain_table = NULL;
2159 +       if ((fpc.fpcaddr & 0xFFFFFFC0) == fpc.fpcaddr) {
2160 +               isp_reg_writel(dev, fpc_val & (~ISPCCDC_FPC_FPCEN),
2161 +                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
2162 +               isp_reg_writel(dev, fpc.fpcaddr,
2163 +                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR);
2164 +       } else {
2165 +               DPRINTK_ISPCCDC("FPC Address should be on 64byte boundary\n");
2166 +               return -EINVAL;
2167 +       }
2168 +       isp_reg_writel(dev, fpc_val | (fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
2169 +                      OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
2170         return 0;
2171  }
2172  
2173  /**
2174 - * ispccdc_allocate_lsc - Allocate space for Lens Shading Compensation table
2175 - * @table_size: LSC gain table size.
2176 - *
2177 - * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if
2178 - * table_size is zero.
2179 + * ispccdc_enable_fpc - Enables the Faulty Pixel Correction.
2180 + * @enable: 0 Disables FPC, 1 Enables FPC.
2181   **/
2182 -static int ispccdc_allocate_lsc(struct isp_ccdc_device *isp_ccdc,
2183 -                               u32 table_size)
2184 +static void ispccdc_enable_fpc(struct isp_ccdc_device *isp_ccdc, u8 enable)
2185  {
2186 -       struct isp_device *isp = to_isp_device(isp_ccdc);
2187 -
2188 -       if (table_size == 0)
2189 -               return -EINVAL;
2190 +       struct device *dev = to_device(isp_ccdc);
2191  
2192 -       if ((isp_ccdc->lsc_config.size >= table_size)
2193 -           && isp_ccdc->lsc_gain_table)
2194 -               return 0;
2195 +       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC,
2196 +                      ~ISPCCDC_FPC_FPCEN, enable ? ISPCCDC_FPC_FPCEN : 0);
2197 +}
2198  
2199 -       ispccdc_free_lsc(isp_ccdc);
2200 +/**
2201 + * ispccdc_config_black_comp - Configures Black Level Compensation parameters.
2202 + * @blcomp: Structure containing the black level compensation value for RGrGbB
2203 + *          pixels. in 2's complement.
2204 + **/
2205 +static void ispccdc_config_black_comp(struct isp_ccdc_device *isp_ccdc,
2206 +                                     struct ispccdc_blcomp blcomp)
2207 +{
2208 +       struct device *dev = to_device(isp_ccdc);
2209 +       u32 blcomp_val = 0;
2210  
2211 -       isp_ccdc->lsc_ispmmu_addr = iommu_vmalloc(isp->iommu, 0, table_size,
2212 -                                                 IOMMU_FLAG);
2213 -       if (IS_ERR_VALUE(isp_ccdc->lsc_ispmmu_addr)) {
2214 -               dev_err(to_device(isp_ccdc),
2215 -                       "ccdc: Cannot allocate memory for gain tables\n");
2216 -               isp_ccdc->lsc_ispmmu_addr = 0;
2217 -               return -ENOMEM;
2218 -       }
2219 -       isp_ccdc->lsc_gain_table = da_to_va(isp->iommu,
2220 -                                           (u32)isp_ccdc->lsc_ispmmu_addr);
2221 +       blcomp_val |= blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
2222 +       blcomp_val |= blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
2223 +       blcomp_val |= blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
2224 +       blcomp_val |= blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
2225  
2226 -       return 0;
2227 +       isp_reg_writel(dev, blcomp_val, OMAP3_ISP_IOMEM_CCDC,
2228 +                      ISPCCDC_BLKCMP);
2229  }
2230  
2231  /**
2232 - * ispccdc_program_lsc - Program Lens Shading Compensation table.
2233 - * @table_size: LSC gain table size.
2234 - *
2235 - * Returns 0 if successful, or -EINVAL if there's no mapped address for the
2236 - * table yet.
2237 + * ispccdc_config_vp - Configures the Video Port Configuration parameters.
2238 + * @vpcfg: Structure containing the Video Port input frequency, and the 10 bit
2239 + *         format.
2240   **/
2241 -static int ispccdc_program_lsc(struct isp_ccdc_device *isp_ccdc)
2242 +static void ispccdc_config_vp(struct isp_ccdc_device *isp_ccdc,
2243 +                             struct ispccdc_vp vpcfg)
2244  {
2245 -       if (!isp_ccdc->lsc_ispmmu_addr)
2246 -               return -EINVAL;
2247 +       struct device *dev = to_device(isp_ccdc);
2248 +       u32 fmtcfg_vp = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2249 +                                     ISPCCDC_FMTCFG);
2250  
2251 -       if (isp_ccdc->lsc_initialized)
2252 -               return 0;
2253 +       fmtcfg_vp &= ISPCCDC_FMTCFG_VPIN_MASK & ISPCCDC_FMTCFG_VPIF_FRQ_MASK;
2254  
2255 -       isp_reg_writel(to_device(isp_ccdc), isp_ccdc->lsc_ispmmu_addr,
2256 -                      OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
2257 -       isp_ccdc->lsc_initialized = 1;
2258 -       return 0;
2259 +       switch (vpcfg.bitshift_sel) {
2260 +       case BIT9_0:
2261 +               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
2262 +               break;
2263 +       case BIT10_1:
2264 +               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
2265 +               break;
2266 +       case BIT11_2:
2267 +               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
2268 +               break;
2269 +       case BIT12_3:
2270 +               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
2271 +               break;
2272 +       };
2273 +       switch (vpcfg.freq_sel) {
2274 +       case PIXCLKBY2:
2275 +               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY2;
2276 +               break;
2277 +       case PIXCLKBY3_5:
2278 +               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY3;
2279 +               break;
2280 +       case PIXCLKBY4_5:
2281 +               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY4;
2282 +               break;
2283 +       case PIXCLKBY5_5:
2284 +               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY5;
2285 +               break;
2286 +       case PIXCLKBY6_5:
2287 +               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY6;
2288 +               break;
2289 +       };
2290 +       isp_reg_writel(dev, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
2291  }
2292  
2293  /**
2294 - * ispccdc_load_lsc - Load Lens Shading Compensation table.
2295 - * @table_addr: LSC gain table MMU Mapped address.
2296 - * @table_size: LSC gain table size.
2297 - *
2298 - * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if
2299 - * table_size is zero.
2300 + * ispccdc_enable_vp - Enables the Video Port.
2301 + * @enable: 0 Disables VP, 1 Enables VP
2302   **/
2303 -int ispccdc_load_lsc(struct isp_ccdc_device *isp_ccdc, u8 *table_addr,
2304 -                    u32 table_size)
2305 +static void ispccdc_enable_vp(struct isp_ccdc_device *isp_ccdc, u8 enable)
2306  {
2307 -       int ret;
2308 -
2309 -       if (!is_isplsc_activated())
2310 -               return 0;
2311 -
2312 -       if (!table_addr)
2313 -               return -EINVAL;
2314 +       struct device *dev = to_device(isp_ccdc);
2315  
2316 -       ret = ispccdc_allocate_lsc(isp_ccdc, table_size);
2317 -       if (ret)
2318 -               return ret;
2319 -
2320 -       if (table_addr != isp_ccdc->lsc_gain_table)
2321 -               memcpy(isp_ccdc->lsc_gain_table, table_addr, table_size);
2322 -       ret = ispccdc_program_lsc(isp_ccdc);
2323 -       if (ret)
2324 -               return ret;
2325 -       return 0;
2326 +       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
2327 +                      ~ISPCCDC_FMTCFG_VPEN,
2328 +                      enable ? ISPCCDC_FMTCFG_VPEN : 0);
2329  }
2330  
2331  /**
2332 - * ispccdc_config_lsc - Configures the lens shading compensation module
2333 - * @lsc_cfg: LSC configuration structure
2334 + * ispccdc_config_culling - Configures the culling parameters.
2335 + * @cull: Structure containing the vertical culling pattern, and horizontal
2336 + *        culling pattern for odd and even lines.
2337   **/
2338 -void ispccdc_config_lsc(struct isp_ccdc_device *isp_ccdc,
2339 -                       struct ispccdc_lsc_config *lsc_cfg)
2340 +static void ispccdc_config_culling(struct isp_ccdc_device *isp_ccdc,
2341 +                                  struct ispccdc_culling cull)
2342  {
2343         struct device *dev = to_device(isp_ccdc);
2344 -       int reg;
2345  
2346 -       if (!is_isplsc_activated())
2347 -               return;
2348 -
2349 -       ispccdc_enable_lsc(isp_ccdc, 0);
2350 -       isp_reg_writel(dev, lsc_cfg->offset, OMAP3_ISP_IOMEM_CCDC,
2351 -                      ISPCCDC_LSC_TABLE_OFFSET);
2352 +       u32 culling_val = 0;
2353  
2354 -       reg = 0;
2355 -       reg |= lsc_cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT;
2356 -       reg |= lsc_cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT;
2357 -       reg |= lsc_cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT;
2358 -       isp_reg_writel(dev, reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
2359 +       culling_val |= cull.v_pattern << ISPCCDC_CULLING_CULV_SHIFT;
2360 +       culling_val |= cull.h_even << ISPCCDC_CULLING_CULHEVN_SHIFT;
2361 +       culling_val |= cull.h_odd << ISPCCDC_CULLING_CULHODD_SHIFT;
2362  
2363 -       reg = 0;
2364 -       reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
2365 -       reg |= lsc_cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT;
2366 -       reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
2367 -       reg |= lsc_cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT;
2368 -       isp_reg_writel(dev, reg, OMAP3_ISP_IOMEM_CCDC,
2369 -                      ISPCCDC_LSC_INITIAL);
2370 +       isp_reg_writel(dev, culling_val, OMAP3_ISP_IOMEM_CCDC,
2371 +                      ISPCCDC_CULLING);
2372  }
2373  
2374  /**
2375 - * ispccdc_enable_lsc - Enables/Disables the Lens Shading Compensation module.
2376 - * @enable: 0 Disables LSC, 1 Enables LSC.
2377 + * ispccdc_enable_lpf - Enables the Low-Pass Filter (LPF).
2378 + * @enable: 0 Disables LPF, 1 Enables LPF
2379   **/
2380 -void ispccdc_enable_lsc(struct isp_ccdc_device *isp_ccdc, u8 enable)
2381 +static void ispccdc_enable_lpf(struct isp_ccdc_device *isp_ccdc, u8 enable)
2382  {
2383         struct device *dev = to_device(isp_ccdc);
2384  
2385 -       if (!is_isplsc_activated())
2386 -               return;
2387 -
2388 -       if (enable) {
2389 -               if (!ispccdc_busy(isp_ccdc)) {
2390 -                       isp_reg_or(dev, OMAP3_ISP_IOMEM_MAIN,
2391 -                                  ISP_CTRL, ISPCTRL_SBL_SHARED_RPORTB
2392 -                                  | ISPCTRL_SBL_RD_RAM_EN);
2393 -
2394 -                       isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC,
2395 -                                  ISPCCDC_LSC_CONFIG, 0x1);
2396 -
2397 -                       isp_ccdc->lsc_state = 1;
2398 -               } else {
2399 -                       /* Postpone enabling LSC */
2400 -                       isp_ccdc->lsc_enable = 1;
2401 -               }
2402 -       } else {
2403 -               isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC,
2404 -                           ISPCCDC_LSC_CONFIG, 0xFFFE);
2405 -               isp_ccdc->lsc_state = 0;
2406 -               isp_ccdc->lsc_enable = 0;
2407 -       }
2408 +       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
2409 +                      ~ISPCCDC_SYN_MODE_LPF,
2410 +                      enable ? ISPCCDC_SYN_MODE_LPF : 0);
2411  }
2412  
2413 -void ispccdc_lsc_error_handler(struct isp_ccdc_device *isp_ccdc)
2414 +/**
2415 + * ispccdc_config_alaw - Configures the input width for A-law.
2416 + * @ipwidth: Input width for A-law
2417 + **/
2418 +static void ispccdc_config_alaw(struct isp_ccdc_device *isp_ccdc,
2419 +                               enum alaw_ipwidth ipwidth)
2420  {
2421 -       int lsc_enable = isp_ccdc->lsc_state;
2422 -
2423 -       ispccdc_enable_lsc(isp_ccdc, 0);
2424 +       struct device *dev = to_device(isp_ccdc);
2425  
2426 -       isp_ccdc->lsc_enable = lsc_enable;
2427 +       isp_reg_writel(dev, ipwidth << ISPCCDC_ALAW_GWDI_SHIFT,
2428 +                      OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
2429  }
2430  
2431  /**
2432 - * ispccdc_config_crop - Configures crop parameters for the ISP CCDC.
2433 - * @left: Left offset of the crop area.
2434 - * @top: Top offset of the crop area.
2435 - * @height: Height of the crop area.
2436 - * @width: Width of the crop area.
2437 - *
2438 - * The following restrictions are applied for the crop settings. If incoming
2439 - * values do not follow these restrictions then we map the settings to the
2440 - * closest acceptable crop value.
2441 - * 1) Left offset is always odd. This can be avoided if we enable byte swap
2442 - *    option for incoming data into CCDC.
2443 - * 2) Top offset is always even.
2444 - * 3) Crop height is always even.
2445 - * 4) Crop width is always a multiple of 16 pixels
2446 + * ispccdc_enable_alaw - Enables the A-law compression.
2447 + * @enable: 0 - Disables A-law, 1 - Enables A-law
2448   **/
2449 -void ispccdc_config_crop(struct isp_ccdc_device *isp_ccdc, u32 left, u32 top,
2450 -                        u32 height, u32 width)
2451 +static void ispccdc_enable_alaw(struct isp_ccdc_device *isp_ccdc, u8 enable)
2452  {
2453 -       isp_ccdc->ccdcin_woffset = left + (left % 2);
2454 -       isp_ccdc->ccdcin_hoffset = top + (top % 2);
2455 -
2456 -       isp_ccdc->crop_w = width - (width % 16);
2457 -       isp_ccdc->crop_h = height + (height % 2);
2458 +       struct device *dev = to_device(isp_ccdc);
2459  
2460 -       DPRINTK_ISPCCDC("\n\tOffsets L %d T %d W %d H %d\n",
2461 -                       isp_ccdc->ccdcin_woffset,
2462 -                       isp_ccdc->ccdcin_hoffset,
2463 -                       isp_ccdc->crop_w,
2464 -                       isp_ccdc->crop_h);
2465 +       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW,
2466 +                      ~ISPCCDC_ALAW_CCDTBL,
2467 +                      enable ? ISPCCDC_ALAW_CCDTBL : 0);
2468  }
2469  
2470  /**
2471 - * ispccdc_config_datapath - Specifies the input and output modules for CCDC.
2472 - * @input: Indicates the module that inputs the image to the CCDC.
2473 - * @output: Indicates the module to which the CCDC outputs the image.
2474 - *
2475 - * Configures the default configuration for the CCDC to work with.
2476 - *
2477 - * The valid values for the input are CCDC_RAW (0), CCDC_YUV_SYNC (1),
2478 - * CCDC_YUV_BT (2), and CCDC_OTHERS (3).
2479 - *
2480 - * The valid values for the output are CCDC_YUV_RSZ (0), CCDC_YUV_MEM_RSZ (1),
2481 - * CCDC_OTHERS_VP (2), CCDC_OTHERS_MEM (3), CCDC_OTHERS_VP_MEM (4).
2482 - *
2483 - * Returns 0 if successful, or -EINVAL if wrong I/O combination or wrong input
2484 - * or output values.
2485 + * ispccdc_config_imgattr - Configures the sensor image specific attributes.
2486 + * @colptn: Color pattern of the sensor.
2487   **/
2488 -static int ispccdc_config_datapath(struct isp_ccdc_device *isp_ccdc,
2489 -                                  struct isp_pipeline *pipe)
2490 +static void ispccdc_config_imgattr(struct isp_ccdc_device *isp_ccdc, u32 colptn)
2491  {
2492         struct device *dev = to_device(isp_ccdc);
2493  
2494 -       u32 syn_mode = 0;
2495 -       struct ispccdc_vp vpcfg;
2496 -       struct ispccdc_syncif syncif;
2497 -       struct ispccdc_bclamp blkcfg;
2498 -
2499 -       u32 colptn = ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
2500 -               ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
2501 -               ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
2502 -               ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
2503 -               ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
2504 -               ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
2505 -               ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
2506 -               ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
2507 -               ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
2508 -               ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
2509 -               ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
2510 -               ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
2511 -               ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
2512 -               ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
2513 -               ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
2514 -               ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
2515 -
2516 -       syn_mode = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
2517 -
2518 -       switch (pipe->ccdc_out) {
2519 -       case CCDC_YUV_RSZ:
2520 -               syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
2521 -               syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
2522 -               break;
2523 -
2524 -       case CCDC_YUV_MEM_RSZ:
2525 -               syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
2526 -               isp_ccdc->wen = 1;
2527 -               syn_mode |= ISPCCDC_SYN_MODE_WEN;
2528 -               break;
2529 -
2530 -       case CCDC_OTHERS_VP:
2531 -               syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
2532 -               syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
2533 -               syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
2534 -               vpcfg.bitshift_sel = BIT9_0;
2535 -               vpcfg.freq_sel = PIXCLKBY2;
2536 -               ispccdc_config_vp(isp_ccdc, vpcfg);
2537 -               ispccdc_enable_vp(isp_ccdc, 1);
2538 -               break;
2539 -
2540 -       case CCDC_OTHERS_MEM:
2541 -               syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
2542 -               syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
2543 -               syn_mode |= ISPCCDC_SYN_MODE_WEN;
2544 -               syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
2545 -               isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
2546 -                           ~ISPCCDC_CFG_WENLOG);
2547 -               vpcfg.bitshift_sel = BIT11_2;
2548 -               vpcfg.freq_sel = PIXCLKBY2;
2549 -               ispccdc_config_vp(isp_ccdc, vpcfg);
2550 -               ispccdc_enable_vp(isp_ccdc, 0);
2551 -               break;
2552 -
2553 -       case CCDC_OTHERS_VP_MEM:
2554 -               syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
2555 -               syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
2556 -               syn_mode |= ISPCCDC_SYN_MODE_WEN;
2557 -               syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
2558 -
2559 -               isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
2560 -                              ~ISPCCDC_CFG_WENLOG, isp_ccdc->wenlog);
2561 -               vpcfg.bitshift_sel = BIT9_0;
2562 -               vpcfg.freq_sel = PIXCLKBY2;
2563 -               ispccdc_config_vp(isp_ccdc, vpcfg);
2564 -               ispccdc_enable_vp(isp_ccdc, 1);
2565 -               break;
2566 -       default:
2567 -               DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output\n");
2568 -               return -EINVAL;
2569 -       };
2570 -
2571 -       isp_reg_writel(dev, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
2572 -
2573 -       switch (pipe->ccdc_in) {
2574 -       case CCDC_RAW:
2575 -               syncif.ccdc_mastermode = 0;
2576 -               syncif.datapol = 0;
2577 -               syncif.datsz = DAT10;
2578 -               syncif.fldmode = 0;
2579 -               syncif.fldout = 0;
2580 -               syncif.fldpol = 0;
2581 -               syncif.fldstat = 0;
2582 -               syncif.hdpol = 0;
2583 -               syncif.ipmod = RAW;
2584 -               syncif.vdpol = 0;
2585 -               ispccdc_config_sync_if(isp_ccdc, syncif);
2586 -               ispccdc_config_imgattr(isp_ccdc, colptn);
2587 -               blkcfg.oblen = 0;
2588 -               blkcfg.dcsubval = 64;
2589 -               ispccdc_config_black_clamp(isp_ccdc, blkcfg);
2590 -               if (is_isplsc_activated()) {
2591 -                       ispccdc_config_lsc(isp_ccdc, &isp_ccdc->lsc_config);
2592 -                       ispccdc_load_lsc(isp_ccdc, isp_ccdc->lsc_gain_table_tmp,
2593 -                                        LSC_TABLE_INIT_SIZE);
2594 -               }
2595 -
2596 -               break;
2597 -       case CCDC_YUV_SYNC:
2598 -               syncif.ccdc_mastermode = 0;
2599 -               syncif.datapol = 0;
2600 -               syncif.datsz = DAT8;
2601 -               syncif.fldmode = 0;
2602 -               syncif.fldout = 0;
2603 -               syncif.fldpol = 0;
2604 -               syncif.fldstat = 0;
2605 -               syncif.hdpol = 0;
2606 -               syncif.ipmod = YUV16;
2607 -               syncif.vdpol = 1;
2608 -               ispccdc_config_imgattr(isp_ccdc, 0);
2609 -               ispccdc_config_sync_if(isp_ccdc, syncif);
2610 -               blkcfg.oblen = 0;
2611 -               blkcfg.dcsubval = 0;
2612 -               ispccdc_config_black_clamp(isp_ccdc, blkcfg);
2613 -               break;
2614 -       case CCDC_YUV_BT:
2615 -               break;
2616 -       case CCDC_OTHERS:
2617 -               break;
2618 -       default:
2619 -               DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Input\n");
2620 -               return -EINVAL;
2621 -       }
2622 -
2623 -       ispccdc_print_status(isp_ccdc, pipe);
2624 -       isp_print_status(dev);
2625 -       return 0;
2626 +       isp_reg_writel(dev, colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
2627  }
2628  
2629  /**
2630 - * ispccdc_config_sync_if - Sets the sync i/f params between sensor and CCDC.
2631 - * @syncif: Structure containing the sync parameters like field state, CCDC in
2632 - *          master/slave mode, raw/yuv data, polarity of data, field, hs, vs
2633 - *          signals.
2634 + * ispccdc_validate_config_lsc - Check that LSC configuration is valid.
2635 + * @lsc_cfg: the LSC configuration to check.
2636 + * @pipe: if not NULL, verify the table size against CCDC input size.
2637 + *
2638 + * Returns 0 if the LSC configuration is valid, or -EINVAL if invalid.
2639   **/
2640 -void ispccdc_config_sync_if(struct isp_ccdc_device *isp_ccdc,
2641 -                           struct ispccdc_syncif syncif)
2642 +static int ispccdc_validate_config_lsc(struct isp_ccdc_device *isp_ccdc,
2643 +                                      struct ispccdc_lsc_config *lsc_cfg,
2644 +                                      struct isp_pipeline *pipe)
2645  {
2646         struct device *dev = to_device(isp_ccdc);
2647 -       u32 syn_mode = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2648 -                                    ISPCCDC_SYN_MODE);
2649 -
2650 -       syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
2651 -
2652 -       if (syncif.fldstat)
2653 -               syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
2654 -       else
2655 -               syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
2656 +       unsigned int paxel_width, paxel_height;
2657 +       unsigned int paxel_shift_x, paxel_shift_y;
2658 +       unsigned int min_width, min_height, min_size;
2659 +       unsigned int input_width, input_height;
2660  
2661 -       syn_mode &= ISPCCDC_SYN_MODE_INPMOD_MASK;
2662 -       isp_ccdc->syncif_ipmod = syncif.ipmod;
2663 +       paxel_shift_x = lsc_cfg->gain_mode_m;
2664 +       paxel_shift_y = lsc_cfg->gain_mode_n;
2665  
2666 -       switch (syncif.ipmod) {
2667 -       case RAW:
2668 -               break;
2669 -       case YUV16:
2670 -               syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
2671 -               break;
2672 -       case YUV8:
2673 -               syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
2674 -               break;
2675 -       };
2676 +       if ((paxel_shift_x < 2) || (paxel_shift_x > 6) ||
2677 +           (paxel_shift_y < 2) || (paxel_shift_y > 6)) {
2678 +               dev_dbg(dev, "CCDC: LSC: Invalid paxel size\n");
2679 +               return -EINVAL;
2680 +       }
2681  
2682 -       syn_mode &= ISPCCDC_SYN_MODE_DATSIZ_MASK;
2683 -       switch (syncif.datsz) {
2684 -       case DAT8:
2685 -               syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
2686 -               break;
2687 -       case DAT10:
2688 -               syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
2689 -               break;
2690 -       case DAT11:
2691 -               syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
2692 -               break;
2693 -       case DAT12:
2694 -               syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
2695 -               break;
2696 -       };
2697 +       if (lsc_cfg->offset & 3) {
2698 +               dev_dbg(dev, "CCDC: LSC: Offset must be a multiple of 4\n");
2699 +               return -EINVAL;
2700 +       }
2701  
2702 -       if (syncif.fldmode)
2703 -               syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
2704 -       else
2705 -               syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
2706 +       if ((lsc_cfg->initial_x & 1) || (lsc_cfg->initial_y & 1)) {
2707 +               dev_dbg(dev, "CCDC: LSC: initial_x and y must be even\n");
2708 +               return -EINVAL;
2709 +       }
2710  
2711 -       if (syncif.datapol)
2712 -               syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
2713 -       else
2714 -               syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
2715 +       if (!pipe)
2716 +               return 0;
2717  
2718 -       if (syncif.fldpol)
2719 -               syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
2720 -       else
2721 -               syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
2722 +       input_width = pipe->ccdc_in_w;
2723 +       input_height = pipe->ccdc_in_h;
2724  
2725 -       if (syncif.hdpol)
2726 -               syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
2727 -       else
2728 -               syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
2729 +       /* Calculate minimum bytesize for validation */
2730 +       paxel_width = 1 << paxel_shift_x;
2731 +       min_width = ((input_width + lsc_cfg->initial_x + paxel_width - 1)
2732 +                    >> paxel_shift_x) + 1;
2733 +
2734 +       paxel_height = 1 << paxel_shift_y;
2735 +       min_height = ((input_height + lsc_cfg->initial_y + paxel_height - 1)
2736 +                    >> paxel_shift_y) + 1;
2737 +
2738 +       min_size = 4 * min_width * min_height;
2739 +       if (min_size > lsc_cfg->size) {
2740 +               dev_dbg(dev, "CCDC: LSC: too small table\n");
2741 +               return -EINVAL;
2742 +       }
2743 +       if (lsc_cfg->offset < (min_width * 4)) {
2744 +               dev_dbg(dev, "CCDC: LSC: Offset is too small\n");
2745 +               return -EINVAL;
2746 +       }
2747 +       if ((lsc_cfg->size / lsc_cfg->offset) < min_height) {
2748 +               dev_dbg(dev, "CCDC: LSC: Wrong size/offset combination\n");
2749 +               return -EINVAL;
2750 +       }
2751 +       return 0;
2752 +}
2753  
2754 -       if (syncif.vdpol)
2755 -               syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
2756 -       else
2757 -               syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
2758 +/**
2759 + * ispccdc_program_lsc - Program Lens Shading Compensation table address.
2760 + **/
2761 +static void ispccdc_program_lsc(struct isp_ccdc_device *isp_ccdc)
2762 +{
2763 +       isp_reg_writel(to_device(isp_ccdc), isp_ccdc->lsc_table_inuse,
2764 +                      OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
2765 +}
2766  
2767 -       if (syncif.ccdc_mastermode) {
2768 -               syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
2769 -               isp_reg_writel(dev,
2770 -                              syncif.hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT
2771 -                              | syncif.vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT,
2772 -                              OMAP3_ISP_IOMEM_CCDC,
2773 -                              ISPCCDC_HD_VD_WID);
2774 +/**
2775 + * ispccdc_config_lsc - Configures the lens shading compensation module
2776 + **/
2777 +static void ispccdc_config_lsc(struct isp_ccdc_device *isp_ccdc)
2778 +{
2779 +       struct device *dev = to_device(isp_ccdc);
2780 +       struct ispccdc_lsc_config *lsc_cfg = &isp_ccdc->lsc_config;
2781 +       int reg;
2782  
2783 -               isp_reg_writel(dev,
2784 -                              syncif.ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
2785 -                              | syncif.hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
2786 -                              OMAP3_ISP_IOMEM_CCDC,
2787 -                              ISPCCDC_PIX_LINES);
2788 -       } else
2789 -               syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
2790 -                             ISPCCDC_SYN_MODE_VDHDOUT);
2791 +       isp_reg_writel(dev, lsc_cfg->offset, OMAP3_ISP_IOMEM_CCDC,
2792 +                      ISPCCDC_LSC_TABLE_OFFSET);
2793  
2794 -       isp_reg_writel(dev, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
2795 +       reg = 0;
2796 +       reg |= lsc_cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT;
2797 +       reg |= lsc_cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT;
2798 +       reg |= lsc_cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT;
2799 +       isp_reg_writel(dev, reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
2800  
2801 -       if (!(syncif.bt_r656_en)) {
2802 -               isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC,
2803 -                           ISPCCDC_REC656IF, ~ISPCCDC_REC656IF_R656ON);
2804 -       }
2805 +       reg = 0;
2806 +       reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
2807 +       reg |= lsc_cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT;
2808 +       reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
2809 +       reg |= lsc_cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT;
2810 +       isp_reg_writel(dev, reg, OMAP3_ISP_IOMEM_CCDC,
2811 +                      ISPCCDC_LSC_INITIAL);
2812  }
2813  
2814  /**
2815 - * ispccdc_config_black_clamp - Configures the clamp parameters in CCDC.
2816 - * @bclamp: Structure containing the optical black average gain, optical black
2817 - *          sample length, sample lines, and the start pixel position of the
2818 - *          samples w.r.t the HS pulse.
2819 - * Configures the clamp parameters in CCDC. Either if its being used the
2820 - * optical black clamp, or the digital clamp. If its a digital clamp, then
2821 - * assures to put a valid DC substraction level.
2822 - *
2823 - * Returns always 0 when completed.
2824 + * ispccdc_enable_lsc - Enables/Disables the Lens Shading Compensation module.
2825 + * @enable: 0 Disables LSC, 1 Enables LSC.
2826   **/
2827 -int ispccdc_config_black_clamp(struct isp_ccdc_device *isp_ccdc,
2828 -                              struct ispccdc_bclamp bclamp)
2829 +static void ispccdc_enable_lsc(struct isp_ccdc_device *isp_ccdc, u8 enable)
2830  {
2831         struct device *dev = to_device(isp_ccdc);
2832 -       u32 bclamp_val = 0;
2833  
2834 -       if (isp_ccdc->obclamp_en) {
2835 -               bclamp_val |= bclamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
2836 -               bclamp_val |= bclamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
2837 -               bclamp_val |= bclamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
2838 -               bclamp_val |= bclamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
2839 -               isp_reg_writel(dev, bclamp_val,
2840 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP);
2841 +       if (enable) {
2842 +               isp_reg_or(dev, OMAP3_ISP_IOMEM_MAIN,
2843 +                          ISP_CTRL, ISPCTRL_SBL_SHARED_RPORTB
2844 +                          | ISPCTRL_SBL_RD_RAM_EN);
2845 +
2846 +               isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC,
2847 +                          ISPCCDC_LSC_CONFIG, ISPCCDC_LSC_ENABLE);
2848         } else {
2849 -               if (omap_rev() < OMAP3430_REV_ES2_0)
2850 -                       if (isp_ccdc->syncif_ipmod == YUV16 ||
2851 -                           isp_ccdc->syncif_ipmod == YUV8 ||
2852 -                           isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2853 -                                         ISPCCDC_REC656IF) &
2854 -                           ISPCCDC_REC656IF_R656ON)
2855 -                               bclamp.dcsubval = 0;
2856 -               isp_reg_writel(dev, bclamp.dcsubval,
2857 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB);
2858 +               isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC,
2859 +                           ISPCCDC_LSC_CONFIG, ~ISPCCDC_LSC_ENABLE);
2860         }
2861 -       return 0;
2862  }
2863  
2864  /**
2865 - * ispccdc_enable_black_clamp - Enables/Disables the optical black clamp.
2866 - * @enable: 0 Disables optical black clamp, 1 Enables optical black clamp.
2867 + * ispccdc_setup_lsc - apply user LSC settings
2868 + * Consume the new LSC configuration and table set by user space application
2869 + * and program to CCDC.  This function must be called from process context
2870 + * before streamon when ISP is not yet running. This function does not yet
2871 + * actually enable LSC, that has to be done separately.
2872 + */
2873 +static void ispccdc_setup_lsc(struct isp_ccdc_device *isp_ccdc,
2874 +                             struct isp_pipeline *pipe)
2875 +{
2876 +       ispccdc_enable_lsc(isp_ccdc, 0);        /* Disable LSC */
2877 +       if (pipe->ccdc_in == CCDC_RAW && isp_ccdc->lsc_request_enable) {
2878 +               /* LSC is requested to be enabled, so configure it */
2879 +               if (isp_ccdc->update_lsc_table) {
2880 +                       struct isp_device *isp = to_isp_device(isp_ccdc);
2881 +                       BUG_ON(isp_ccdc->lsc_table_new == PTR_FREE);
2882 +                       iommu_vfree(isp->iommu, isp_ccdc->lsc_table_inuse);
2883 +                       isp_ccdc->lsc_table_inuse = isp_ccdc->lsc_table_new;
2884 +                       isp_ccdc->lsc_table_new = PTR_FREE;
2885 +                       isp_ccdc->update_lsc_table = 0;
2886 +               }
2887 +               ispccdc_config_lsc(isp_ccdc);
2888 +               ispccdc_program_lsc(isp_ccdc);
2889 +       }
2890 +       isp_ccdc->update_lsc_config = 0;
2891 +}
2892 +
2893 +void ispccdc_lsc_error_handler(struct isp_ccdc_device *isp_ccdc)
2894 +{
2895 +       ispccdc_enable_lsc(isp_ccdc, 0);
2896 +}
2897 +
2898 +/**
2899 + * ispccdc_config_crop - Configures crop parameters for the ISP CCDC.
2900 + * @left: Left offset of the crop area.
2901 + * @top: Top offset of the crop area.
2902 + * @height: Height of the crop area.
2903 + * @width: Width of the crop area.
2904   *
2905 - * Enables or disables the optical black clamp. When disabled, the digital
2906 - * clamp operates.
2907 + * The following restrictions are applied for the crop settings. If incoming
2908 + * values do not follow these restrictions then we map the settings to the
2909 + * closest acceptable crop value.
2910 + * 1) Left offset is always odd. This can be avoided if we enable byte swap
2911 + *    option for incoming data into CCDC.
2912 + * 2) Top offset is always even.
2913 + * 3) Crop height is always even.
2914 + * 4) Crop width is always a multiple of 16 pixels
2915   **/
2916 -void ispccdc_enable_black_clamp(struct isp_ccdc_device *isp_ccdc, u8 enable)
2917 +static void ispccdc_config_crop(struct isp_ccdc_device *isp_ccdc,
2918 +                               u32 left, u32 top, u32 height, u32 width)
2919  {
2920 -       struct device *dev = to_device(isp_ccdc);
2921 +       isp_ccdc->ccdcin_woffset = left + (left % 2);
2922 +       isp_ccdc->ccdcin_hoffset = top + (top % 2);
2923  
2924 -       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
2925 -                      ~ISPCCDC_CLAMP_CLAMPEN,
2926 -                      enable ? ISPCCDC_CLAMP_CLAMPEN : 0);
2927 -       isp_ccdc->obclamp_en = enable;
2928 +       isp_ccdc->crop_w = width - (width % 16);
2929 +       isp_ccdc->crop_h = height + (height % 2);
2930 +
2931 +       DPRINTK_ISPCCDC("\n\tOffsets L %d T %d W %d H %d\n",
2932 +                       isp_ccdc->ccdcin_woffset,
2933 +                       isp_ccdc->ccdcin_hoffset,
2934 +                       isp_ccdc->crop_w,
2935 +                       isp_ccdc->crop_h);
2936  }
2937  
2938  /**
2939 - * ispccdc_config_fpc - Configures the Faulty Pixel Correction parameters.
2940 - * @fpc: Structure containing the number of faulty pixels corrected in the
2941 - *       frame, address of the FPC table.
2942 + * ispccdc_config_outlineoffset - Configures the output line offset
2943 + * @offset: Must be twice the Output width and aligned on 32 byte boundary
2944 + * @oddeven: Specifies the odd/even line pattern to be chosen to store the
2945 + *           output.
2946 + * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
2947   *
2948 - * Returns 0 if successful, or -EINVAL if FPC Address is not on the 64 byte
2949 + * - Configures the output line offset when stored in memory
2950 + * - Sets the odd/even line pattern to store the output
2951 + *    (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
2952 + * - Configures the number of even and odd line fields in case of rearranging
2953 + * the lines.
2954 + *
2955 + * Returns 0 if successful, or -EINVAL if the offset is not in 32 byte
2956   * boundary.
2957   **/
2958 -int ispccdc_config_fpc(struct isp_ccdc_device *isp_ccdc, struct ispccdc_fpc fpc)
2959 +static int ispccdc_config_outlineoffset(struct isp_ccdc_device *isp_ccdc,
2960 +                                       u32 offset, u8 oddeven, u8 numlines)
2961  {
2962         struct device *dev = to_device(isp_ccdc);
2963 -       u32 fpc_val = 0;
2964 -
2965 -       fpc_val = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
2966  
2967 -       if ((fpc.fpcaddr & 0xFFFFFFC0) == fpc.fpcaddr) {
2968 -               isp_reg_writel(dev, fpc_val & (~ISPCCDC_FPC_FPCEN),
2969 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
2970 -               isp_reg_writel(dev, fpc.fpcaddr,
2971 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR);
2972 +       if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
2973 +               isp_reg_writel(dev, (offset & 0xFFFF),
2974 +                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF);
2975         } else {
2976 -               DPRINTK_ISPCCDC("FPC Address should be on 64byte boundary\n");
2977 +               DPRINTK_ISPCCDC("ISP_ERR : Offset should be in 32 byte"
2978 +                               " boundary\n");
2979                 return -EINVAL;
2980         }
2981 -       isp_reg_writel(dev, fpc_val | (fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
2982 -                      OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
2983 -       return 0;
2984 -}
2985  
2986 -/**
2987 - * ispccdc_enable_fpc - Enables the Faulty Pixel Correction.
2988 - * @enable: 0 Disables FPC, 1 Enables FPC.
2989 - **/
2990 -void ispccdc_enable_fpc(struct isp_ccdc_device *isp_ccdc, u8 enable)
2991 -{
2992 -       struct device *dev = to_device(isp_ccdc);
2993 +       isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
2994 +                   ~ISPCCDC_SDOFST_FINV);
2995  
2996 -       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC,
2997 -                      ~ISPCCDC_FPC_FPCEN, enable ? ISPCCDC_FPC_FPCEN : 0);
2998 +       isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
2999 +                   ~ISPCCDC_SDOFST_FOFST_4L);
3000 +
3001 +       switch (oddeven) {
3002 +       case EVENEVEN:
3003 +               isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3004 +                          (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
3005 +               break;
3006 +       case ODDEVEN:
3007 +               isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3008 +                          (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
3009 +               break;
3010 +       case EVENODD:
3011 +               isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3012 +                          (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
3013 +               break;
3014 +       case ODDODD:
3015 +               isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3016 +                          (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
3017 +               break;
3018 +       default:
3019 +               break;
3020 +       }
3021 +       return 0;
3022  }
3023  
3024  /**
3025 - * ispccdc_config_black_comp - Configures Black Level Compensation parameters.
3026 - * @blcomp: Structure containing the black level compensation value for RGrGbB
3027 - *          pixels. in 2's complement.
3028 + * ispccdc_set_outaddr - Sets the memory address where the output will be saved
3029 + * @addr: 32-bit memory address aligned on 32 byte boundary.
3030 + *
3031 + * Sets the memory address where the output will be saved.
3032 + *
3033 + * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
3034 + * boundary.
3035   **/
3036 -void ispccdc_config_black_comp(struct isp_ccdc_device *isp_ccdc,
3037 -                              struct ispccdc_blcomp blcomp)
3038 +int ispccdc_set_outaddr(struct isp_ccdc_device *isp_ccdc, u32 addr)
3039  {
3040         struct device *dev = to_device(isp_ccdc);
3041 -       u32 blcomp_val = 0;
3042  
3043 -       blcomp_val |= blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
3044 -       blcomp_val |= blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
3045 -       blcomp_val |= blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
3046 -       blcomp_val |= blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
3047 +       if ((addr & ISP_32B_BOUNDARY_BUF) == addr) {
3048 +               isp_reg_writel(dev, addr, OMAP3_ISP_IOMEM_CCDC,
3049 +                              ISPCCDC_SDR_ADDR);
3050 +               return 0;
3051 +       } else {
3052 +               DPRINTK_ISPCCDC("ISP_ERR : Address should be in 32 byte"
3053 +                               " boundary\n");
3054 +               return -EINVAL;
3055 +       }
3056  
3057 -       isp_reg_writel(dev, blcomp_val, OMAP3_ISP_IOMEM_CCDC,
3058 -                      ISPCCDC_BLKCMP);
3059  }
3060  
3061  /**
3062 - * ispccdc_config_vp - Configures the Video Port Configuration parameters.
3063 - * @vpcfg: Structure containing the Video Port input frequency, and the 10 bit
3064 - *         format.
3065 + * ispccdc_config_sync_if - Sets the sync i/f params between sensor and CCDC.
3066 + * @syncif: Structure containing the sync parameters like field state, CCDC in
3067 + *          master/slave mode, raw/yuv data, polarity of data, field, hs, vs
3068 + *          signals.
3069   **/
3070 -void ispccdc_config_vp(struct isp_ccdc_device *isp_ccdc,
3071 -                      struct ispccdc_vp vpcfg)
3072 +static void ispccdc_config_sync_if(struct isp_ccdc_device *isp_ccdc,
3073 +                                  struct ispccdc_syncif syncif)
3074  {
3075         struct device *dev = to_device(isp_ccdc);
3076 -       u32 fmtcfg_vp = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
3077 -                                     ISPCCDC_FMTCFG);
3078 +       u32 syn_mode = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
3079 +                                    ISPCCDC_SYN_MODE);
3080  
3081 -       fmtcfg_vp &= ISPCCDC_FMTCFG_VPIN_MASK & ISPCCDC_FMTCFG_VPIF_FRQ_MASK;
3082 +       syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
3083  
3084 -       switch (vpcfg.bitshift_sel) {
3085 -       case BIT9_0:
3086 -               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
3087 -               break;
3088 -       case BIT10_1:
3089 -               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
3090 +       if (syncif.fldstat)
3091 +               syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
3092 +       else
3093 +               syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
3094 +
3095 +       syn_mode &= ISPCCDC_SYN_MODE_INPMOD_MASK;
3096 +       isp_ccdc->syncif_ipmod = syncif.ipmod;
3097 +
3098 +       switch (syncif.ipmod) {
3099 +       case RAW:
3100                 break;
3101 -       case BIT11_2:
3102 -               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
3103 +       case YUV16:
3104 +               syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
3105                 break;
3106 -       case BIT12_3:
3107 -               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
3108 +       case YUV8:
3109 +               syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
3110                 break;
3111         };
3112 -       switch (vpcfg.freq_sel) {
3113 -       case PIXCLKBY2:
3114 -               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY2;
3115 -               break;
3116 -       case PIXCLKBY3_5:
3117 -               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY3;
3118 +
3119 +       syn_mode &= ISPCCDC_SYN_MODE_DATSIZ_MASK;
3120 +       switch (syncif.datsz) {
3121 +       case DAT8:
3122 +               syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
3123                 break;
3124 -       case PIXCLKBY4_5:
3125 -               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY4;
3126 +       case DAT10:
3127 +               syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
3128                 break;
3129 -       case PIXCLKBY5_5:
3130 -               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY5;
3131 +       case DAT11:
3132 +               syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
3133                 break;
3134 -       case PIXCLKBY6_5:
3135 -               fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY6;
3136 +       case DAT12:
3137 +               syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
3138                 break;
3139         };
3140 -       isp_reg_writel(dev, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
3141 -}
3142  
3143 -/**
3144 - * ispccdc_enable_vp - Enables the Video Port.
3145 - * @enable: 0 Disables VP, 1 Enables VP
3146 - **/
3147 -void ispccdc_enable_vp(struct isp_ccdc_device *isp_ccdc, u8 enable)
3148 -{
3149 -       struct device *dev = to_device(isp_ccdc);
3150 +       if (syncif.fldmode)
3151 +               syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
3152 +       else
3153 +               syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
3154  
3155 -       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
3156 -                      ~ISPCCDC_FMTCFG_VPEN,
3157 -                      enable ? ISPCCDC_FMTCFG_VPEN : 0);
3158 -}
3159 +       if (syncif.datapol)
3160 +               syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
3161 +       else
3162 +               syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
3163  
3164 -/**
3165 - * ispccdc_config_reformatter - Configures the Reformatter.
3166 - * @refmt: Structure containing the memory address to format and the bit fields
3167 - *         for the reformatter registers.
3168 - *
3169 - * Configures the Reformatter register values if line alternating is disabled.
3170 - * Else, just enabling line alternating is enough.
3171 - **/
3172 -void ispccdc_config_reformatter(struct isp_ccdc_device *isp_ccdc,
3173 -                               struct ispccdc_refmt refmt)
3174 -{
3175 -       struct device *dev = to_device(isp_ccdc);
3176 -       u32 fmtcfg_val = 0;
3177 -
3178 -       fmtcfg_val = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
3179 -
3180 -       if (refmt.lnalt)
3181 -               fmtcfg_val |= ISPCCDC_FMTCFG_LNALT;
3182 -       else {
3183 -               fmtcfg_val &= ~ISPCCDC_FMTCFG_LNALT;
3184 -               fmtcfg_val &= 0xFFFFF003;
3185 -               fmtcfg_val |= refmt.lnum << ISPCCDC_FMTCFG_LNUM_SHIFT;
3186 -               fmtcfg_val |= refmt.plen_even <<
3187 -                       ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT;
3188 -               fmtcfg_val |= refmt.plen_odd << ISPCCDC_FMTCFG_PLEN_ODD_SHIFT;
3189 -
3190 -               isp_reg_writel(dev, refmt.prgeven0,
3191 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN0);
3192 -               isp_reg_writel(dev, refmt.prgeven1,
3193 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN1);
3194 -               isp_reg_writel(dev, refmt.prgodd0,
3195 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD0);
3196 -               isp_reg_writel(dev, refmt.prgodd1,
3197 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD1);
3198 -               isp_reg_writel(dev, refmt.fmtaddr0,
3199 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR0);
3200 -               isp_reg_writel(dev, refmt.fmtaddr1,
3201 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR1);
3202 -               isp_reg_writel(dev, refmt.fmtaddr2,
3203 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR2);
3204 -               isp_reg_writel(dev, refmt.fmtaddr3,
3205 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR3);
3206 -               isp_reg_writel(dev, refmt.fmtaddr4,
3207 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR4);
3208 -               isp_reg_writel(dev, refmt.fmtaddr5,
3209 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR5);
3210 -               isp_reg_writel(dev, refmt.fmtaddr6,
3211 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR6);
3212 -               isp_reg_writel(dev, refmt.fmtaddr7,
3213 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR7);
3214 -       }
3215 -       isp_reg_writel(dev, fmtcfg_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
3216 -}
3217 +       if (syncif.fldpol)
3218 +               syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
3219 +       else
3220 +               syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
3221  
3222 -/**
3223 - * ispccdc_enable_reformatter - Enables the Reformatter.
3224 - * @enable: 0 Disables Reformatter, 1- Enables Data Reformatter
3225 - **/
3226 -void ispccdc_enable_reformatter(struct isp_ccdc_device *isp_ccdc, u8 enable)
3227 -{
3228 -       struct device *dev = to_device(isp_ccdc);
3229 +       if (syncif.hdpol)
3230 +               syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
3231 +       else
3232 +               syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
3233  
3234 -       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
3235 -                      ~ISPCCDC_FMTCFG_FMTEN,
3236 -                      enable ? ISPCCDC_FMTCFG_FMTEN : 0);
3237 -       isp_ccdc->refmt_en = enable;
3238 -}
3239 +       if (syncif.vdpol)
3240 +               syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
3241 +       else
3242 +               syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
3243  
3244 -/**
3245 - * ispccdc_config_culling - Configures the culling parameters.
3246 - * @cull: Structure containing the vertical culling pattern, and horizontal
3247 - *        culling pattern for odd and even lines.
3248 - **/
3249 -void ispccdc_config_culling(struct isp_ccdc_device *isp_ccdc,
3250 -                           struct ispccdc_culling cull)
3251 -{
3252 -       struct device *dev = to_device(isp_ccdc);
3253 +       if (syncif.ccdc_mastermode) {
3254 +               syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
3255 +               isp_reg_writel(dev,
3256 +                              syncif.hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT
3257 +                              | syncif.vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT,
3258 +                              OMAP3_ISP_IOMEM_CCDC,
3259 +                              ISPCCDC_HD_VD_WID);
3260  
3261 -       u32 culling_val = 0;
3262 +               isp_reg_writel(dev,
3263 +                              syncif.ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
3264 +                              | syncif.hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
3265 +                              OMAP3_ISP_IOMEM_CCDC,
3266 +                              ISPCCDC_PIX_LINES);
3267 +       } else
3268 +               syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
3269 +                             ISPCCDC_SYN_MODE_VDHDOUT);
3270  
3271 -       culling_val |= cull.v_pattern << ISPCCDC_CULLING_CULV_SHIFT;
3272 -       culling_val |= cull.h_even << ISPCCDC_CULLING_CULHEVN_SHIFT;
3273 -       culling_val |= cull.h_odd << ISPCCDC_CULLING_CULHODD_SHIFT;
3274 +       isp_reg_writel(dev, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
3275  
3276 -       isp_reg_writel(dev, culling_val, OMAP3_ISP_IOMEM_CCDC,
3277 -                      ISPCCDC_CULLING);
3278 +       if (!(syncif.bt_r656_en)) {
3279 +               isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC,
3280 +                           ISPCCDC_REC656IF, ~ISPCCDC_REC656IF_R656ON);
3281 +       }
3282  }
3283  
3284  /**
3285 - * ispccdc_enable_lpf - Enables the Low-Pass Filter (LPF).
3286 - * @enable: 0 Disables LPF, 1 Enables LPF
3287 - **/
3288 -void ispccdc_enable_lpf(struct isp_ccdc_device *isp_ccdc, u8 enable)
3289 + * Set the value to be used for CCDC_CFG.WENLOG.
3290 + *  w - Value of wenlog.
3291 + */
3292 +void ispccdc_set_wenlog(struct isp_ccdc_device *isp_ccdc, u32 wenlog)
3293  {
3294 -       struct device *dev = to_device(isp_ccdc);
3295 -
3296 -       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
3297 -                      ~ISPCCDC_SYN_MODE_LPF,
3298 -                      enable ? ISPCCDC_SYN_MODE_LPF : 0);
3299 +       isp_ccdc->wenlog = wenlog;
3300  }
3301  
3302  /**
3303 - * ispccdc_config_alaw - Configures the input width for A-law.
3304 - * @ipwidth: Input width for A-law
3305 + * ispccdc_config_datapath - Specifies the input and output modules for CCDC.
3306 + * @input: Indicates the module that inputs the image to the CCDC.
3307 + * @output: Indicates the module to which the CCDC outputs the image.
3308 + *
3309 + * Configures the default configuration for the CCDC to work with.
3310 + *
3311 + * The valid values for the input are CCDC_RAW (0), CCDC_YUV_SYNC (1),
3312 + * CCDC_YUV_BT (2), and CCDC_OTHERS (3).
3313 + *
3314 + * The valid values for the output are CCDC_YUV_RSZ (0), CCDC_YUV_MEM_RSZ (1),
3315 + * CCDC_OTHERS_VP (2), CCDC_OTHERS_MEM (3), CCDC_OTHERS_VP_MEM (4).
3316 + *
3317 + * Returns 0 if successful, or -EINVAL if wrong I/O combination or wrong input
3318 + * or output values.
3319   **/
3320 -void ispccdc_config_alaw(struct isp_ccdc_device *isp_ccdc,
3321 -                        enum alaw_ipwidth ipwidth)
3322 +static int ispccdc_config_datapath(struct isp_ccdc_device *isp_ccdc,
3323 +                                  struct isp_pipeline *pipe)
3324  {
3325         struct device *dev = to_device(isp_ccdc);
3326  
3327 -       isp_reg_writel(dev, ipwidth << ISPCCDC_ALAW_GWDI_SHIFT,
3328 -                      OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
3329 -}
3330 +       u32 syn_mode = 0;
3331 +       struct ispccdc_vp vpcfg;
3332 +       struct ispccdc_syncif syncif;
3333 +       struct ispccdc_bclamp blkcfg;
3334  
3335 -/**
3336 - * ispccdc_enable_alaw - Enables the A-law compression.
3337 - * @enable: 0 - Disables A-law, 1 - Enables A-law
3338 - **/
3339 -void ispccdc_enable_alaw(struct isp_ccdc_device *isp_ccdc, u8 enable)
3340 -{
3341 -       struct device *dev = to_device(isp_ccdc);
3342 +       u32 colptn = ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
3343 +               ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
3344 +               ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
3345 +               ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
3346 +               ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
3347 +               ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
3348 +               ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
3349 +               ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
3350 +               ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
3351 +               ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
3352 +               ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
3353 +               ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
3354 +               ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
3355 +               ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
3356 +               ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
3357 +               ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
3358 +
3359 +       syn_mode = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
3360 +
3361 +       switch (pipe->ccdc_out) {
3362 +       case CCDC_YUV_RSZ:
3363 +               syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
3364 +               syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
3365 +               break;
3366 +
3367 +       case CCDC_YUV_MEM_RSZ:
3368 +               syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
3369 +               isp_ccdc->wen = 1;
3370 +               syn_mode |= ISPCCDC_SYN_MODE_WEN;
3371 +               break;
3372 +
3373 +       case CCDC_OTHERS_VP:
3374 +               syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
3375 +               syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
3376 +               syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
3377 +               vpcfg.bitshift_sel = BIT9_0;
3378 +               vpcfg.freq_sel = PIXCLKBY2;
3379 +               ispccdc_config_vp(isp_ccdc, vpcfg);
3380 +               ispccdc_enable_vp(isp_ccdc, 1);
3381 +               break;
3382 +
3383 +       case CCDC_OTHERS_MEM:
3384 +               syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
3385 +               syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
3386 +               syn_mode |= ISPCCDC_SYN_MODE_WEN;
3387 +               syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
3388 +               isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
3389 +                           ~ISPCCDC_CFG_WENLOG);
3390 +               vpcfg.bitshift_sel = BIT11_2;
3391 +               vpcfg.freq_sel = PIXCLKBY2;
3392 +               ispccdc_config_vp(isp_ccdc, vpcfg);
3393 +               ispccdc_enable_vp(isp_ccdc, 0);
3394 +               break;
3395  
3396 -       isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW,
3397 -                      ~ISPCCDC_ALAW_CCDTBL,
3398 -                      enable ? ISPCCDC_ALAW_CCDTBL : 0);
3399 -}
3400 +       case CCDC_OTHERS_VP_MEM:
3401 +               syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
3402 +               syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
3403 +               syn_mode |= ISPCCDC_SYN_MODE_WEN;
3404 +               syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
3405  
3406 -/**
3407 - * ispccdc_config_imgattr - Configures the sensor image specific attributes.
3408 - * @colptn: Color pattern of the sensor.
3409 - **/
3410 -void ispccdc_config_imgattr(struct isp_ccdc_device *isp_ccdc, u32 colptn)
3411 -{
3412 -       struct device *dev = to_device(isp_ccdc);
3413 +               isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
3414 +                              ~ISPCCDC_CFG_WENLOG, isp_ccdc->wenlog);
3415 +               vpcfg.bitshift_sel = BIT9_0;
3416 +               vpcfg.freq_sel = PIXCLKBY2;
3417 +               ispccdc_config_vp(isp_ccdc, vpcfg);
3418 +               ispccdc_enable_vp(isp_ccdc, 1);
3419 +               break;
3420 +       default:
3421 +               DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output\n");
3422 +               return -EINVAL;
3423 +       };
3424  
3425 -       isp_reg_writel(dev, colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
3426 -}
3427 +       isp_reg_writel(dev, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
3428  
3429 -void ispccdc_config_shadow_registers(struct isp_ccdc_device *isp_ccdc)
3430 -{
3431 -       if (isp_ccdc->lsc_enable) {
3432 -               ispccdc_enable_lsc(isp_ccdc, 1);
3433 -               isp_ccdc->lsc_enable = 0;
3434 +       switch (pipe->ccdc_in) {
3435 +       case CCDC_RAW:
3436 +               syncif.ccdc_mastermode = 0;
3437 +               syncif.datapol = 0;
3438 +               syncif.datsz = DAT10;
3439 +               syncif.fldmode = 0;
3440 +               syncif.fldout = 0;
3441 +               syncif.fldpol = 0;
3442 +               syncif.fldstat = 0;
3443 +               syncif.hdpol = 0;
3444 +               syncif.ipmod = RAW;
3445 +               syncif.vdpol = 0;
3446 +               ispccdc_config_sync_if(isp_ccdc, syncif);
3447 +               ispccdc_config_imgattr(isp_ccdc, colptn);
3448 +               blkcfg.oblen = 0;
3449 +               blkcfg.dcsubval = 64;
3450 +               ispccdc_config_black_clamp(isp_ccdc, blkcfg);
3451 +               break;
3452 +       case CCDC_YUV_SYNC:
3453 +               syncif.ccdc_mastermode = 0;
3454 +               syncif.datapol = 0;
3455 +               syncif.datsz = DAT8;
3456 +               syncif.fldmode = 0;
3457 +               syncif.fldout = 0;
3458 +               syncif.fldpol = 0;
3459 +               syncif.fldstat = 0;
3460 +               syncif.hdpol = 0;
3461 +               syncif.ipmod = YUV16;
3462 +               syncif.vdpol = 1;
3463 +               ispccdc_config_imgattr(isp_ccdc, 0);
3464 +               ispccdc_config_sync_if(isp_ccdc, syncif);
3465 +               blkcfg.oblen = 0;
3466 +               blkcfg.dcsubval = 0;
3467 +               ispccdc_config_black_clamp(isp_ccdc, blkcfg);
3468 +               break;
3469 +       case CCDC_YUV_BT:
3470 +               break;
3471 +       case CCDC_OTHERS:
3472 +               break;
3473 +       default:
3474 +               DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Input\n");
3475 +               return -EINVAL;
3476         }
3477 +
3478 +       ispccdc_print_status(isp_ccdc, pipe);
3479 +       isp_print_status(dev);
3480 +       return 0;
3481  }
3482  
3483  /**
3484 @@ -1199,156 +1097,339 @@ int ispccdc_s_pipeline(struct isp_ccdc_d
3485                                OMAP3_ISP_IOMEM_CCDC,
3486                                ISPCCDC_VP_OUT);
3487  
3488 -       if (is_isplsc_activated()) {
3489 -               if (pipe->ccdc_in == CCDC_RAW) {
3490 -                       ispccdc_config_lsc(isp_ccdc, &isp_ccdc->lsc_config);
3491 -                       ispccdc_load_lsc(isp_ccdc, isp_ccdc->lsc_gain_table,
3492 -                                        isp_ccdc->lsc_config.size);
3493 -               }
3494 -       }
3495 +       ispccdc_setup_lsc(isp_ccdc, pipe);
3496  
3497         return 0;
3498  }
3499  
3500  /**
3501 - * ispccdc_config_outlineoffset - Configures the output line offset
3502 - * @offset: Must be twice the Output width and aligned on 32 byte boundary
3503 - * @oddeven: Specifies the odd/even line pattern to be chosen to store the
3504 - *           output.
3505 - * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
3506 - *
3507 - * - Configures the output line offset when stored in memory
3508 - * - Sets the odd/even line pattern to store the output
3509 - *    (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
3510 - * - Configures the number of even and odd line fields in case of rearranging
3511 - * the lines.
3512 + * ispccdc_enable - Enables the CCDC module.
3513 + * @enable: 0 Disables CCDC, 1 Enables CCDC
3514   *
3515 - * Returns 0 if successful, or -EINVAL if the offset is not in 32 byte
3516 - * boundary.
3517 + * Client should configure all the sub modules in CCDC before this.
3518   **/
3519 -int ispccdc_config_outlineoffset(struct isp_ccdc_device *isp_ccdc, u32 offset,
3520 -                                u8 oddeven, u8 numlines)
3521 +void ispccdc_enable(struct isp_ccdc_device *isp_ccdc, u8 enable)
3522 +{
3523 +       struct isp_device *isp = to_isp_device(isp_ccdc);
3524 +       int enable_lsc;
3525 +
3526 +       enable_lsc = enable &&
3527 +                    isp->pipeline.ccdc_in == CCDC_RAW &&
3528 +                    isp_ccdc->lsc_request_enable &&
3529 +                    ispccdc_validate_config_lsc(isp_ccdc,
3530 +                               &isp_ccdc->lsc_config, &isp->pipeline) == 0;
3531 +       ispccdc_enable_lsc(isp_ccdc, enable_lsc);
3532 +       isp_reg_and_or(isp->dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR,
3533 +                      ~ISPCCDC_PCR_EN, enable ? ISPCCDC_PCR_EN : 0);
3534 +}
3535 +
3536 +/*
3537 + * Returns zero if the CCDC is idle and the image has been written to
3538 + * memory, too.
3539 + */
3540 +int ispccdc_sbl_busy(void *_isp_ccdc)
3541  {
3542 +       struct isp_ccdc_device *isp_ccdc = _isp_ccdc;
3543         struct device *dev = to_device(isp_ccdc);
3544  
3545 -       if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
3546 -               isp_reg_writel(dev, (offset & 0xFFFF),
3547 -                              OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF);
3548 -       } else {
3549 -               DPRINTK_ISPCCDC("ISP_ERR : Offset should be in 32 byte"
3550 -                               " boundary\n");
3551 +       return ispccdc_busy(isp_ccdc)
3552 +               | (isp_reg_readl(dev, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) &
3553 +                  ISPSBL_CCDC_WR_0_DATA_READY)
3554 +               | (isp_reg_readl(dev, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) &
3555 +                  ISPSBL_CCDC_WR_0_DATA_READY)
3556 +               | (isp_reg_readl(dev, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) &
3557 +                  ISPSBL_CCDC_WR_0_DATA_READY)
3558 +               | (isp_reg_readl(dev, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) &
3559 +                  ISPSBL_CCDC_WR_0_DATA_READY);
3560 +}
3561 +
3562 +/**
3563 + * ispccdc_busy - Gets busy state of the CCDC.
3564 + **/
3565 +int ispccdc_busy(struct isp_ccdc_device *isp_ccdc)
3566 +{
3567 +       struct device *dev = to_device(isp_ccdc);
3568 +
3569 +       return isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
3570 +               ISPCCDC_PCR_BUSY;
3571 +}
3572 +
3573 +void ispccdc_config_shadow_registers(struct isp_ccdc_device *isp_ccdc)
3574 +{
3575 +       unsigned long flags;
3576 +
3577 +       spin_lock_irqsave(&isp_ccdc->lock, flags);
3578 +       if (isp_ccdc->shadow_update)
3579 +               goto out;
3580 +
3581 +#if 0  /* FIXME: Do not support on-the-fly-LSC configuration yet */
3582 +       if (isp_ccdc->update_lsc_config) {
3583 +               ispccdc_config_lsc(isp_ccdc);
3584 +               ispccdc_enable_lsc(isp_ccdc, isp_ccdc->lsc_request_enable);
3585 +               isp_ccdc->update_lsc_config = 0;
3586 +       }
3587 +
3588 +       if (isp_ccdc->update_lsc_table) {
3589 +               u32 n = isp_ccdc->lsc_table_new;
3590 +               /* Swap tables--no need to vfree in interrupt context */
3591 +               isp_ccdc->lsc_table_new = isp_ccdc->lsc_table_inuse;
3592 +               isp_ccdc->lsc_table_inuse = n;
3593 +               ispccdc_program_lsc(isp_ccdc);
3594 +               isp_ccdc->update_lsc_table = 0;
3595 +       }
3596 +#endif
3597 +
3598 +out:
3599 +       spin_unlock_irqrestore(&isp_ccdc->lock, flags);
3600 +}
3601 +
3602 +/**
3603 + * ispccdc_config - Sets CCDC configuration from userspace
3604 + * @userspace_add: Structure containing CCDC configuration sent from userspace.
3605 + *
3606 + * Returns 0 if successful, -EINVAL if the pointer to the configuration
3607 + * structure is null, or the copy_from_user function fails to copy user space
3608 + * memory to kernel space memory.
3609 + **/
3610 +int ispccdc_config(struct isp_ccdc_device *isp_ccdc,
3611 +                            void *userspace_add)
3612 +{
3613 +       struct isp_device *isp = to_isp_device(isp_ccdc);
3614 +       struct ispccdc_bclamp bclamp_t;
3615 +       struct ispccdc_blcomp blcomp_t;
3616 +       struct ispccdc_fpc fpc_t;
3617 +       struct ispccdc_culling cull_t;
3618 +       struct ispccdc_update_config *ccdc_struct;
3619 +       unsigned long flags;
3620 +       int ret = 0;
3621 +
3622 +       if (userspace_add == NULL)
3623                 return -EINVAL;
3624 +
3625 +       ccdc_struct = userspace_add;
3626 +
3627 +       spin_lock_irqsave(&isp_ccdc->lock, flags);
3628 +       isp_ccdc->shadow_update = 1;
3629 +       spin_unlock_irqrestore(&isp_ccdc->lock, flags);
3630 +
3631 +       if (ISP_ABS_CCDC_ALAW & ccdc_struct->flag) {
3632 +               if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
3633 +                       ispccdc_config_alaw(isp_ccdc, ccdc_struct->alawip);
3634 +               ispccdc_enable_alaw(isp_ccdc, 1);
3635 +       } else if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
3636 +               ispccdc_enable_alaw(isp_ccdc, 0);
3637 +
3638 +       if (ISP_ABS_CCDC_LPF & ccdc_struct->flag)
3639 +               ispccdc_enable_lpf(isp_ccdc, 1);
3640 +       else
3641 +               ispccdc_enable_lpf(isp_ccdc, 0);
3642 +
3643 +       if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->flag) {
3644 +               if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
3645 +                       if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
3646 +                                          ccdc_struct->bclamp,
3647 +                                          sizeof(struct ispccdc_bclamp))) {
3648 +                               ret = -EFAULT;
3649 +                               goto out;
3650 +                       }
3651 +
3652 +                       ispccdc_enable_black_clamp(isp_ccdc, 1);
3653 +                       ispccdc_config_black_clamp(isp_ccdc, bclamp_t);
3654 +               } else
3655 +                       ispccdc_enable_black_clamp(isp_ccdc, 1);
3656 +       } else {
3657 +               if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
3658 +                       if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
3659 +                                          ccdc_struct->bclamp,
3660 +                                          sizeof(struct ispccdc_bclamp))) {
3661 +                               ret = -EFAULT;
3662 +                               goto out;
3663 +                       }
3664 +
3665 +                       ispccdc_enable_black_clamp(isp_ccdc, 0);
3666 +                       ispccdc_config_black_clamp(isp_ccdc, bclamp_t);
3667 +               }
3668 +       }
3669 +
3670 +       if (ISP_ABS_CCDC_BCOMP & ccdc_struct->update) {
3671 +               if (copy_from_user(&blcomp_t, (struct ispccdc_blcomp *)
3672 +                                  ccdc_struct->blcomp,
3673 +                                  sizeof(blcomp_t))) {
3674 +                               ret = -EFAULT;
3675 +                               goto out;
3676 +                       }
3677 +
3678 +               ispccdc_config_black_comp(isp_ccdc, blcomp_t);
3679 +       }
3680 +
3681 +       if (ISP_ABS_CCDC_FPC & ccdc_struct->flag) {
3682 +               if (ISP_ABS_CCDC_FPC & ccdc_struct->update) {
3683 +                       if (copy_from_user(&fpc_t, (struct ispccdc_fpc *)
3684 +                                          ccdc_struct->fpc,
3685 +                                          sizeof(fpc_t))) {
3686 +                               ret = -EFAULT;
3687 +                               goto out;
3688 +                       }
3689 +                       isp_ccdc->fpc_table_add = kmalloc(64 + fpc_t.fpnum * 4,
3690 +                                               GFP_KERNEL | GFP_DMA);
3691 +                       if (!isp_ccdc->fpc_table_add) {
3692 +                               ret = -ENOMEM;
3693 +                               goto out;
3694 +                       }
3695 +                       while (((unsigned long)isp_ccdc->fpc_table_add
3696 +                               & 0xFFFFFFC0)
3697 +                              != (unsigned long)isp_ccdc->fpc_table_add)
3698 +                               isp_ccdc->fpc_table_add++;
3699 +
3700 +                       isp_ccdc->fpc_table_add_m = iommu_kmap(
3701 +                               isp->iommu,
3702 +                               0,
3703 +                               virt_to_phys(isp_ccdc->fpc_table_add),
3704 +                               fpc_t.fpnum * 4,
3705 +                               IOMMU_FLAG);
3706 +                       /* FIXME: Correct unwinding */
3707 +                       BUG_ON(IS_ERR_VALUE(isp_ccdc->fpc_table_add_m));
3708 +
3709 +                       if (copy_from_user(isp_ccdc->fpc_table_add,
3710 +                                          (u32 *)fpc_t.fpcaddr,
3711 +                                          fpc_t.fpnum * 4)) {
3712 +                               ret = -EFAULT;
3713 +                               goto out;
3714 +                       }
3715 +
3716 +                       fpc_t.fpcaddr = isp_ccdc->fpc_table_add_m;
3717 +                       ispccdc_config_fpc(isp_ccdc, fpc_t);
3718 +               }
3719 +               ispccdc_enable_fpc(isp_ccdc, 1);
3720 +       } else if (ISP_ABS_CCDC_FPC & ccdc_struct->update)
3721 +               ispccdc_enable_fpc(isp_ccdc, 0);
3722 +
3723 +       if (ISP_ABS_CCDC_CULL & ccdc_struct->update) {
3724 +               if (copy_from_user(&cull_t, (struct ispccdc_culling *)
3725 +                                  ccdc_struct->cull,
3726 +                                  sizeof(cull_t))) {
3727 +                       ret = -EFAULT;
3728 +                       goto out;
3729 +               }
3730 +               ispccdc_config_culling(isp_ccdc, cull_t);
3731 +       }
3732 +
3733 +       if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
3734 +               if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->flag) {
3735 +                       struct ispccdc_lsc_config cfg;
3736 +                       if (copy_from_user(&cfg, ccdc_struct->lsc_cfg,
3737 +                                          sizeof(cfg))) {
3738 +                               ret = -EFAULT;
3739 +                               goto out;
3740 +                       }
3741 +                       ret = ispccdc_validate_config_lsc(isp_ccdc, &cfg,
3742 +                                               isp->running == ISP_RUNNING ?
3743 +                                               &isp->pipeline : NULL);
3744 +                       if (ret)
3745 +                               goto out;
3746 +                       memcpy(&isp_ccdc->lsc_config, &cfg,
3747 +                              sizeof(isp_ccdc->lsc_config));
3748 +                       isp_ccdc->lsc_request_enable = 1;
3749 +               } else {
3750 +                       isp_ccdc->lsc_request_enable = 0;
3751 +               }
3752 +               isp_ccdc->update_lsc_config = 1;
3753         }
3754  
3755 -       isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3756 -                   ~ISPCCDC_SDOFST_FINV);
3757 +       if (ISP_ABS_TBL_LSC & ccdc_struct->update) {
3758 +               void *n;
3759 +               if (isp_ccdc->lsc_table_new != PTR_FREE)
3760 +                       iommu_vfree(isp->iommu, isp_ccdc->lsc_table_new);
3761 +               isp_ccdc->lsc_table_new = iommu_vmalloc(isp->iommu, 0,
3762 +                                       isp_ccdc->lsc_config.size, IOMMU_FLAG);
3763 +               if (IS_ERR_VALUE(isp_ccdc->lsc_table_new)) {
3764 +                       /* Disable LSC if table can not be allocated */
3765 +                       isp_ccdc->lsc_table_new = PTR_FREE;
3766 +                       isp_ccdc->lsc_request_enable = 0;
3767 +                       isp_ccdc->update_lsc_config = 1;
3768 +                       ret = -ENOMEM;
3769 +                       goto out;
3770 +               }
3771 +               n = da_to_va(isp->iommu, isp_ccdc->lsc_table_new);
3772 +               if (copy_from_user(n, ccdc_struct->lsc,
3773 +                                  isp_ccdc->lsc_config.size)) {
3774 +                       ret = -EFAULT;
3775 +                       goto out;
3776 +               }
3777 +               isp_ccdc->update_lsc_table = 1;
3778 +       }
3779  
3780 -       isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3781 -                   ~ISPCCDC_SDOFST_FOFST_4L);
3782 +       if (isp->running == ISP_STOPPED &&
3783 +           (isp_ccdc->update_lsc_table || isp_ccdc->update_lsc_config))
3784 +               ispccdc_setup_lsc(isp_ccdc, &isp->pipeline);
3785  
3786 -       switch (oddeven) {
3787 -       case EVENEVEN:
3788 -               isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3789 -                          (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
3790 -               break;
3791 -       case ODDEVEN:
3792 -               isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3793 -                          (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
3794 -               break;
3795 -       case EVENODD:
3796 -               isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3797 -                          (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
3798 -               break;
3799 -       case ODDODD:
3800 -               isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3801 -                          (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
3802 -               break;
3803 -       default:
3804 -               break;
3805 -       }
3806 -       return 0;
3807 +       if (ISP_ABS_CCDC_COLPTN & ccdc_struct->update)
3808 +               ispccdc_config_imgattr(isp_ccdc, ccdc_struct->colptn);
3809 +
3810 +out:
3811 +       if (ret == -EFAULT)
3812 +               dev_err(to_device(isp_ccdc),
3813 +                       "ccdc: user provided bad configuration data address");
3814 +
3815 +       if (ret == -ENOMEM)
3816 +               dev_err(to_device(isp_ccdc),
3817 +                       "ccdc: can not allocate memory");
3818 +
3819 +       isp_ccdc->shadow_update = 0;
3820 +       return ret;
3821  }
3822  
3823  /**
3824 - * ispccdc_set_outaddr - Sets the memory address where the output will be saved
3825 - * @addr: 32-bit memory address aligned on 32 byte boundary.
3826 + * ispccdc_request - Reserves the CCDC module.
3827   *
3828 - * Sets the memory address where the output will be saved.
3829 + * Reserves the CCDC module and assures that is used only once at a time.
3830   *
3831 - * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
3832 - * boundary.
3833 + * Returns 0 if successful, or -EBUSY if CCDC module is busy.
3834   **/
3835 -int ispccdc_set_outaddr(struct isp_ccdc_device *isp_ccdc, u32 addr)
3836 +int ispccdc_request(struct isp_ccdc_device *isp_ccdc)
3837  {
3838         struct device *dev = to_device(isp_ccdc);
3839  
3840 -       if ((addr & ISP_32B_BOUNDARY_BUF) == addr) {
3841 -               isp_reg_writel(dev, addr, OMAP3_ISP_IOMEM_CCDC,
3842 -                              ISPCCDC_SDR_ADDR);
3843 -               return 0;
3844 -       } else {
3845 -               DPRINTK_ISPCCDC("ISP_ERR : Address should be in 32 byte"
3846 -                               " boundary\n");
3847 -               return -EINVAL;
3848 +       mutex_lock(&isp_ccdc->mutexlock);
3849 +       if (isp_ccdc->ccdc_inuse) {
3850 +               mutex_unlock(&isp_ccdc->mutexlock);
3851 +               DPRINTK_ISPCCDC("ISP_ERR : CCDC Module Busy\n");
3852 +               return -EBUSY;
3853         }
3854  
3855 +       isp_ccdc->ccdc_inuse = 1;
3856 +       mutex_unlock(&isp_ccdc->mutexlock);
3857 +       isp_reg_or(dev, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
3858 +                  ISPCTRL_CCDC_RAM_EN | ISPCTRL_CCDC_CLK_EN |
3859 +                  ISPCTRL_SBL_WR1_RAM_EN);
3860 +       isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
3861 +                  ISPCCDC_CFG_VDLC);
3862 +       return 0;
3863  }
3864  
3865  /**
3866 - * ispccdc_enable - Enables the CCDC module.
3867 - * @enable: 0 Disables CCDC, 1 Enables CCDC
3868 + * ispccdc_free - Frees the CCDC module.
3869   *
3870 - * Client should configure all the sub modules in CCDC before this.
3871 + * Frees the CCDC module so it can be used by another process.
3872 + *
3873 + * Returns 0 if successful, or -EINVAL if module has been already freed.
3874   **/
3875 -void ispccdc_enable(struct isp_ccdc_device *isp_ccdc, u8 enable)
3876 +int ispccdc_free(struct isp_ccdc_device *isp_ccdc)
3877  {
3878 -       struct isp_device *isp = to_isp_device(isp_ccdc);
3879 -
3880 -       if (enable) {
3881 -               if (isp_ccdc->lsc_enable
3882 -                   && isp->pipeline.ccdc_in == CCDC_RAW)
3883 -                       ispccdc_enable_lsc(isp_ccdc, 1);
3884 -
3885 -       } else {
3886 -               int lsc_enable = isp_ccdc->lsc_state;
3887 -
3888 -               ispccdc_enable_lsc(isp_ccdc, 0);
3889 -               isp_ccdc->lsc_enable = lsc_enable;
3890 +       mutex_lock(&isp_ccdc->mutexlock);
3891 +       if (!isp_ccdc->ccdc_inuse) {
3892 +               mutex_unlock(&isp_ccdc->mutexlock);
3893 +               DPRINTK_ISPCCDC("ISP_ERR: CCDC Module already freed\n");
3894 +               return -EINVAL;
3895         }
3896  
3897 -       isp_reg_and_or(isp->dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR,
3898 -                      ~ISPCCDC_PCR_EN, enable ? ISPCCDC_PCR_EN : 0);
3899 -}
3900 -
3901 -/*
3902 - * Returns zero if the CCDC is idle and the image has been written to
3903 - * memory, too.
3904 - */
3905 -int ispccdc_sbl_busy(void *_isp_ccdc)
3906 -{
3907 -       struct isp_ccdc_device *isp_ccdc = _isp_ccdc;
3908 -       struct device *dev = to_device(isp_ccdc);
3909 -
3910 -       return ispccdc_busy(isp_ccdc)
3911 -               | (isp_reg_readl(dev, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) &
3912 -                  ISPSBL_CCDC_WR_0_DATA_READY)
3913 -               | (isp_reg_readl(dev, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) &
3914 -                  ISPSBL_CCDC_WR_0_DATA_READY)
3915 -               | (isp_reg_readl(dev, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) &
3916 -                  ISPSBL_CCDC_WR_0_DATA_READY)
3917 -               | (isp_reg_readl(dev, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) &
3918 -                  ISPSBL_CCDC_WR_0_DATA_READY);
3919 -}
3920 -
3921 -/**
3922 - * ispccdc_busy - Gets busy state of the CCDC.
3923 - **/
3924 -int ispccdc_busy(struct isp_ccdc_device *isp_ccdc)
3925 -{
3926 -       struct device *dev = to_device(isp_ccdc);
3927 -
3928 -       return isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
3929 -               ISPCCDC_PCR_BUSY;
3930 +       isp_ccdc->ccdc_inuse = 0;
3931 +       mutex_unlock(&isp_ccdc->mutexlock);
3932 +       isp_reg_and(to_device(isp_ccdc), OMAP3_ISP_IOMEM_MAIN,
3933 +                   ISP_CTRL, ~(ISPCTRL_CCDC_CLK_EN |
3934 +                               ISPCTRL_CCDC_RAM_EN |
3935 +                               ISPCTRL_SBL_WR1_RAM_EN));
3936 +       return 0;
3937  }
3938  
3939  /**
3940 @@ -1370,129 +1451,6 @@ void ispccdc_restore_context(struct devi
3941  }
3942  
3943  /**
3944 - * ispccdc_print_status - Prints the values of the CCDC Module registers
3945 - *
3946 - * Also prints other debug information stored in the CCDC module.
3947 - **/
3948 -void ispccdc_print_status(struct isp_ccdc_device *isp_ccdc,
3949 -                         struct isp_pipeline *pipe)
3950 -{
3951 -       if (!is_ispccdc_debug_enabled())
3952 -               return;
3953 -
3954 -       DPRINTK_ISPCCDC("Module in use =%d\n", isp_ccdc->ccdc_inuse);
3955 -       DPRINTK_ISPCCDC("Accepted CCDC Input (width = %d,Height = %d)\n",
3956 -                       isp_ccdc->ccdcin_w,
3957 -                       isp_ccdc->ccdcin_h);
3958 -       DPRINTK_ISPCCDC("Accepted CCDC Output (width = %d,Height = %d)\n",
3959 -                       isp_ccdc->ccdcout_w,
3960 -                       isp_ccdc->ccdcout_h);
3961 -       DPRINTK_ISPCCDC("###CCDC PCR=0x%x\n",
3962 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
3963 -                                     ISPCCDC_PCR));
3964 -       DPRINTK_ISPCCDC("ISP_CTRL =0x%x\n",
3965 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
3966 -                                     ISP_CTRL));
3967 -       switch (pipe->ccdc_in) {
3968 -       case CCDC_RAW:
3969 -               DPRINTK_ISPCCDC("ccdc input format is CCDC_RAW\n");
3970 -               break;
3971 -       case CCDC_YUV_SYNC:
3972 -               DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_SYNC\n");
3973 -               break;
3974 -       case CCDC_YUV_BT:
3975 -               DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_BT\n");
3976 -               break;
3977 -       default:
3978 -               break;
3979 -       }
3980 -
3981 -       switch (pipe->ccdc_out) {
3982 -       case CCDC_OTHERS_VP:
3983 -               DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_VP\n");
3984 -               break;
3985 -       case CCDC_OTHERS_MEM:
3986 -               DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_MEM\n");
3987 -               break;
3988 -       case CCDC_YUV_RSZ:
3989 -               DPRINTK_ISPCCDC("ccdc output format is CCDC_YUV_RSZ\n");
3990 -               break;
3991 -       default:
3992 -               break;
3993 -       }
3994 -
3995 -       DPRINTK_ISPCCDC("###ISP_CTRL in ccdc =0x%x\n",
3996 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
3997 -                                     ISP_CTRL));
3998 -       DPRINTK_ISPCCDC("###ISP_IRQ0ENABLE in ccdc =0x%x\n",
3999 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
4000 -                                     ISP_IRQ0ENABLE));
4001 -       DPRINTK_ISPCCDC("###ISP_IRQ0STATUS in ccdc =0x%x\n",
4002 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
4003 -                                     ISP_IRQ0STATUS));
4004 -       DPRINTK_ISPCCDC("###CCDC SYN_MODE=0x%x\n",
4005 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4006 -                                     ISPCCDC_SYN_MODE));
4007 -       DPRINTK_ISPCCDC("###CCDC HORZ_INFO=0x%x\n",
4008 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4009 -                                     ISPCCDC_HORZ_INFO));
4010 -       DPRINTK_ISPCCDC("###CCDC VERT_START=0x%x\n",
4011 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4012 -                                     ISPCCDC_VERT_START));
4013 -       DPRINTK_ISPCCDC("###CCDC VERT_LINES=0x%x\n",
4014 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4015 -                                     ISPCCDC_VERT_LINES));
4016 -       DPRINTK_ISPCCDC("###CCDC CULLING=0x%x\n",
4017 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4018 -                                     ISPCCDC_CULLING));
4019 -       DPRINTK_ISPCCDC("###CCDC HSIZE_OFF=0x%x\n",
4020 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4021 -                                     ISPCCDC_HSIZE_OFF));
4022 -       DPRINTK_ISPCCDC("###CCDC SDOFST=0x%x\n",
4023 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4024 -                                     ISPCCDC_SDOFST));
4025 -       DPRINTK_ISPCCDC("###CCDC SDR_ADDR=0x%x\n",
4026 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4027 -                                     ISPCCDC_SDR_ADDR));
4028 -       DPRINTK_ISPCCDC("###CCDC CLAMP=0x%x\n",
4029 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4030 -                                     ISPCCDC_CLAMP));
4031 -       DPRINTK_ISPCCDC("###CCDC COLPTN=0x%x\n",
4032 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4033 -                                     ISPCCDC_COLPTN));
4034 -       DPRINTK_ISPCCDC("###CCDC CFG=0x%x\n",
4035 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4036 -                                     ISPCCDC_CFG));
4037 -       DPRINTK_ISPCCDC("###CCDC VP_OUT=0x%x\n",
4038 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4039 -                                     ISPCCDC_VP_OUT));
4040 -       DPRINTK_ISPCCDC("###CCDC_SDR_ADDR= 0x%x\n",
4041 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4042 -                                     ISPCCDC_SDR_ADDR));
4043 -       DPRINTK_ISPCCDC("###CCDC FMTCFG=0x%x\n",
4044 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4045 -                                     ISPCCDC_FMTCFG));
4046 -       DPRINTK_ISPCCDC("###CCDC FMT_HORZ=0x%x\n",
4047 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4048 -                                     ISPCCDC_FMT_HORZ));
4049 -       DPRINTK_ISPCCDC("###CCDC FMT_VERT=0x%x\n",
4050 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4051 -                                     ISPCCDC_FMT_VERT));
4052 -       DPRINTK_ISPCCDC("###CCDC LSC_CONFIG=0x%x\n",
4053 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4054 -                                     ISPCCDC_LSC_CONFIG));
4055 -       DPRINTK_ISPCCDC("###CCDC LSC_INIT=0x%x\n",
4056 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4057 -                                     ISPCCDC_LSC_INITIAL));
4058 -       DPRINTK_ISPCCDC("###CCDC LSC_TABLE BASE=0x%x\n",
4059 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4060 -                                     ISPCCDC_LSC_TABLE_BASE));
4061 -       DPRINTK_ISPCCDC("###CCDC LSC TABLE OFFSET=0x%x\n",
4062 -                       isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4063 -                                     ISPCCDC_LSC_TABLE_OFFSET));
4064 -}
4065 -
4066 -/**
4067   * isp_ccdc_init - CCDC module initialization.
4068   *
4069   * Always returns 0
4070 @@ -1501,24 +1459,34 @@ int __init isp_ccdc_init(struct device *
4071  {
4072         struct isp_device *isp = dev_get_drvdata(dev);
4073         struct isp_ccdc_device *isp_ccdc = &isp->isp_ccdc;
4074 +       void *p;
4075  
4076         isp_ccdc->ccdc_inuse = 0;
4077         ispccdc_config_crop(isp_ccdc, 0, 0, 0, 0);
4078         mutex_init(&isp_ccdc->mutexlock);
4079  
4080 -       if (is_isplsc_activated()) {
4081 -               isp_ccdc->lsc_gain_table_tmp = kmalloc(LSC_TABLE_INIT_SIZE,
4082 -                                                      GFP_KERNEL | GFP_DMA);
4083 -               memset(isp_ccdc->lsc_gain_table_tmp, 0x40, LSC_TABLE_INIT_SIZE);
4084 -               isp_ccdc->lsc_config.initial_x = 0;
4085 -               isp_ccdc->lsc_config.initial_y = 0;
4086 -               isp_ccdc->lsc_config.gain_mode_n = 0x6;
4087 -               isp_ccdc->lsc_config.gain_mode_m = 0x6;
4088 -               isp_ccdc->lsc_config.gain_format = 0x4;
4089 -               isp_ccdc->lsc_config.offset = 0x60;
4090 -               isp_ccdc->lsc_config.size = LSC_TABLE_INIT_SIZE;
4091 -               isp_ccdc->lsc_enable = 1;
4092 -       }
4093 +       isp_ccdc->update_lsc_config = 0;
4094 +       isp_ccdc->lsc_request_enable = 1;
4095 +
4096 +       isp_ccdc->lsc_config.initial_x = 0;
4097 +       isp_ccdc->lsc_config.initial_y = 0;
4098 +       isp_ccdc->lsc_config.gain_mode_n = 0x6;
4099 +       isp_ccdc->lsc_config.gain_mode_m = 0x6;
4100 +       isp_ccdc->lsc_config.gain_format = 0x4;
4101 +       isp_ccdc->lsc_config.offset = 0x60;
4102 +       isp_ccdc->lsc_config.size = LSC_TABLE_INIT_SIZE;
4103 +
4104 +       isp_ccdc->update_lsc_table = 0;
4105 +       isp_ccdc->lsc_table_new = PTR_FREE;
4106 +       isp_ccdc->lsc_table_inuse = iommu_vmalloc(isp->iommu, 0,
4107 +                                       LSC_TABLE_INIT_SIZE, IOMMU_FLAG);
4108 +       if (IS_ERR_VALUE(isp_ccdc->lsc_table_inuse))
4109 +               return -ENOMEM;
4110 +       p = da_to_va(isp->iommu, isp_ccdc->lsc_table_inuse);
4111 +       memset(p, 0x40, LSC_TABLE_INIT_SIZE);
4112 +
4113 +       isp_ccdc->shadow_update = 0;
4114 +       spin_lock_init(&isp_ccdc->lock);
4115  
4116         return 0;
4117  }
4118 @@ -1531,10 +1499,9 @@ void isp_ccdc_cleanup(struct device *dev
4119         struct isp_device *isp = dev_get_drvdata(dev);
4120         struct isp_ccdc_device *isp_ccdc = &isp->isp_ccdc;
4121  
4122 -       if (is_isplsc_activated()) {
4123 -               ispccdc_free_lsc(isp_ccdc);
4124 -               kfree(isp_ccdc->lsc_gain_table_tmp);
4125 -       }
4126 +       iommu_vfree(isp->iommu, isp_ccdc->lsc_table_inuse);
4127 +       if (isp_ccdc->lsc_table_new != PTR_FREE)
4128 +               iommu_vfree(isp->iommu, isp_ccdc->lsc_table_new);
4129  
4130         if (isp_ccdc->fpc_table_add_m != 0) {
4131                 iommu_kunmap(isp->iommu, isp_ccdc->fpc_table_add_m);
4132 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/ispccdc.h kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/ispccdc.h
4133 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/ispccdc.h      2011-09-04 11:36:23.000000000 +0200
4134 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/ispccdc.h      2011-09-04 11:37:54.000000000 +0200
4135 @@ -24,8 +24,6 @@
4136  
4137  #include <mach/isp_user.h>
4138  
4139 -#define is_isplsc_activated()          1
4140 -
4141  /* Enumeration constants for CCDC input output format */
4142  enum ccdc_input {
4143         CCDC_RAW,
4144 @@ -152,6 +150,14 @@ struct ispccdc_refmt {
4145   * @syncif_ipmod: Image
4146   * @obclamp_en: Data input format.
4147   * @mutexlock: Mutex used to get access to the CCDC.
4148 + * @update_lsc_config: Set when user changes lsc_config
4149 + * @lsc_request_enable: Whether LSC is requested to be enabled
4150 + * @lsc_config: LSC config set by user
4151 + * @update_lsc_table: Set when user provides a new LSC table to lsc_table_new
4152 + * @lsc_table_new: LSC table set by user, ISP address
4153 + * @lsc_table_inuse: LSC table currently in use, ISP address
4154 + * @shadow_update: non-zero when user is updating CCDC configuration
4155 + * @lock: serializes shadow_update with interrupt handler
4156   */
4157  struct isp_ccdc_device {
4158         u8 ccdc_inuse;
4159 @@ -166,102 +172,39 @@ struct isp_ccdc_device {
4160         u8 ccdcslave;
4161         u8 syncif_ipmod;
4162         u8 obclamp_en;
4163 -       u8 lsc_enable;
4164 -       u8 lsc_initialized;
4165 -       int lsc_state;
4166         struct mutex mutexlock; /* For checking/modifying ccdc_inuse */
4167         u32 wenlog;
4168 -       u8 *lsc_gain_table_tmp;
4169 -       unsigned long lsc_ispmmu_addr;
4170 -       u8 *lsc_gain_table;
4171 -       struct ispccdc_lsc_config lsc_config;
4172         unsigned long fpc_table_add_m;
4173         u32 *fpc_table_add;
4174 -};
4175 -
4176 -int ispccdc_request(struct isp_ccdc_device *isp_ccdc);
4177 -
4178 -int ispccdc_free(struct isp_ccdc_device *isp_ccdc);
4179 -
4180 -void ispccdc_config_crop(struct isp_ccdc_device *isp_ccdc, u32 left, u32 top,
4181 -                        u32 height, u32 width);
4182 -
4183 -void ispccdc_config_sync_if(struct isp_ccdc_device *isp_ccdc,
4184 -                           struct ispccdc_syncif syncif);
4185 -
4186 -int ispccdc_config_black_clamp(struct isp_ccdc_device *isp_ccdc,
4187 -                              struct ispccdc_bclamp bclamp);
4188 -
4189 -void ispccdc_enable_black_clamp(struct isp_ccdc_device *isp_ccdc, u8 enable);
4190 -
4191 -int ispccdc_config_fpc(struct isp_ccdc_device *isp_ccdc,
4192 -                      struct ispccdc_fpc fpc);
4193 -
4194 -void ispccdc_enable_fpc(struct isp_ccdc_device *isp_ccdc, u8 enable);
4195  
4196 -void ispccdc_config_black_comp(struct isp_ccdc_device *isp_ccdc,
4197 -                              struct ispccdc_blcomp blcomp);
4198 -
4199 -void ispccdc_config_vp(struct isp_ccdc_device *isp_ccdc, struct ispccdc_vp vp);
4200 -
4201 -void ispccdc_enable_vp(struct isp_ccdc_device *isp_ccdc, u8 enable);
4202 -
4203 -void ispccdc_config_reformatter(struct isp_ccdc_device *isp_ccdc,
4204 -                               struct ispccdc_refmt refmt);
4205 -
4206 -void ispccdc_enable_reformatter(struct isp_ccdc_device *isp_ccdc, u8 enable);
4207 -
4208 -void ispccdc_config_culling(struct isp_ccdc_device *isp_ccdc,
4209 -                           struct ispccdc_culling culling);
4210 -
4211 -void ispccdc_enable_lpf(struct isp_ccdc_device *isp_ccdc, u8 enable);
4212 -
4213 -void ispccdc_config_alaw(struct isp_ccdc_device *isp_ccdc,
4214 -                        enum alaw_ipwidth ipwidth);
4215 -
4216 -void ispccdc_enable_alaw(struct isp_ccdc_device *isp_ccdc, u8 enable);
4217 -
4218 -int ispccdc_load_lsc(struct isp_ccdc_device *isp_ccdc, u8 *table_addr,
4219 -                    u32 table_size);
4220 -
4221 -void ispccdc_config_lsc(struct isp_ccdc_device *isp_ccdc,
4222 -                       struct ispccdc_lsc_config *lsc_cfg);
4223 +       /* LSC related fields */
4224 +       u8 update_lsc_config;
4225 +       u8 lsc_request_enable;
4226 +       struct ispccdc_lsc_config lsc_config;
4227 +       u8 update_lsc_table;
4228 +       u32 lsc_table_new;
4229 +       u32 lsc_table_inuse;
4230  
4231 -void ispccdc_enable_lsc(struct isp_ccdc_device *isp_ccdc, u8 enable);
4232 +       int shadow_update;
4233 +       spinlock_t lock;
4234 +};
4235  
4236  void ispccdc_lsc_error_handler(struct isp_ccdc_device *isp_ccdc);
4237 -
4238 -void ispccdc_config_imgattr(struct isp_ccdc_device *isp_ccdc, u32 colptn);
4239 -
4240 -void ispccdc_config_shadow_registers(struct isp_ccdc_device *isp_ccdc);
4241 -
4242 +int ispccdc_set_outaddr(struct isp_ccdc_device *isp_ccdc, u32 addr);
4243 +void ispccdc_set_wenlog(struct isp_ccdc_device *isp_ccdc, u32 wenlog);
4244  int ispccdc_try_pipeline(struct isp_ccdc_device *isp_ccdc,
4245                          struct isp_pipeline *pipe);
4246 -
4247  int ispccdc_s_pipeline(struct isp_ccdc_device *isp_ccdc,
4248                        struct isp_pipeline *pipe);
4249 -
4250 -int ispccdc_config_outlineoffset(struct isp_ccdc_device *isp_ccdc, u32 offset,
4251 -                                u8 oddeven, u8 numlines);
4252 -
4253 -int ispccdc_set_outaddr(struct isp_ccdc_device *isp_ccdc, u32 addr);
4254 -
4255  void ispccdc_enable(struct isp_ccdc_device *isp_ccdc, u8 enable);
4256 -
4257  int ispccdc_sbl_busy(void *_isp_ccdc);
4258 -
4259  int ispccdc_busy(struct isp_ccdc_device *isp_ccdc);
4260 -
4261 +void ispccdc_config_shadow_registers(struct isp_ccdc_device *isp_ccdc);
4262 +int ispccdc_config(struct isp_ccdc_device *isp_ccdc,
4263 +                            void *userspace_add);
4264 +int ispccdc_request(struct isp_ccdc_device *isp_ccdc);
4265 +int ispccdc_free(struct isp_ccdc_device *isp_ccdc);
4266  void ispccdc_save_context(struct device *dev);
4267 -
4268  void ispccdc_restore_context(struct device *dev);
4269  
4270 -void ispccdc_print_status(struct isp_ccdc_device *isp_ccdc,
4271 -                         struct isp_pipeline *pipe);
4272 -
4273 -int omap34xx_isp_ccdc_config(struct isp_ccdc_device *isp_ccdc,
4274 -                            void *userspace_add);
4275 -
4276 -void ispccdc_set_wenlog(struct isp_ccdc_device *isp_ccdc, u32 wenlog);
4277 -
4278  #endif         /* OMAP_ISP_CCDC_H */
4279 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isp.h kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isp.h
4280 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isp.h  2011-09-04 11:36:23.000000000 +0200
4281 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isp.h  2011-09-04 11:37:54.000000000 +0200
4282 @@ -249,6 +249,8 @@ struct isp_bufs {
4283         int done;
4284         /* Wait for this many hs_vs before anything else. */
4285         int wait_hs_vs;
4286 +       /* Ignore statistic's interrupts until first good hs_vs. */
4287 +       int wait_stats;
4288  };
4289  
4290  /**
4291 @@ -361,7 +363,7 @@ struct isp_device {
4292         struct iommu *iommu;
4293  };
4294  
4295 -void omap34xx_isp_hist_dma_done(struct device *dev);
4296 +void isp_hist_dma_done(struct device *dev);
4297  
4298  void isp_flush(struct device *dev);
4299  
4300 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isphist.c kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isphist.c
4301 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isphist.c      2011-09-04 11:36:23.000000000 +0200
4302 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isphist.c      2011-09-04 11:37:54.000000000 +0200
4303 @@ -229,6 +229,7 @@ void isp_hist_config_registers(struct is
4304         isp_hist_dma_config(isp_hist);
4305  
4306         isp_hist->update = 0;
4307 +       isp_hist->stat.config_counter++;
4308         spin_unlock_irqrestore(&isp_hist->lock, irqflags);
4309  
4310         isp_hist_print_status(isp_hist);
4311 @@ -251,7 +252,7 @@ static void isp_hist_dma_cb(int lch, u16
4312                 isp_reg_and(dev, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
4313                             ~ISPHIST_CNT_CLR_EN);
4314                 if (!ret)
4315 -                       omap34xx_isp_hist_dma_done(dev);
4316 +                       isp_hist_dma_done(dev);
4317         }
4318         isp_hist->waiting_dma = 0;
4319  }
4320 @@ -568,8 +569,8 @@ static void isp_hist_update_params(struc
4321   *
4322   * Returns 0 on success configuration.
4323   **/
4324 -int omap34xx_isp_hist_config(struct isp_hist_device *isp_hist,
4325 -                            struct isp_hist_config *histcfg)
4326 +int isp_hist_config(struct isp_hist_device *isp_hist,
4327 +                   struct isp_hist_config *histcfg)
4328  {
4329         struct device *dev = to_device(isp_hist);
4330         unsigned long irqflags;
4331 @@ -632,15 +633,15 @@ int omap34xx_isp_hist_config(struct isp_
4332  }
4333  
4334  /**
4335 - * omap34xx_isp_hist_request_statistics - Request statistics in Histogram.
4336 + * isp_hist_request_statistics - Request statistics in Histogram.
4337   * @histdata: Pointer to data structure.
4338   *
4339   * This API allows the user to request for histogram statistics.
4340   *
4341   * Returns 0 on successful request.
4342   **/
4343 -int omap34xx_isp_hist_request_statistics(struct isp_hist_device *isp_hist,
4344 -                                        struct isp_hist_data *histdata)
4345 +int isp_hist_request_statistics(struct isp_hist_device *isp_hist,
4346 +                               struct isp_hist_data *histdata)
4347  {
4348         struct device *dev = to_device(isp_hist);
4349         struct ispstat_buffer *buf;
4350 @@ -718,17 +719,17 @@ void isp_hist_cleanup(struct device *dev
4351  }
4352  
4353  /**
4354 - * isphist_save_context - Saves the values of the histogram module registers.
4355 + * isp_hist_save_context - Saves the values of the histogram module registers.
4356   **/
4357 -void isphist_save_context(struct device *dev)
4358 +void isp_hist_save_context(struct device *dev)
4359  {
4360         isp_save_context(dev, isphist_reg_list);
4361  }
4362  
4363  /**
4364 - * isphist_restore_context - Restores the values of the histogram module regs.
4365 + * isp_hist_restore_context - Restores the values of the histogram module regs.
4366   **/
4367 -void isphist_restore_context(struct device *dev)
4368 +void isp_hist_restore_context(struct device *dev)
4369  {
4370         isp_restore_context(dev, isphist_reg_list);
4371  }
4372 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isphist.h kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isphist.h
4373 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isphist.h      2011-09-04 11:36:23.000000000 +0200
4374 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isphist.h      2011-09-04 11:37:54.000000000 +0200
4375 @@ -149,11 +149,11 @@ void isp_hist_mark_invalid_buf(struct is
4376  void isp_hist_config_registers(struct isp_hist_device *isp_hist);
4377  void isp_hist_suspend(struct isp_hist_device *isp_hist);
4378  void isp_hist_resume(struct isp_hist_device *isp_hist);
4379 -void isphist_save_context(struct device *dev);
4380 -void isphist_restore_context(struct device *dev);
4381 -int omap34xx_isp_hist_config(struct isp_hist_device *isp_hist,
4382 -                            struct isp_hist_config *histcfg);
4383 -int omap34xx_isp_hist_request_statistics(struct isp_hist_device *isp_hist,
4384 -                                        struct isp_hist_data *histdata);
4385 +void isp_hist_save_context(struct device *dev);
4386 +void isp_hist_restore_context(struct device *dev);
4387 +int isp_hist_config(struct isp_hist_device *isp_hist,
4388 +                   struct isp_hist_config *histcfg);
4389 +int isp_hist_request_statistics(struct isp_hist_device *isp_hist,
4390 +                               struct isp_hist_data *histdata);
4391  
4392  #endif                         /* OMAP_ISP_HIST */
4393 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isph3a.c kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isph3a.c
4394 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isph3a.c       2011-09-04 11:36:23.000000000 +0200
4395 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isph3a.c       2011-09-04 11:37:54.000000000 +0200
4396 @@ -194,6 +194,7 @@ void isph3a_aewb_config_registers(struct
4397  
4398         ispstat_bufs_set_size(&isp_h3a->stat, isp_h3a->buf_size);
4399         isp_h3a->update = 0;
4400 +       isp_h3a->stat.config_counter++;
4401  
4402         spin_unlock_irqrestore(isp_h3a->lock, irqflags);
4403  }
4404 @@ -404,14 +405,14 @@ static void isph3a_aewb_set_params(struc
4405  }
4406  
4407  /**
4408 - * omap34xx_isph3a_aewb_config - Configure AEWB regs, enable/disable H3A engine.
4409 + * isph3a_aewb_config - Configure AEWB regs, enable/disable H3A engine.
4410   * @aewbcfg: Pointer to AEWB config structure.
4411   *
4412   * Returns 0 if successful, -EINVAL if aewbcfg pointer is NULL, -ENOMEM if
4413   * was unable to allocate memory for the buffer, of other errors if H3A
4414   * callback is not set or the parameters for AEWB are invalid.
4415   **/
4416 -int omap34xx_isph3a_aewb_config(struct isp_h3a_device *isp_h3a,
4417 +int isph3a_aewb_config(struct isp_h3a_device *isp_h3a,
4418                                 struct isph3a_aewb_config *aewbcfg)
4419  {
4420         struct device *dev = to_device(isp_h3a);
4421 @@ -454,7 +455,7 @@ int omap34xx_isph3a_aewb_config(struct i
4422  
4423         return 0;
4424  }
4425 -EXPORT_SYMBOL(omap34xx_isph3a_aewb_config);
4426 +EXPORT_SYMBOL(isph3a_aewb_config);
4427  
4428  /**
4429   * isph3a_aewb_request_statistics - REquest statistics and update gains in AEWB
4430 @@ -467,8 +468,8 @@ EXPORT_SYMBOL(omap34xx_isph3a_aewb_confi
4431   * Returns 0 if successful, -EINVAL when H3A engine is not enabled, or other
4432   * errors when setting gains.
4433   **/
4434 -int omap34xx_isph3a_aewb_request_statistics(struct isp_h3a_device *isp_h3a,
4435 -                                           struct isph3a_aewb_data *aewbdata)
4436 +int isph3a_aewb_request_statistics(struct isp_h3a_device *isp_h3a,
4437 +                                  struct isph3a_aewb_data *aewbdata)
4438  {
4439         struct device *dev = to_device(isp_h3a);
4440         unsigned long irqflags;
4441 @@ -517,7 +518,7 @@ int omap34xx_isph3a_aewb_request_statist
4442  
4443         return ret;
4444  }
4445 -EXPORT_SYMBOL(omap34xx_isph3a_aewb_request_statistics);
4446 +EXPORT_SYMBOL(isph3a_aewb_request_statistics);
4447  
4448  /**
4449   * isph3a_aewb_init - Module Initialisation.
4450 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isph3a.h kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isph3a.h
4451 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isph3a.h       2011-09-04 11:36:23.000000000 +0200
4452 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isph3a.h       2011-09-04 11:37:54.000000000 +0200
4453 @@ -130,11 +130,11 @@ struct isp_h3a_device {
4454         struct ispstat stat;
4455  };
4456  
4457 -int omap34xx_isph3a_aewb_config(struct isp_h3a_device *isp_h3a,
4458 -                               struct isph3a_aewb_config *aewbcfg);
4459 +int isph3a_aewb_config(struct isp_h3a_device *isp_h3a,
4460 +                      struct isph3a_aewb_config *aewbcfg);
4461  
4462 -int omap34xx_isph3a_aewb_request_statistics(struct isp_h3a_device *isp_h3a,
4463 -                                           struct isph3a_aewb_data *aewbdata);
4464 +int isph3a_aewb_request_statistics(struct isp_h3a_device *isp_h3a,
4465 +                                  struct isph3a_aewb_data *aewbdata);
4466  
4467  void isph3a_save_context(struct device *dev);
4468  
4469 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isppreview.c kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isppreview.c
4470 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isppreview.c   2011-09-04 11:36:23.000000000 +0200
4471 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isppreview.c   2011-09-04 11:37:54.000000000 +0200
4472 @@ -184,17 +184,16 @@ static u32 luma_enhance_table[] = {
4473  #include "luma_enhance_table.h"
4474  };
4475  
4476 -static int omap34xx_isp_tables_update(struct isp_prev_device *isp_prev,
4477 -                               struct isptables_update *isptables_struct);
4478 +static int isppreview_tables_update(struct isp_prev_device *isp_prev,
4479 +                                   struct isptables_update *isptables_struct);
4480  
4481  
4482  /**
4483 - * omap34xx_isp_preview_config - Abstraction layer Preview configuration.
4484 + * isppreview_config - Abstraction layer Preview configuration.
4485   * @userspace_add: Pointer from Userspace to structure with flags and data to
4486   *                 update.
4487   **/
4488 -int omap34xx_isp_preview_config(struct isp_prev_device *isp_prev,
4489 -                               void *userspace_add)
4490 +int isppreview_config(struct isp_prev_device *isp_prev, void *userspace_add)
4491  {
4492         struct isp_device *isp = to_isp_device(isp_prev);
4493         struct device *dev = to_device(isp_prev);
4494 @@ -348,32 +347,26 @@ out_config_shadow:
4495         isp_table_update.prev_cfa = config->prev_cfa;
4496         isp_table_update.prev_wbal = config->prev_wbal;
4497  
4498 -       if (omap34xx_isp_tables_update(isp_prev, &isp_table_update))
4499 +       if (isppreview_tables_update(isp_prev, &isp_table_update))
4500                 goto err_copy_from_user;
4501  
4502 -       spin_lock_irqsave(&isp_prev->lock, flags);
4503         isp_prev->shadow_update = 0;
4504 -       spin_unlock_irqrestore(&isp_prev->lock, flags);
4505 -
4506         return 0;
4507  
4508  err_copy_from_user:
4509 -       spin_lock_irqsave(&isp_prev->lock, flags);
4510         isp_prev->shadow_update = 0;
4511 -       spin_unlock_irqrestore(&isp_prev->lock, flags);
4512 -
4513         dev_err(dev, "preview: Config: Copy From User Error\n");
4514         return -EFAULT;
4515  }
4516 -EXPORT_SYMBOL_GPL(omap34xx_isp_preview_config);
4517 +EXPORT_SYMBOL_GPL(isppreview_config);
4518  
4519  /**
4520 - * omap34xx_isp_tables_update - Abstraction layer Tables update.
4521 + * isppreview_tables_update - Abstraction layer Tables update.
4522   * @isptables_struct: Pointer from Userspace to structure with flags and table
4523   *                 data to update.
4524   **/
4525 -static int omap34xx_isp_tables_update(struct isp_prev_device *isp_prev,
4526 -                              struct isptables_update *isptables_struct)
4527 +static int isppreview_tables_update(struct isp_prev_device *isp_prev,
4528 +                                   struct isptables_update *isptables_struct)
4529  {
4530         struct device *dev = to_device(isp_prev);
4531  
4532 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isppreview.h kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isppreview.h
4533 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/isppreview.h   2011-09-04 11:36:23.000000000 +0200
4534 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/isppreview.h   2011-09-04 11:37:54.000000000 +0200
4535 @@ -419,8 +419,7 @@ void isppreview_restore_context(struct d
4536  static inline void isppreview_restore_context(struct device *dev) {}
4537  #endif
4538  
4539 -int omap34xx_isp_preview_config(struct isp_prev_device *isp_prev,
4540 -                               void *userspace_add);
4541 +int isppreview_config(struct isp_prev_device *isp_prev, void *userspace_add);
4542  
4543  void isppreview_set_skip(struct isp_prev_device *isp_prev, u32 h, u32 v);
4544  
4545 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/ispreg.h kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/ispreg.h
4546 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/isp/ispreg.h       2011-09-04 11:36:23.000000000 +0200
4547 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/isp/ispreg.h       2011-09-04 11:37:54.000000000 +0200
4548 @@ -1275,6 +1275,7 @@
4549  
4550  #define ISPHIST_HV_INFO_MASK                   0x3FFF3FFF
4551  
4552 +#define ISPCCDC_LSC_ENABLE                     1
4553  #define ISPCCDC_LSC_GAIN_MODE_N_MASK           0x700
4554  #define ISPCCDC_LSC_GAIN_MODE_N_SHIFT          8
4555  #define ISPCCDC_LSC_GAIN_MODE_M_MASK           0x3800
4556 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/smia-sensor.c kernel-2.6.28-20094803.3+0m5/drivers/media/video/smia-sensor.c
4557 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/smia-sensor.c      2011-09-04 11:36:23.000000000 +0200
4558 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/smia-sensor.c      2011-09-04 11:37:54.000000000 +0200
4559 @@ -38,7 +38,17 @@
4560  #include "smia-sensor.h"
4561  
4562  #define DEFAULT_XCLK           9600000         /* [Hz] */
4563 -#define DEFAULT_EXPOSURE       33946           /* [us] */
4564 +
4565 +#define SMIA_CTRL_GAIN         0
4566 +#define SMIA_CTRL_EXPOSURE     1
4567 +#define SMIA_NCTRLS            2
4568 +
4569 +#define CID_TO_CTRL(id)                ((id) == V4L2_CID_GAIN ? SMIA_CTRL_GAIN : \
4570 +                                (id) == V4L2_CID_EXPOSURE ? \
4571 +                                        SMIA_CTRL_EXPOSURE : \
4572 +                                        -EINVAL)
4573 +
4574 +#define VS6555_RESET_SHIFT_HACK        1
4575  
4576  /* Register definitions */
4577  
4578 @@ -53,6 +63,50 @@
4579  #define REG_COARSE_EXPOSURE    0x0202
4580  #define REG_ANALOG_GAIN                0x0204
4581  
4582 +struct smia_sensor;
4583 +
4584 +struct smia_sensor_type {
4585 +       u8 manufacturer_id;
4586 +       u16 model_id;
4587 +       char *name;
4588 +       int ev_table_size;
4589 +       u16 *ev_table;
4590 +};
4591 +
4592 +/* Current values for V4L2 controls */
4593 +struct smia_control {
4594 +       s32 minimum;
4595 +       s32 maximum;
4596 +       s32 step;
4597 +       s32 default_value;
4598 +       s32 value;
4599 +       int (*set)(struct smia_sensor *, s32 value);
4600 +};
4601 +
4602 +struct smia_sensor {
4603 +       struct i2c_client *i2c_client;
4604 +       struct i2c_driver driver;
4605 +
4606 +       /* Sensor information */
4607 +       struct smia_sensor_type *type;
4608 +       u8  revision_number;
4609 +       u8  smia_version;
4610 +
4611 +       /* V4L2 current control values */
4612 +       struct smia_control controls[SMIA_NCTRLS];
4613 +
4614 +       struct smia_reglist *current_reglist;
4615 +       struct v4l2_int_device *v4l2_int_device;
4616 +       struct v4l2_fract timeperframe;
4617 +
4618 +       struct smia_sensor_platform_data *platform_data;
4619 +
4620 +       const struct firmware *fw;
4621 +       struct smia_meta_reglist *meta_reglist;
4622 +
4623 +       enum v4l2_power power;
4624 +};
4625 +
4626  static int smia_ioctl_queryctrl(struct v4l2_int_device *s,
4627                                 struct v4l2_queryctrl *a);
4628  static int smia_ioctl_g_ctrl(struct v4l2_int_device *s,
4629 @@ -77,6 +131,106 @@ static int smia_ioctl_enum_frameinterval
4630                                           struct v4l2_frmivalenum *frm);
4631  static int smia_ioctl_dev_init(struct v4l2_int_device *s);
4632  
4633 +/* SMIA-model gain is stored in precalculated tables here. In the model,
4634 + * reg  = (c0-gain*c1) / (gain*m1-m0)
4635 + * gain = 2^ev
4636 + * The constants c0, m0, c1 and m1 depend on sensor.
4637 + */
4638 +
4639 +/* Analog gain table for VS6555.
4640 + * m0   = 0
4641 + * c0   = 256
4642 + * m1   = -1  (erroneously -16 in silicon)
4643 + * c1   = 256
4644 + * step = 16
4645 + */
4646 +static u16 smia_gain_vs6555[] = {
4647 +/*     reg        EV    gain     */
4648 +         0,    /* 0.0   1.00000  */
4649 +        16,    /* 0.1   1.07177  */
4650 +        32,    /* 0.2   1.14870  */
4651 +        48,    /* 0.3   1.23114  */
4652 +        64,    /* 0.4   1.31951  */
4653 +        80,    /* 0.5   1.41421  */
4654 +        80,    /* 0.6   1.51572  */
4655 +        96,    /* 0.7   1.62450  */
4656 +       112,    /* 0.8   1.74110  */
4657 +       112,    /* 0.9   1.86607  */
4658 +       128,    /* 1.0   2.00000  */
4659 +       144,    /* 1.1   2.14355  */
4660 +       144,    /* 1.2   2.29740  */
4661 +       160,    /* 1.3   2.46229  */
4662 +       160,    /* 1.4   2.63902  */
4663 +       160,    /* 1.5   2.82843  */
4664 +       176,    /* 1.6   3.03143  */
4665 +       176,    /* 1.7   3.24901  */
4666 +       176,    /* 1.8   3.48220  */
4667 +       192,    /* 1.9   3.73213  */
4668 +       192,    /* 2.0   4.00000  */
4669 +       192,    /* 2.1   4.28709  */
4670 +       208,    /* 2.2   4.59479  */
4671 +       208,    /* 2.3   4.92458  */
4672 +       208,    /* 2.4   5.27803  */
4673 +       208,    /* 2.5   5.65685  */
4674 +       208,    /* 2.6   6.06287  */
4675 +       224,    /* 2.7   6.49802  */
4676 +       224,    /* 2.8   6.96440  */
4677 +       224,    /* 2.9   7.46426  */
4678 +       224,    /* 3.0   8.00000  */
4679 +       224,    /* 3.1   8.57419  */
4680 +       224,    /* 3.2   9.18959  */
4681 +       224,    /* 3.3   9.84916  */
4682 +       224,    /* 3.4  10.55606  */
4683 +       240,    /* 3.5  11.31371  */
4684 +       240,    /* 3.6  12.12573  */
4685 +       240,    /* 3.7  12.99604  */
4686 +       240,    /* 3.8  13.92881  */
4687 +       240,    /* 3.9  14.92853  */
4688 +       240,    /* 4.0  16.00000  */
4689 +};
4690 +
4691 +/* Analog gain table for TCM8330MD.
4692 + * m0   = 1
4693 + * c0   = 0
4694 + * m1   = 0
4695 + * c1   = 36 (MMS uses 29)
4696 + * step = 1
4697 + */
4698 +static u16 smia_gain_tcm8330md[] = {
4699 +/*     reg        EV      gain     */
4700 +        36,    /* 0.0     1.00000  */
4701 +        39,    /* 0.1     1.07177  */
4702 +        41,    /* 0.2     1.14870  */
4703 +        44,    /* 0.3     1.23114  */
4704 +        48,    /* 0.4     1.31951  */
4705 +        51,    /* 0.5     1.41421  */
4706 +        55,    /* 0.6     1.51572  */
4707 +        58,    /* 0.7     1.62450  */
4708 +        63,    /* 0.8     1.74110  */
4709 +        67,    /* 0.9     1.86607  */
4710 +        72,    /* 1.0     2.00000  */
4711 +        77,    /* 1.1     2.14355  */
4712 +        83,    /* 1.2     2.29740  */
4713 +        89,    /* 1.3     2.46229  */
4714 +        95,    /* 1.4     2.63902  */
4715 +       102,    /* 1.5     2.82843  */
4716 +       109,    /* 1.6     3.03143  */
4717 +       117,    /* 1.7     3.24901  */
4718 +       125,    /* 1.8     3.48220  */
4719 +       134,    /* 1.9     3.73213  */
4720 +       144,    /* 2.0     4.00000  */
4721 +       154,    /* 2.1     4.28709  */
4722 +       165,    /* 2.2     4.59479  */
4723 +       177,    /* 2.3     4.92458  */
4724 +       190,    /* 2.4     5.27803  */
4725 +       204,    /* 2.5     5.65685  */
4726 +       218,    /* 2.6     6.06287  */
4727 +       234,    /* 2.7     6.49802  */
4728 +       251,    /* 2.8     6.96440  */
4729 +       269,    /* 2.9     7.46426  */
4730 +       288,    /* 3.0     8.00000  */
4731 +};
4732 +
4733  static struct v4l2_int_ioctl_desc smia_ioctl_desc[] = {
4734         { vidioc_int_enum_fmt_cap_num,
4735           (v4l2_int_ioctl_func *)smia_ioctl_enum_fmt_cap },
4736 @@ -125,13 +279,16 @@ static struct v4l2_int_device smia_int_d
4737         },
4738  };
4739  
4740 -static struct {
4741 -       u8 manufacturer_id;
4742 -       u16 model_id;
4743 -       char *name;
4744 -} smia_sensors[] = {
4745 -       { 0x01, 0x022b, "vs6555" },
4746 -       { 0x0c, 0x208a, "tcm8330md" },
4747 +static struct smia_sensor_type smia_sensors[] = {
4748 +       { 0, 0, "unknown", 0, NULL },
4749 +       {
4750 +               0x01, 0x022b, "vs6555",
4751 +               ARRAY_SIZE(smia_gain_vs6555), smia_gain_vs6555
4752 +       },
4753 +       {
4754 +               0x0c, 0x208a, "tcm8330md",
4755 +               ARRAY_SIZE(smia_gain_tcm8330md), smia_gain_tcm8330md
4756 +       },
4757  };
4758  
4759  static const __u32 smia_mode_ctrls[] = {
4760 @@ -198,6 +355,47 @@ static int smia_exposure_rows_to_us(stru
4761         return (smia_get_row_time(sensor) * rows + (1 << 7)) >> 8;
4762  }
4763  
4764 +/* Called to change the V4L2 gain control value. This function
4765 + * rounds and clamps the given value and updates the V4L2 control value.
4766 + * If power is on, also updates the sensor analog gain.
4767 + */
4768 +static int smia_set_gain(struct smia_sensor *sensor, s32 gain)
4769 +{
4770 +       gain = clamp(gain,
4771 +               sensor->controls[SMIA_CTRL_GAIN].minimum,
4772 +               sensor->controls[SMIA_CTRL_GAIN].maximum);
4773 +       sensor->controls[SMIA_CTRL_GAIN].value = gain;
4774 +
4775 +       if (sensor->power == V4L2_POWER_OFF)
4776 +               return 0;
4777 +
4778 +       return smia_i2c_write_reg(sensor->i2c_client,
4779 +                                 SMIA_REG_16BIT, REG_ANALOG_GAIN,
4780 +                                 sensor->type->ev_table[gain]);
4781 +}
4782 +
4783 +/* Called to change the V4L2 exposure control value. This function
4784 + * rounds and clamps the given value and updates the V4L2 control value.
4785 + * If power is on, also update the sensor exposure time.
4786 + * exptime is in microseconds.
4787 + */
4788 +static int smia_set_exposure(struct smia_sensor *sensor, s32 exptime)
4789 +{
4790 +       int exposure_rows;
4791 +
4792 +       exptime = clamp(exptime, sensor->controls[SMIA_CTRL_EXPOSURE].minimum,
4793 +                                sensor->controls[SMIA_CTRL_EXPOSURE].maximum);
4794 +
4795 +       exposure_rows = smia_exposure_us_to_rows(sensor, &exptime);
4796 +       sensor->controls[SMIA_CTRL_EXPOSURE].value = exptime;
4797 +
4798 +       if (sensor->power == V4L2_POWER_OFF)
4799 +               return 0;
4800 +
4801 +       return smia_i2c_write_reg(sensor->i2c_client,
4802 +                       SMIA_REG_16BIT, REG_COARSE_EXPOSURE, exposure_rows);
4803 +}
4804 +
4805  static int smia_stream_on(struct v4l2_int_device *s)
4806  {
4807         struct smia_sensor *sensor = s->priv;
4808 @@ -212,6 +410,37 @@ static int smia_stream_off(struct v4l2_i
4809                                   SMIA_REG_8BIT, 0x0100, 0x00);
4810  }
4811  
4812 +static int smia_update_controls(struct v4l2_int_device *s)
4813 +{
4814 +       struct smia_sensor *sensor = s->priv;
4815 +       int i;
4816 +
4817 +       sensor->controls[SMIA_CTRL_EXPOSURE].minimum = 0;
4818 +       sensor->controls[SMIA_CTRL_EXPOSURE].maximum =
4819 +               smia_exposure_rows_to_us(sensor,
4820 +                                        sensor->current_reglist->mode.max_exp);
4821 +       sensor->controls[SMIA_CTRL_EXPOSURE].step =
4822 +               smia_exposure_rows_to_us(sensor, 1);
4823 +       sensor->controls[SMIA_CTRL_EXPOSURE].default_value =
4824 +               sensor->controls[SMIA_CTRL_EXPOSURE].maximum;
4825 +       if (sensor->controls[SMIA_CTRL_EXPOSURE].value == 0)
4826 +               sensor->controls[SMIA_CTRL_EXPOSURE].value =
4827 +                       sensor->controls[SMIA_CTRL_EXPOSURE].maximum;
4828 +
4829 +       /* Adjust V4L2 control values and write them to the sensor */
4830 +
4831 +       for (i = 0; i < ARRAY_SIZE(sensor->controls); i++) {
4832 +               int rval;
4833 +               if (!sensor->controls[i].set)
4834 +                       continue;
4835 +               rval = sensor->controls[i].set(sensor,
4836 +                       sensor->controls[i].value);
4837 +               if (rval)
4838 +                       return rval;
4839 +       }
4840 +       return 0;
4841 +}
4842 +
4843  /* Must be called with power already enabled on the sensor */
4844  static int smia_configure(struct v4l2_int_device *s)
4845  {
4846 @@ -223,17 +452,6 @@ static int smia_configure(struct v4l2_in
4847         if (rval)
4848                 goto fail;
4849  
4850 -       rval = smia_i2c_write_reg(sensor->i2c_client, SMIA_REG_8BIT,
4851 -                                 REG_ANALOG_GAIN+1,
4852 -                                 sensor->ctrl_gain << 4);
4853 -       if (rval)
4854 -               goto fail;
4855 -       rval = smia_i2c_write_reg(sensor->i2c_client,
4856 -               SMIA_REG_16BIT, REG_COARSE_EXPOSURE,
4857 -               smia_exposure_us_to_rows(sensor, &sensor->ctrl_exposure));
4858 -       if (rval)
4859 -               goto fail;
4860 -
4861         /*
4862          * FIXME: remove stream_off from here as soon as camera-firmware
4863          * is modified to not enable streaming automatically.
4864 @@ -242,6 +460,10 @@ static int smia_configure(struct v4l2_in
4865         if (rval)
4866                 goto fail;
4867  
4868 +       rval = smia_update_controls(s);
4869 +       if (rval)
4870 +               goto fail;
4871 +
4872         rval = sensor->platform_data->configure_interface(
4873                 s,
4874                 sensor->current_reglist->mode.window_width,
4875 @@ -313,21 +535,13 @@ static struct v4l2_queryctrl smia_ctrls[
4876         {
4877                 .id             = V4L2_CID_GAIN,
4878                 .type           = V4L2_CTRL_TYPE_INTEGER,
4879 -               .name           = "Analog gain",
4880 -               .minimum        = 0,
4881 -               .maximum        = 15,
4882 -               .step           = 1,
4883 -               .default_value  = 0,
4884 +               .name           = "Analog gain [0.1 EV]",
4885                 .flags          = V4L2_CTRL_FLAG_SLIDER,
4886         },
4887         {
4888                 .id             = V4L2_CID_EXPOSURE,
4889                 .type           = V4L2_CTRL_TYPE_INTEGER,
4890                 .name           = "Exposure time [us]",
4891 -               .minimum        = 0,
4892 -               .maximum        = DEFAULT_EXPOSURE,
4893 -               .step           = 1,
4894 -               .default_value  = DEFAULT_EXPOSURE,
4895                 .flags          = V4L2_CTRL_FLAG_SLIDER,
4896         },
4897  };
4898 @@ -336,7 +550,7 @@ static int smia_ioctl_queryctrl(struct v
4899                            struct v4l2_queryctrl *a)
4900  {
4901         struct smia_sensor *sensor = s->priv;
4902 -       int rval;
4903 +       int rval, ctrl;
4904  
4905         rval = smia_ctrl_query(smia_ctrls, ARRAY_SIZE(smia_ctrls), a);
4906         if (rval) {
4907 @@ -344,16 +558,16 @@ static int smia_ioctl_queryctrl(struct v
4908                                         ARRAY_SIZE(smia_mode_ctrls), a);
4909         }
4910  
4911 -       switch (a->id) {
4912 -       case V4L2_CID_EXPOSURE:
4913 -               if (sensor->current_reglist) {
4914 -                       a->maximum = smia_exposure_rows_to_us(sensor,
4915 -                                    sensor->current_reglist->mode.max_exp);
4916 -                       a->step = smia_exposure_rows_to_us(sensor, 1);
4917 -                       a->default_value = a->maximum;
4918 -               }
4919 -               break;
4920 -       }
4921 +       ctrl = CID_TO_CTRL(a->id);
4922 +       if (ctrl < 0)
4923 +               return ctrl;
4924 +       if (!sensor->controls[ctrl].set)
4925 +               return -EINVAL;
4926 +
4927 +       a->minimum       = sensor->controls[ctrl].minimum;
4928 +       a->maximum       = sensor->controls[ctrl].maximum;
4929 +       a->step          = sensor->controls[ctrl].step;
4930 +       a->default_value = sensor->controls[ctrl].default_value;
4931  
4932         return 0;
4933  }
4934 @@ -362,6 +576,7 @@ static int smia_ioctl_g_ctrl(struct v4l2
4935                         struct v4l2_control *vc)
4936  {
4937         struct smia_sensor *sensor = s->priv;
4938 +       int ctrl;
4939  
4940         int rval = smia_mode_g_ctrl(smia_mode_ctrls,
4941                         ARRAY_SIZE(smia_mode_ctrls),
4942 @@ -369,16 +584,13 @@ static int smia_ioctl_g_ctrl(struct v4l2
4943         if (rval == 0)
4944                 return 0;
4945  
4946 -       switch (vc->id) {
4947 -       case V4L2_CID_GAIN:
4948 -               vc->value = sensor->ctrl_gain;
4949 -               break;
4950 -       case V4L2_CID_EXPOSURE:
4951 -               vc->value = sensor->ctrl_exposure;
4952 -               break;
4953 -       default:
4954 +       ctrl = CID_TO_CTRL(vc->id);
4955 +       if (ctrl < 0)
4956 +               return ctrl;
4957 +       if (!sensor->controls[ctrl].set)
4958                 return -EINVAL;
4959 -       }
4960 +       vc->value = sensor->controls[ctrl].value;
4961 +
4962         return 0;
4963  }
4964  
4965 @@ -386,30 +598,13 @@ static int smia_ioctl_s_ctrl(struct v4l2
4966                         struct v4l2_control *vc)
4967  {
4968         struct smia_sensor *sensor = s->priv;
4969 -       int exposure_rows;
4970 -       int r = 0;
4971  
4972 -       switch (vc->id) {
4973 -       case V4L2_CID_GAIN:
4974 -               sensor->ctrl_gain = clamp(vc->value, 0, 15);
4975 -               if (sensor->power == V4L2_POWER_ON)
4976 -                       r = smia_i2c_write_reg(sensor->i2c_client,
4977 -                               SMIA_REG_8BIT, REG_ANALOG_GAIN+1,
4978 -                               sensor->ctrl_gain << 4);
4979 -               break;
4980 -       case V4L2_CID_EXPOSURE:
4981 -               sensor->ctrl_exposure = vc->value;
4982 -               exposure_rows = smia_exposure_us_to_rows(sensor,
4983 -                                                       &sensor->ctrl_exposure);
4984 -               if (sensor->power == V4L2_POWER_ON)
4985 -                       r = smia_i2c_write_reg(sensor->i2c_client,
4986 -                               SMIA_REG_16BIT, REG_COARSE_EXPOSURE,
4987 -                               exposure_rows);
4988 -               break;
4989 -       default:
4990 +       int ctrl = CID_TO_CTRL(vc->id);
4991 +       if (ctrl < 0)
4992 +               return ctrl;
4993 +       if (!sensor->controls[ctrl].set)
4994                 return -EINVAL;
4995 -       }
4996 -       return r;
4997 +       return sensor->controls[ctrl].set(sensor, vc->value);
4998  }
4999  
5000  static int smia_ioctl_enum_fmt_cap(struct v4l2_int_device *s,
5001 @@ -440,13 +635,10 @@ static int smia_ioctl_s_fmt_cap(struct v
5002  
5003         reglist = smia_reglist_find_mode_fmt(sensor->meta_reglist,
5004                                              sensor->current_reglist, f);
5005 -
5006 -       if (reglist) {
5007 -               sensor->current_reglist = reglist;
5008 -               return 0;
5009 -       }
5010 -
5011 -       return -EINVAL;
5012 +       if (!reglist)
5013 +               return -EINVAL;
5014 +       sensor->current_reglist = reglist;
5015 +       return smia_update_controls(s);
5016  }
5017  
5018  static int smia_ioctl_g_parm(struct v4l2_int_device *s,
5019 @@ -476,12 +668,10 @@ static int smia_ioctl_s_parm(struct v4l2
5020         reglist = smia_reglist_find_mode_streamparm(sensor->meta_reglist,
5021                                                     sensor->current_reglist, a);
5022  
5023 -       if (reglist) {
5024 -               sensor->current_reglist = reglist;
5025 -               return 0;
5026 -       }
5027 -
5028 -       return -EINVAL;
5029 +       if (!reglist)
5030 +               return -EINVAL;
5031 +       sensor->current_reglist = reglist;
5032 +       return smia_update_controls(s);
5033  }
5034  
5035  static int smia_ioctl_dev_init(struct v4l2_int_device *s)
5036 @@ -508,35 +698,56 @@ static int smia_ioctl_dev_init(struct v4
5037                 goto out_poweroff;
5038         }
5039  
5040 -       sensor->model_id        = model_id;
5041         sensor->revision_number = revision_number;
5042 -       sensor->manufacturer_id = manufacturer_id;
5043         sensor->smia_version    = smia_version;
5044  
5045 -       if (sensor->smia_version != 10) {
5046 +       if (smia_version != 10) {
5047                 /* We support only SMIA version 1.0 at the moment */
5048                 dev_err(&sensor->i2c_client->dev,
5049                         "unknown sensor 0x%04x detected (smia ver %i.%i)\n",
5050 -                       sensor->model_id,
5051 -                       sensor->smia_version / 10, sensor->smia_version % 10);
5052 +                       model_id, smia_version / 10, smia_version % 10);
5053                 rval = -ENODEV;
5054                 goto out_poweroff;
5055         }
5056  
5057 -       /* Update identification string */
5058 -       for (i = 0; i < ARRAY_SIZE(smia_sensors); i++) {
5059 -               if (smia_sensors[i].manufacturer_id == sensor->manufacturer_id
5060 -                   && smia_sensors[i].model_id == sensor->model_id)
5061 +       /* Detect which sensor we have */
5062 +       for (i = 1; i < ARRAY_SIZE(smia_sensors); i++) {
5063 +               if (smia_sensors[i].manufacturer_id == manufacturer_id
5064 +                   && smia_sensors[i].model_id == model_id)
5065                         break;
5066         }
5067 -       if (i < ARRAY_SIZE(smia_sensors))
5068 -               strncpy(s->name, smia_sensors[i].name, V4L2NAMESIZE);
5069 +       if (i >= ARRAY_SIZE(smia_sensors))
5070 +               i = 0;                  /* Unknown sensor */
5071 +       sensor->type = &smia_sensors[i];
5072 +
5073 +       /* Initialize V4L2 controls */
5074 +
5075 +       /* Gain is initialized here permanently */
5076 +       sensor->controls[SMIA_CTRL_GAIN].minimum           = 0;
5077 +       sensor->controls[SMIA_CTRL_GAIN].maximum           =
5078 +                               sensor->type->ev_table_size - 1;
5079 +       sensor->controls[SMIA_CTRL_GAIN].step              = 1;
5080 +       sensor->controls[SMIA_CTRL_GAIN].default_value     = 0;
5081 +       sensor->controls[SMIA_CTRL_GAIN].value             = 0;
5082 +       sensor->controls[SMIA_CTRL_GAIN].set               =
5083 +                               sensor->type->ev_table ? smia_set_gain : NULL;
5084 +
5085 +       /* Exposure parameters may change at each mode change, just zero here */
5086 +       sensor->controls[SMIA_CTRL_EXPOSURE].minimum       = 0;
5087 +       sensor->controls[SMIA_CTRL_EXPOSURE].maximum       = 0;
5088 +       sensor->controls[SMIA_CTRL_EXPOSURE].step          = 0;
5089 +       sensor->controls[SMIA_CTRL_EXPOSURE].default_value = 0;
5090 +       sensor->controls[SMIA_CTRL_EXPOSURE].value         = 0;
5091 +       sensor->controls[SMIA_CTRL_EXPOSURE].set           = smia_set_exposure;
5092 +
5093 +       /* Update identification string */
5094 +       strncpy(s->name, sensor->type->name, V4L2NAMESIZE);
5095         s->name[V4L2NAMESIZE-1] = 0;    /* Ensure NULL terminated string */
5096  
5097         /* Import firmware */
5098         snprintf(name, FIRMWARE_NAME_MAX, "%s-%02x-%04x-%02x.bin",
5099 -                SMIA_SENSOR_NAME, sensor->manufacturer_id,
5100 -                sensor->model_id, sensor->revision_number);
5101 +                SMIA_SENSOR_NAME, sensor->type->manufacturer_id,
5102 +                sensor->type->model_id, sensor->revision_number);
5103  
5104         if (request_firmware(&sensor->fw, name,
5105                              &sensor->i2c_client->dev)) {
5106 @@ -585,10 +796,74 @@ out_poweroff:
5107         return rval;
5108  }
5109  
5110 +#if VS6555_RESET_SHIFT_HACK
5111 +/*
5112 + * Check if certain undocumented registers have values we expect.
5113 + * If not, reset sensor and recheck.
5114 + * This should be called when streaming is already enabled.
5115 + */
5116 +static int smia_vs6555_reset_shift_hack(struct v4l2_int_device *s)
5117 +{
5118 +       struct smia_sensor *sensor = s->priv;
5119 +       int count = 10;
5120 +       int r381c = 0;
5121 +       int r381d = 0;
5122 +       int r381e = 0;
5123 +       int r381f = 0;
5124 +       int rval;
5125 +
5126 +       do {
5127 +               rval = smia_i2c_read_reg(sensor->i2c_client,
5128 +                                        SMIA_REG_8BIT, 0x381c, &r381c);
5129 +               if (rval)
5130 +                       return rval;
5131 +               rval = smia_i2c_read_reg(sensor->i2c_client,
5132 +                                        SMIA_REG_8BIT, 0x381d, &r381d);
5133 +               if (rval)
5134 +                       return rval;
5135 +               rval = smia_i2c_read_reg(sensor->i2c_client,
5136 +                                        SMIA_REG_8BIT, 0x381e, &r381e);
5137 +               if (rval)
5138 +                       return rval;
5139 +               rval = smia_i2c_read_reg(sensor->i2c_client,
5140 +                                        SMIA_REG_8BIT, 0x381f, &r381f);
5141 +               if (rval)
5142 +                       return rval;
5143 +
5144 +               if (r381d != 0 && r381f != 0 &&
5145 +                   r381c == 0 && r381e == 0)
5146 +                       return 0;
5147 +
5148 +               dev_dbg(&sensor->i2c_client->dev, "VS6555 HW misconfigured--"
5149 +                       "trying to reset (%02X%02X%02X%02X)\n",
5150 +                       r381c, r381d, r381e, r381f);
5151 +
5152 +               smia_stream_off(s);
5153 +               smia_power_off(s);
5154 +               msleep(2);
5155 +               rval = smia_power_on(s);
5156 +               if (rval)
5157 +                       return rval;
5158 +               rval = smia_configure(s);
5159 +               if (rval)
5160 +                       return rval;
5161 +               rval = smia_stream_on(s);
5162 +               if (rval)
5163 +                       return rval;
5164 +       } while (--count > 0);
5165 +
5166 +       dev_warn(&sensor->i2c_client->dev,
5167 +               "VS6555 reset failed--expect bad image\n");
5168 +
5169 +       return 0;       /* Return zero nevertheless -- at least we tried */
5170 +}
5171 +#endif
5172 +
5173  static int smia_ioctl_s_power(struct v4l2_int_device *s,
5174                                 enum v4l2_power new_state)
5175  {
5176         struct smia_sensor *sensor = s->priv;
5177 +       enum v4l2_power old_state = sensor->power;
5178         int rval = 0;
5179  
5180         /*
5181 @@ -599,7 +874,7 @@ static int smia_ioctl_s_power(struct v4l
5182                 new_state = V4L2_POWER_OFF;
5183  
5184         /* If we are already in this mode, do nothing */
5185 -       if (sensor->power == new_state)
5186 +       if (old_state == new_state)
5187                 return 0;
5188  
5189         /* Disable power if so requested (it was enabled) */
5190 @@ -615,7 +890,7 @@ static int smia_ioctl_s_power(struct v4l
5191         /* Either STANDBY or ON requested */
5192  
5193         /* Enable power and move to standby if it was off */
5194 -       if (sensor->power == V4L2_POWER_OFF) {
5195 +       if (old_state == V4L2_POWER_OFF) {
5196                 rval = smia_power_on(s);
5197                 if (rval)
5198                         goto out;
5199 @@ -625,23 +900,26 @@ static int smia_ioctl_s_power(struct v4l
5200  
5201         if (new_state == V4L2_POWER_ON) {
5202                 /* Standby -> streaming */
5203 +               sensor->power = V4L2_POWER_ON;
5204                 rval = smia_configure(s);
5205                 if (rval) {
5206                         smia_stream_off(s);
5207 -                       if (sensor->power == V4L2_POWER_OFF)
5208 +                       if (old_state == V4L2_POWER_OFF)
5209                                 smia_power_off(s);
5210                         goto out;
5211                 }
5212                 rval = smia_stream_on(s);
5213 +#if VS6555_RESET_SHIFT_HACK
5214 +               if (rval == 0 && sensor->type->manufacturer_id == 0x01)
5215 +                       rval = smia_vs6555_reset_shift_hack(s);
5216 +#endif
5217         } else {
5218                 /* Streaming -> standby */
5219                 rval = smia_stream_off(s);
5220         }
5221  
5222  out:
5223 -       if (rval == 0)
5224 -               sensor->power = new_state;
5225 -
5226 +       sensor->power = (rval == 0) ? new_state : old_state;
5227         return rval;
5228  }
5229  
5230 @@ -717,9 +995,6 @@ static int smia_probe(struct i2c_client
5231         sensor->i2c_client = client;
5232         i2c_set_clientdata(client, sensor);
5233  
5234 -       sensor->ctrl_gain     = 0;
5235 -       sensor->ctrl_exposure = DEFAULT_EXPOSURE;
5236 -
5237         rval = v4l2_int_device_register(sensor->v4l2_int_device);
5238         if (rval)
5239                 i2c_set_clientdata(client, NULL);
5240 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/media/video/smia-sensor.h kernel-2.6.28-20094803.3+0m5/drivers/media/video/smia-sensor.h
5241 --- kernel-2.6.28-20094102.6+0m5/drivers/media/video/smia-sensor.h      2011-09-04 11:36:23.000000000 +0200
5242 +++ kernel-2.6.28-20094803.3+0m5/drivers/media/video/smia-sensor.h      2011-09-04 11:37:54.000000000 +0200
5243 @@ -24,7 +24,6 @@
5244  #ifndef SMIA_SENSOR_H
5245  #define SMIA_SENSOR_H
5246  
5247 -#include <linux/i2c.h>
5248  #include <media/v4l2-int-device.h>
5249  
5250  #define SMIA_SENSOR_NAME       "smia-sensor"
5251 @@ -39,30 +38,5 @@ struct smia_sensor_platform_data {
5252         int (*power_off)(struct v4l2_int_device *s);
5253  };
5254  
5255 -struct smia_sensor {
5256 -       struct i2c_client *i2c_client;
5257 -       struct i2c_driver driver;
5258 -
5259 -       /* Sensor information */
5260 -       u16 model_id;
5261 -       u8  revision_number;
5262 -       u8  manufacturer_id;
5263 -       u8  smia_version;
5264 -
5265 -       /* V4L2 current control values */
5266 -       s32 ctrl_exposure;
5267 -       s32 ctrl_gain;
5268 -
5269 -       struct smia_reglist *current_reglist;
5270 -       struct v4l2_int_device *v4l2_int_device;
5271 -       struct v4l2_fract timeperframe;
5272 -
5273 -       struct smia_sensor_platform_data *platform_data;
5274 -
5275 -       const struct firmware *fw;
5276 -       struct smia_meta_reglist *meta_reglist;
5277 -
5278 -       enum v4l2_power power;
5279 -};
5280  
5281  #endif /* SMIA_SENSOR_H */
5282 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/mfd/twl4030-power.c kernel-2.6.28-20094803.3+0m5/drivers/mfd/twl4030-power.c
5283 --- kernel-2.6.28-20094102.6+0m5/drivers/mfd/twl4030-power.c    2011-09-04 11:36:23.000000000 +0200
5284 +++ kernel-2.6.28-20094803.3+0m5/drivers/mfd/twl4030-power.c    2011-09-04 11:37:54.000000000 +0200
5285 @@ -69,6 +69,11 @@ static u8 triton_next_free_address = 0x2
5286  #define KEY_1                  0xC0
5287  #define KEY_2                  0x0C
5288  
5289 +#define R_VDD1_OSC             0x5C
5290 +#define R_VDD2_OSC             0x6A
5291 +#define R_VIO_OSC              0x52
5292 +#define EXT_FS_CLK_EN          (0x1 << 6)
5293 +
5294  /* resource configuration registers */
5295  
5296  #define DEVGROUP_OFFSET                0
5297 @@ -467,6 +472,31 @@ int twl4030_disable_regulator(int res)
5298  }
5299  EXPORT_SYMBOL(twl4030_disable_regulator);
5300  
5301 +/**
5302 + * @brief twl_workaround - implement errata XYZ
5303 + * XYZ errata workaround requires the TWL DCDCs to use
5304 + * HFCLK - for this you need to write to all OSC regs to
5305 + * enable this path
5306 + * WARNING: you SHOULD change your board dependent script
5307 + * file to handle RET and OFF mode sequences correctly
5308 + *
5309 + * @return
5310 + */
5311 +static void __init twl_workaround(void)
5312 +{
5313 +       u8 val;
5314 +       u8 reg[]={R_VDD1_OSC, R_VDD2_OSC, R_VIO_OSC};
5315 +       int i;
5316 +       int err = 0;
5317 +       for (i = 0; i < sizeof(reg); i++) {
5318 +               err |= twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &val, reg[i]);
5319 +               val |= EXT_FS_CLK_EN;
5320 +               err |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val, reg[i]);
5321 +       }
5322 +       if (err)
5323 +               pr_warning("TWL4030: workaround setup failed!\n");
5324 +}
5325 +
5326  void __init twl4030_power_init(struct twl4030_power_data *triton2_scripts)
5327  {
5328         int err = 0;
5329 @@ -502,6 +532,8 @@ void __init twl4030_power_init(struct tw
5330                 }
5331         }
5332  
5333 +       /* TODO: introduce workaround based on TWL4030 revision */
5334 +       twl_workaround();
5335         if (twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY))
5336                 printk(KERN_ERR
5337                         "TWL4030 Unable to relock registers\n");
5338 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/Kconfig kernel-2.6.28-20094803.3+0m5/drivers/misc/Kconfig
5339 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/Kconfig   2011-09-04 11:36:23.000000000 +0200
5340 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/Kconfig   2011-09-04 11:37:54.000000000 +0200
5341 @@ -523,5 +523,6 @@ source "drivers/misc/c2port/Kconfig"
5342  source "drivers/misc/ssi/Kconfig"
5343  source "drivers/misc/mcsaab/Kconfig"
5344  source "drivers/misc/cmt-speech/Kconfig"
5345 +source "drivers/misc/ssi-char/Kconfig"
5346  
5347  endif # MISC_DEVICES
5348 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/Makefile kernel-2.6.28-20094803.3+0m5/drivers/misc/Makefile
5349 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/Makefile  2011-09-04 11:36:23.000000000 +0200
5350 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/Makefile  2011-09-04 11:37:54.000000000 +0200
5351 @@ -38,3 +38,5 @@ obj-$(CONFIG_C2PORT)          += c2port/
5352  obj-$(CONFIG_OMAP_SSI)         += ssi/
5353  obj-$(CONFIG_SSI_MCSAAB_IMP)   += mcsaab/
5354  obj-$(CONFIG_SSI_CMT_SPEECH)   += cmt-speech/
5355 +obj-$(CONFIG_SSI_CHAR)     += ssi-char/
5356 +obj-$(CONFIG_PANIC_INFO_BUFF)  += panic_info_buff.o
5357 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/panic_info_buff.c kernel-2.6.28-20094803.3+0m5/drivers/misc/panic_info_buff.c
5358 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/panic_info_buff.c 1970-01-01 01:00:00.000000000 +0100
5359 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/panic_info_buff.c 2011-09-04 11:37:54.000000000 +0200
5360 @@ -0,0 +1,93 @@
5361 +/*
5362 + * Copyright (C) Nokia Corporation
5363 + *
5364 + * Contact: Atal Shargorodsky <ext-atal.shargorodsky@nokia.com>
5365 + *
5366 + * This program is free software; you can redistribute it and/or modify
5367 + * it under the terms of the GNU General Public License as published by
5368 + * the Free Software Foundation; either version 2 of the License, or
5369 + * (at your option) any later version.
5370 + *
5371 + * This program is distributed in the hope that it will be useful,
5372 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5373 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5374 + * GNU General Public License for more details.
5375 + *
5376 + * You should have received a copy of the GNU General Public License
5377 + * along with this program; if not, write to the Free Software
5378 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5379 + */
5380 +
5381 +#include <linux/module.h>
5382 +#include <linux/kernel.h>
5383 +#include <linux/uaccess.h>
5384 +#include <linux/debugfs.h>
5385 +#include <linux/notifier.h>
5386 +
5387 +#define PANIC_BUFFER_MAX_LEN  1024
5388 +static char panic_info_buff[PANIC_BUFFER_MAX_LEN];
5389 +static struct dentry *panic_info_buff_debugfs;
5390 +
5391 +static int panic_info_buff_open(struct inode *inode, struct file *file)
5392 +{
5393 +       return 0;
5394 +}
5395 +
5396 +static ssize_t panic_info_buff_write(struct file *file,
5397 +               const char __user *buf, size_t len, loff_t *off)
5398 +{
5399 +       if (len >= PANIC_BUFFER_MAX_LEN)
5400 +               return -EINVAL;
5401 +       if (copy_from_user(panic_info_buff, buf, len))
5402 +               return -EFAULT;
5403 +       panic_info_buff[len] = '\0';
5404 +       return len;
5405 +}
5406 +
5407 +static struct file_operations panic_info_buff_fops = {
5408 +       .open   = panic_info_buff_open,
5409 +       .write  = panic_info_buff_write,
5410 +       .llseek = no_llseek,
5411 +       .owner  = THIS_MODULE,
5412 +};
5413 +
5414 +static int panic_info_buff_event(struct notifier_block *this,
5415 +       unsigned long event, void *ptr)
5416 +{
5417 +       if (panic_info_buff[0] == '\0') {
5418 +               printk(KERN_EMERG "Panic info buffer is empty.\n");
5419 +       } else {
5420 +               printk(KERN_EMERG "Panic info buffer:\n");
5421 +               printk(KERN_EMERG "%s\n", panic_info_buff);
5422 +       }
5423 +       return NOTIFY_OK;
5424 +}
5425 +
5426 +static struct notifier_block panic_info_buff_block = {
5427 +       .notifier_call  = panic_info_buff_event,
5428 +       .priority       = 1,
5429 +};
5430 +
5431 +static int __devinit panic_info_buff_init(void)
5432 +{
5433 +       panic_info_buff_debugfs = debugfs_create_file("panic_info_buff",
5434 +               S_IFREG | S_IWUSR | S_IWGRP,
5435 +               NULL, NULL, &panic_info_buff_fops);
5436 +       atomic_notifier_chain_register(&panic_notifier_list,
5437 +               &panic_info_buff_block);
5438 +       return 0;
5439 +}
5440 +module_init(panic_info_buff_init);
5441 +
5442 +static void __devexit panic_info_buff_exit(void)
5443 +{
5444 +       debugfs_remove(panic_info_buff_debugfs);
5445 +       atomic_notifier_chain_unregister(&panic_notifier_list,
5446 +               &panic_info_buff_block);
5447 +
5448 +}
5449 +module_exit(panic_info_buff_exit);
5450 +
5451 +MODULE_AUTHOR("Nokia Corporation");
5452 +MODULE_LICENSE("GPL");
5453 +MODULE_ALIAS("panic_info_buff");
5454 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi/ssi_driver.h kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi/ssi_driver.h
5455 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi/ssi_driver.h  2011-09-04 11:36:23.000000000 +0200
5456 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi/ssi_driver.h  2011-09-04 11:37:54.000000000 +0200
5457 @@ -44,6 +44,8 @@
5458  
5459  /* Channel states */
5460  #define        SSI_CH_OPEN             0x01
5461 +#define SSI_CH_RX_POLL         0x10
5462 +
5463  /*
5464   * The number of channels to use by the driver in the ports, or the highest
5465   * port channel number (+1) used. (MAX:8)
5466 @@ -87,8 +89,8 @@ struct ssi_channel {
5467         u8 channel_number;
5468         rwlock_t rw_lock;
5469         struct ssi_device *dev;
5470 -       void (*write_done)(struct ssi_device *dev);
5471 -       void (*read_done)(struct ssi_device *dev);
5472 +       void (*write_done) (struct ssi_device *dev);
5473 +       void (*read_done) (struct ssi_device *dev);
5474         void (*port_event)(struct ssi_device *dev, unsigned int event,
5475                                                                 void *arg);
5476  };
5477 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi/ssi_driver_if.c kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi/ssi_driver_if.c
5478 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi/ssi_driver_if.c       2011-09-04 11:36:23.000000000 +0200
5479 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi/ssi_driver_if.c       2011-09-04 11:37:54.000000000 +0200
5480 @@ -24,6 +24,127 @@
5481  
5482  #include "ssi_driver.h"
5483  
5484 +#define NOT_SET                (-1)
5485 +
5486 +int ssi_set_rx(struct ssi_port *sport, struct ssr_ctx *cfg)
5487 +{
5488 +       struct ssi_dev *ssi_ctrl = sport->ssi_controller;
5489 +       void __iomem *base = ssi_ctrl->base;
5490 +       int port = sport->port_number;
5491 +
5492 +       if ((cfg->mode != SSI_MODE_STREAM) &&
5493 +               (cfg->mode != SSI_MODE_FRAME) &&
5494 +               (cfg->mode != SSI_MODE_SLEEP) &&
5495 +               (cfg->mode != NOT_SET))
5496 +               return -EINVAL;
5497 +
5498 +       if ((cfg->frame_size > SSI_MAX_FRAME_SIZE) &&
5499 +               (cfg->frame_size != NOT_SET))
5500 +               return -EINVAL;
5501 +
5502 +       if ((cfg->channels == 0) ||
5503 +               ((cfg->channels > SSI_CHANNELS_DEFAULT) &&
5504 +                       (cfg->channels != NOT_SET)))
5505 +               return -EINVAL;
5506 +
5507 +       if ((cfg->timeout > SSI_MAX_RX_TIMEOUT) && (cfg->timeout != NOT_SET))
5508 +               return -EINVAL;
5509 +
5510 +       if (cfg->mode != NOT_SET)
5511 +               ssi_outl(cfg->mode, base, SSI_SSR_MODE_REG(port));
5512 +
5513 +       if (cfg->frame_size != NOT_SET)
5514 +               ssi_outl(cfg->frame_size, base, SSI_SSR_FRAMESIZE_REG(port));
5515 +
5516 +       if (cfg->channels != NOT_SET) {
5517 +               if ((cfg->channels & (-cfg->channels)) ^ cfg->channels)
5518 +                       return -EINVAL;
5519 +               else
5520 +                       ssi_outl(cfg->channels, base,
5521 +                                       SSI_SSR_CHANNELS_REG(port));
5522 +       }
5523 +
5524 +       if (cfg->timeout != NOT_SET)
5525 +               ssi_outl(cfg->timeout, base, SSI_SSR_TIMEOUT_REG(port));
5526 +
5527 +       return 0;
5528 +}
5529 +
5530 +void ssi_get_rx(struct ssi_port *sport, struct ssr_ctx *cfg)
5531 +{
5532 +       struct ssi_dev *ssi_ctrl = sport->ssi_controller;
5533 +       void __iomem *base = ssi_ctrl->base;
5534 +       int port = sport->port_number;
5535 +
5536 +       cfg->mode = ssi_inl(base, SSI_SSR_MODE_REG(port));
5537 +       cfg->frame_size = ssi_inl(base, SSI_SSR_FRAMESIZE_REG(port));
5538 +       cfg->channels = ssi_inl(base, SSI_SSR_CHANNELS_REG(port));
5539 +       cfg->timeout = ssi_inl(base, SSI_SSR_TIMEOUT_REG(port));
5540 +}
5541 +
5542 +int ssi_set_tx(struct ssi_port *sport, struct sst_ctx *cfg)
5543 +{
5544 +       struct ssi_dev *ssi_ctrl = sport->ssi_controller;
5545 +       void __iomem *base = ssi_ctrl->base;
5546 +       int port = sport->port_number;
5547 +
5548 +       if ((cfg->mode != SSI_MODE_STREAM) &&
5549 +               (cfg->mode != SSI_MODE_FRAME) &&
5550 +               (cfg->mode != NOT_SET))
5551 +               return -EINVAL;
5552 +
5553 +       if ((cfg->frame_size > SSI_MAX_FRAME_SIZE) &&
5554 +               (cfg->frame_size != NOT_SET))
5555 +               return -EINVAL;
5556 +
5557 +       if ((cfg->channels == 0) ||
5558 +               ((cfg->channels > SSI_CHANNELS_DEFAULT) &&
5559 +                       (cfg->channels != NOT_SET)))
5560 +               return -EINVAL;
5561 +
5562 +       if ((cfg->divisor > SSI_MAX_TX_DIVISOR) && (cfg->divisor != NOT_SET))
5563 +               return -EINVAL;
5564 +
5565 +       if ((cfg->arb_mode != SSI_ARBMODE_ROUNDROBIN) &&
5566 +               (cfg->arb_mode != SSI_ARBMODE_PRIORITY) &&
5567 +               (cfg->mode != NOT_SET))
5568 +               return -EINVAL;
5569 +
5570 +       if (cfg->mode != NOT_SET)
5571 +               ssi_outl(cfg->channels, base, SSI_SST_CHANNELS_REG(port));
5572 +
5573 +       if (cfg->frame_size != NOT_SET)
5574 +               ssi_outl(cfg->frame_size, base, SSI_SST_FRAMESIZE_REG(port));
5575 +
5576 +       if (cfg->channels != NOT_SET) {
5577 +               if ((cfg->channels & (-cfg->channels)) ^ cfg->channels)
5578 +                       return -EINVAL;
5579 +               else
5580 +                       ssi_outl(cfg->mode, base, SSI_SST_MODE_REG(port));
5581 +       }
5582 +
5583 +       if (cfg->divisor != NOT_SET)
5584 +               ssi_outl(cfg->divisor, base, SSI_SST_DIVISOR_REG(port));
5585 +
5586 +       if (cfg->arb_mode != NOT_SET)
5587 +               ssi_outl(cfg->arb_mode, base, SSI_SST_ARBMODE_REG(port));
5588 +
5589 +       return 0;
5590 +}
5591 +
5592 +void ssi_get_tx(struct ssi_port *sport, struct sst_ctx *cfg)
5593 +{
5594 +    struct ssi_dev *ssi_ctrl = sport->ssi_controller;
5595 +    void __iomem *base = ssi_ctrl->base;
5596 +    int port = sport->port_number;
5597 +
5598 +    cfg->mode = ssi_inl(base, SSI_SST_MODE_REG(port));
5599 +    cfg->frame_size = ssi_inl(base, SSI_SST_FRAMESIZE_REG(port));
5600 +    cfg->channels = ssi_inl(base, SSI_SST_CHANNELS_REG(port));
5601 +    cfg->divisor = ssi_inl(base, SSI_SST_DIVISOR_REG(port));
5602 +    cfg->arb_mode = ssi_inl(base, SSI_SST_ARBMODE_REG(port));
5603 +}
5604 +
5605  /**
5606   * ssi_open - open a ssi device channel.
5607   * @dev - Reference to the ssi device channel to be openned.
5608 @@ -225,6 +346,38 @@ void ssi_read_cancel(struct ssi_device *
5609  EXPORT_SYMBOL(ssi_read_cancel);
5610  
5611  /**
5612 + * ssi_poll - SSI poll
5613 + * @dev - ssi device channel reference to apply the I/O control
5614 + *                                             (or port associated to it)
5615 + *
5616 + * Return 0 on sucess, a negative value on failure.
5617 + *
5618 + */
5619 +int ssi_poll(struct ssi_device *dev)
5620 +{
5621 +       struct ssi_channel *ch;
5622 +       int err;
5623 +
5624 +       if (unlikely(!dev || !dev->ch))
5625 +               return -EINVAL;
5626 +
5627 +       if (unlikely(!(dev->ch->flags & SSI_CH_OPEN))) {
5628 +               dev_err(&dev->device, "SSI device NOT open\n");
5629 +               return -EINVAL;
5630 +       }
5631 +
5632 +       ch = dev->ch;
5633 +       spin_lock_bh(&ch->ssi_port->ssi_controller->lock);
5634 +       ch->flags |= SSI_CH_RX_POLL;
5635 +       err = ssi_driver_read_interrupt(ch, NULL);
5636 +       spin_unlock_bh(&ch->ssi_port->ssi_controller->lock);
5637 +
5638 +       return err;
5639 +}
5640 +EXPORT_SYMBOL(ssi_poll);
5641 +
5642 +
5643 +/**
5644   * ssi_ioctl - SSI I/O control
5645   * @dev - ssi device channel reference to apply the I/O control
5646   *                                             (or port associated to it)
5647 @@ -305,6 +458,33 @@ int ssi_ioctl(struct ssi_device *dev, un
5648                 }
5649                 *(unsigned int *)arg = ssi_cawake(dev->ch->ssi_port);
5650                 break;
5651 +       case SSI_IOCTL_SET_RX:
5652 +               if (!arg) {
5653 +                       err = -EINVAL;
5654 +                       goto out;
5655 +               }
5656 +               err = ssi_set_rx(dev->ch->ssi_port, (struct ssr_ctx *)arg);
5657 +               break;
5658 +       case SSI_IOCTL_GET_RX:
5659 +               if (!arg) {
5660 +                       err = -EINVAL;
5661 +                       goto out;
5662 +               }
5663 +               ssi_get_rx(dev->ch->ssi_port, (struct ssr_ctx *)arg);
5664 +               break;
5665 +       case SSI_IOCTL_SET_TX:
5666 +               if (!arg) {
5667 +                       err = -EINVAL;
5668 +                       goto out;
5669 +               }
5670 +               err = ssi_set_tx(dev->ch->ssi_port, (struct sst_ctx *)arg);
5671 +               break;
5672 +       case SSI_IOCTL_GET_TX:
5673 +               if (!arg) {
5674 +                       err = -EINVAL;
5675 +                       goto out;
5676 +               }
5677 +               ssi_get_tx(dev->ch->ssi_port, (struct sst_ctx *)arg);
5678         case SSI_IOCTL_TX_CH_FULL:
5679                 if (!arg) {
5680                         err = -EINVAL;
5681 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi/ssi_driver_int.c kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi/ssi_driver_int.c
5682 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi/ssi_driver_int.c      2011-09-04 11:36:23.000000000 +0200
5683 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi/ssi_driver_int.c      2011-09-04 11:37:54.000000000 +0200
5684 @@ -25,9 +25,19 @@
5685  
5686  void ssi_reset_ch_read(struct ssi_channel *ch)
5687  {
5688 +       struct ssi_port *p = ch->ssi_port;
5689 +       struct ssi_dev *ssi_ctrl = p->ssi_controller;
5690 +       unsigned int channel = ch->channel_number;
5691 +       void __iomem *base = ssi_ctrl->base;
5692 +       unsigned int port = p->port_number;
5693 +       unsigned int irq = p->n_irq;
5694 +
5695         ch->read_data.addr = NULL;
5696         ch->read_data.size = 0;
5697         ch->read_data.lch = -1;
5698 +
5699 +       ssi_outl(SSI_SSR_DATAAVAILABLE(channel), base,
5700 +                       SSI_SYS_MPU_STATUS_REG(port, irq));
5701  }
5702  
5703  void ssi_reset_ch_write(struct ssi_channel *ch)
5704 @@ -145,6 +155,8 @@ static void do_channel_rx(struct ssi_cha
5705         unsigned int n_ch;
5706         unsigned int n_p;
5707         unsigned int irq;
5708 +       int rx_poll = 0;
5709 +       int data_read = 0;
5710  
5711         n_ch = ch->channel_number;
5712         n_p = ch->ssi_port->port_number;
5713 @@ -152,7 +164,14 @@ static void do_channel_rx(struct ssi_cha
5714  
5715         spin_lock(&ssi_ctrl->lock);
5716  
5717 -       *(ch->read_data.addr) = ssi_inl(base, SSI_SSR_BUFFER_CH_REG(n_p, n_ch));
5718 +       if (ch->flags & SSI_CH_RX_POLL)
5719 +               rx_poll = 1;
5720 +
5721 +       if (ch->read_data.addr) {
5722 +               data_read = 1;
5723 +               *(ch->read_data.addr) = ssi_inl(base,
5724 +                                               SSI_SSR_BUFFER_CH_REG(n_p, n_ch));
5725 +       }
5726  
5727         ssi_outl_and(~SSI_SSR_DATAAVAILABLE(n_ch), base,
5728                                         SSI_SYS_MPU_ENABLE_REG(n_p, irq));
5729 @@ -160,7 +179,13 @@ static void do_channel_rx(struct ssi_cha
5730  
5731         spin_unlock(&ssi_ctrl->lock);
5732  
5733 -       (*ch->read_done)(ch->dev);
5734 +       if (rx_poll)
5735 +               ssi_port_event_handler(ch->ssi_port,
5736 +                                       SSI_EVENT_SSR_DATAAVAILABLE,
5737 +                                       (void *)n_ch);
5738 +
5739 +       if (data_read)
5740 +               (*ch->read_done)(ch->dev);
5741  }
5742  
5743  static void do_ssi_tasklet(unsigned long ssi_port)
5744 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/Kconfig kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/Kconfig
5745 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/Kconfig  1970-01-01 01:00:00.000000000 +0100
5746 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/Kconfig  2011-09-04 11:37:54.000000000 +0200
5747 @@ -0,0 +1,18 @@
5748 +#
5749 +# OMAP SSI kernel configuration
5750 +#
5751 +
5752 +config SSI_CHAR
5753 +       tristate "SSI character driver"
5754 +       depends on OMAP_SSI
5755 +       ---help---
5756 +         If you say Y here, you will enable the CMT character driver.
5757 +         This driver provides a simple character device interface for
5758 +         serial communication with the cellular modem over the SSI bus.
5759 +
5760 +config SSI_CHAR_DEBUG
5761 +       bool "Debug CMT character driver"
5762 +       depends on SSI_CHAR && DEBUG_KERNEL
5763 +       default n
5764 +       ---help---
5765 +         Enable the debug information in the CMT character driver.
5766 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/Makefile kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/Makefile
5767 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/Makefile 1970-01-01 01:00:00.000000000 +0100
5768 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/Makefile 2011-09-04 11:37:54.000000000 +0200
5769 @@ -0,0 +1,8 @@
5770 +#
5771 +# Makefile for SSI CHAR driver
5772 +#
5773 +#EXTRA_CFLAGS := -I$(src)/../../../include
5774 +
5775 +obj-$(CONFIG_SSI_CHAR) += ssi_char.o
5776 +
5777 +ssi_char-objs  := ssi-char.o ssi-if.o
5778 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/ssi-char.c kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/ssi-char.c
5779 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/ssi-char.c       1970-01-01 01:00:00.000000000 +0100
5780 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/ssi-char.c       2011-09-04 11:37:54.000000000 +0200
5781 @@ -0,0 +1,493 @@
5782 +/*
5783 + * ssi-char.c
5784 + *
5785 + * SSI character device driver, implements the character device
5786 + * interface.
5787 + *
5788 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
5789 + *
5790 + * Contact: Andras Domokos <andras.domokos@nokia.com>
5791 + *
5792 + * This program is free software; you can redistribute it and/or
5793 + * modify it under the terms of the GNU General Public License
5794 + * version 2 as published by the Free Software Foundation.
5795 + *
5796 + * This program is distributed in the hope that it will be useful, but
5797 + * WITHOUT ANY WARRANTY; without even the implied warranty of
5798 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5799 + * General Public License for more details.
5800 + *
5801 + * You should have received a copy of the GNU General Public License
5802 + * along with this program; if not, write to the Free Software
5803 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
5804 + * 02110-1301 USA
5805 + */
5806 +
5807 +#include <linux/errno.h>
5808 +#include <linux/module.h>
5809 +#include <linux/types.h>
5810 +#include <linux/init.h>
5811 +#include <linux/device.h>
5812 +#include <linux/err.h>
5813 +#include <linux/miscdevice.h>
5814 +#include <linux/file.h>
5815 +#include <linux/mm.h>
5816 +#include <linux/fs.h>
5817 +#include <linux/cdev.h>
5818 +#include <linux/poll.h>
5819 +#include <asm/mach-types.h>
5820 +#include <linux/ioctl.h>
5821 +#include <linux/uaccess.h>
5822 +
5823 +#include <mach/ssi.h>
5824 +#include <linux/ssi_driver_if.h>
5825 +#include <linux/ssi_char.h>
5826 +
5827 +#include "ssi-char-debug.h"
5828 +#include "ssi-char.h"
5829 +
5830 +#define DRIVER_VERSION  "0.1.0"
5831 +
5832 +static unsigned int port = 1;
5833 +module_param(port, uint, 1);
5834 +MODULE_PARM_DESC(port, "SSI port to be probed");
5835 +
5836 +static unsigned int channels_map[SSI_MAX_CHAR_DEVS] = {1};
5837 +module_param_array(channels_map, uint, NULL, 0);
5838 +MODULE_PARM_DESC(channels_map, "SSI channels to be probed");
5839 +
5840 +dev_t ssi_char_dev;
5841 +
5842 +struct char_queue {
5843 +       struct list_head list;
5844 +       u32 *data;
5845 +       unsigned int count;
5846 +};
5847 +
5848 +struct ssi_char {
5849 +       unsigned int opened;
5850 +       int poll_event;
5851 +       struct list_head rx_queue;
5852 +       struct list_head tx_queue;
5853 +       spinlock_t lock;
5854 +       struct fasync_struct *async_queue;
5855 +       wait_queue_head_t rx_wait;
5856 +       wait_queue_head_t tx_wait;
5857 +       wait_queue_head_t poll_wait;
5858 +};
5859 +
5860 +static struct ssi_char ssi_char_data[SSI_MAX_CHAR_DEVS];
5861 +
5862 +void if_notify(int ch, struct ssi_event *ev)
5863 +{
5864 +       struct char_queue *entry;
5865 +
5866 +       spin_lock(&ssi_char_data[ch].lock);
5867 +
5868 +       if (!ssi_char_data[ch].opened) {
5869 +               printk(KERN_DEBUG "device not opened\n!");
5870 +               spin_unlock(&ssi_char_data[ch].lock);
5871 +               return;
5872 +       }
5873 +
5874 +       switch (SSI_EV_TYPE(ev->event)) {
5875 +       case SSI_EV_IN:
5876 +               entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
5877 +               if (!entry) {
5878 +                       pr_err("SSI-CHAR: entry allocation failed.\n");
5879 +                       spin_unlock(&ssi_char_data[ch].lock);
5880 +                       return;
5881 +               }
5882 +               entry->data = ev->data;
5883 +               entry->count = ev->count;
5884 +               list_add_tail(&entry->list, &ssi_char_data[ch].rx_queue);
5885 +               spin_unlock(&ssi_char_data[ch].lock);
5886 +               wake_up_interruptible(&ssi_char_data[ch].rx_wait);
5887 +               break;
5888 +       case SSI_EV_OUT:
5889 +               entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
5890 +               if (!entry) {
5891 +                       pr_err("SSI-CHAR: entry allocation failed.\n");
5892 +                       spin_unlock(&ssi_char_data[ch].lock);
5893 +                       return;
5894 +               }
5895 +               entry->data = ev->data;
5896 +               entry->count = ev->count;
5897 +               ssi_char_data[ch].poll_event |= (POLLOUT | POLLWRNORM);
5898 +               list_add_tail(&entry->list, &ssi_char_data[ch].tx_queue);
5899 +               spin_unlock(&ssi_char_data[ch].lock);
5900 +               wake_up_interruptible(&ssi_char_data[ch].tx_wait);
5901 +               break;
5902 +       case SSI_EV_EXCEP:
5903 +               ssi_char_data[ch].poll_event |= POLLPRI;
5904 +               spin_unlock(&ssi_char_data[ch].lock);
5905 +               wake_up_interruptible(&ssi_char_data[ch].poll_wait);
5906 +               break;
5907 +       case SSI_EV_AVAIL:
5908 +               ssi_char_data[ch].poll_event |= (POLLIN | POLLRDNORM);
5909 +               spin_unlock(&ssi_char_data[ch].lock);
5910 +               wake_up_interruptible(&ssi_char_data[ch].poll_wait);
5911 +               break;
5912 +       default:
5913 +               spin_unlock(&ssi_char_data[ch].lock);
5914 +               break;
5915 +       }
5916 +}
5917 +
5918 +
5919 +static int ssi_char_fasync(int fd, struct file *file, int on)
5920 +{
5921 +       int ch = (int)file->private_data;
5922 +       if (fasync_helper(fd, file, on, &ssi_char_data[ch].async_queue) >= 0)
5923 +               return 0;
5924 +       else
5925 +               return -EIO;
5926 +}
5927 +
5928 +
5929 +static unsigned int ssi_char_poll(struct file *file, poll_table *wait)
5930 +{
5931 +       int ch = (int)file->private_data;
5932 +       unsigned int ret = 0;
5933 +
5934 +       poll_wait(file, &ssi_char_data[ch].poll_wait, wait);
5935 +       poll_wait(file, &ssi_char_data[ch].tx_wait, wait);
5936 +       spin_lock_bh(&ssi_char_data[ch].lock);
5937 +       ret = ssi_char_data[ch].poll_event;
5938 +       spin_unlock_bh(&ssi_char_data[ch].lock);
5939 +
5940 +       return ret;
5941 +}
5942 +
5943 +
5944 +static ssize_t ssi_char_read(struct file *file, char __user *buf,
5945 +                       size_t count, loff_t *ppos)
5946 +{
5947 +       int ch = (int)file->private_data;
5948 +       DECLARE_WAITQUEUE(wait, current);
5949 +       u32 *data;
5950 +       unsigned int data_len;
5951 +       struct char_queue *entry;
5952 +       ssize_t ret;
5953 +
5954 +       /* only 32bit data is supported for now */
5955 +       if ((count < 4) || (count & 3))
5956 +               return -EINVAL;
5957 +
5958 +       data = kmalloc(count, GFP_ATOMIC);
5959 +
5960 +       ret = if_ssi_read(ch, data, count);
5961 +       if (ret < 0) {
5962 +               kfree(data);
5963 +               goto out2;
5964 +       }
5965 +
5966 +       add_wait_queue(&ssi_char_data[ch].rx_wait, &wait);
5967 +
5968 +       for ( ; ; ) {
5969 +               data = NULL;
5970 +               data_len = 0;
5971 +
5972 +               set_current_state(TASK_INTERRUPTIBLE);
5973 +
5974 +               spin_lock_bh(&ssi_char_data[ch].lock);
5975 +               if (!list_empty(&ssi_char_data[ch].rx_queue)) {
5976 +                       entry = list_entry(ssi_char_data[ch].rx_queue.next,
5977 +                                       struct char_queue, list);
5978 +                       data = entry->data;
5979 +                       data_len = entry->count;
5980 +                       list_del(&entry->list);
5981 +                       kfree(entry);
5982 +               }
5983 +               spin_unlock_bh(&ssi_char_data[ch].lock);
5984 +
5985 +               if (data_len) {
5986 +                       spin_lock_bh(&ssi_char_data[ch].lock);
5987 +                       ssi_char_data[ch].poll_event &= ~(POLLIN | POLLRDNORM |
5988 +                                                               POLLPRI);
5989 +                       if_ssi_poll(ch);
5990 +                       spin_unlock_bh(&ssi_char_data[ch].lock);
5991 +                       break;
5992 +               } else if (file->f_flags & O_NONBLOCK) {
5993 +                       ret = -EAGAIN;
5994 +                       goto out;
5995 +               } else if (signal_pending(current)) {
5996 +                       ret = -EAGAIN;
5997 +                       if_ssi_cancel_read(ch);
5998 +                       break;
5999 +               }
6000 +
6001 +               schedule();
6002 +       }
6003 +
6004 +       if (data_len) {
6005 +               ret = copy_to_user((void __user *)buf, data, data_len);
6006 +               if (!ret)
6007 +                       ret = data_len;
6008 +       }
6009 +
6010 +       kfree(data);
6011 +
6012 +out:
6013 +       __set_current_state(TASK_RUNNING);
6014 +       remove_wait_queue(&ssi_char_data[ch].rx_wait, &wait);
6015 +
6016 +out2:
6017 +       return ret;
6018 +}
6019 +
6020 +static ssize_t ssi_char_write(struct file *file, const char __user *buf,
6021 +                        size_t count, loff_t *ppos)
6022 +{
6023 +       int ch = (int)file->private_data;
6024 +       DECLARE_WAITQUEUE(wait, current);
6025 +       u32 *data;
6026 +       unsigned int data_len = 0;
6027 +       struct char_queue *entry;
6028 +       ssize_t ret;
6029 +
6030 +       /* only 32bit data is supported for now */
6031 +       if ((count < 4) || (count & 3))
6032 +               return -EINVAL;
6033 +
6034 +       data = kmalloc(count, GFP_ATOMIC);
6035 +
6036 +       if (copy_from_user(data, (void __user *)buf, count)) {
6037 +               ret = -EFAULT;
6038 +               kfree(data);
6039 +       } else {
6040 +               ret = count;
6041 +       }
6042 +
6043 +       spin_lock_bh(&ssi_char_data[ch].lock);
6044 +       ret = if_ssi_write(ch, data, count);
6045 +       if (ret < 0) {
6046 +               spin_unlock_bh(&ssi_char_data[ch].lock);
6047 +               kfree(data);
6048 +               goto out2;
6049 +       }
6050 +       ssi_char_data[ch].poll_event &= ~(POLLOUT | POLLWRNORM);
6051 +       spin_unlock_bh(&ssi_char_data[ch].lock);
6052 +
6053 +       add_wait_queue(&ssi_char_data[ch].tx_wait, &wait);
6054 +
6055 +       for ( ; ; ) {
6056 +               data = NULL;
6057 +               data_len = 0;
6058 +
6059 +               set_current_state(TASK_INTERRUPTIBLE);
6060 +
6061 +               spin_lock_bh(&ssi_char_data[ch].lock);
6062 +               if (!list_empty(&ssi_char_data[ch].tx_queue)) {
6063 +                       entry = list_entry(ssi_char_data[ch].tx_queue.next,
6064 +                                       struct char_queue, list);
6065 +                       data = entry->data;
6066 +                       data_len = entry->count;
6067 +                       list_del(&entry->list);
6068 +                       kfree(entry);
6069 +               }
6070 +               spin_unlock_bh(&ssi_char_data[ch].lock);
6071 +
6072 +               if (data_len) {
6073 +                       ret = data_len;
6074 +                       break;
6075 +               } else if (file->f_flags & O_NONBLOCK) {
6076 +                       ret = -EAGAIN;
6077 +                       goto out;
6078 +               } else if (signal_pending(current)) {
6079 +                       ret = -ERESTARTSYS;
6080 +                       goto out;
6081 +               }
6082 +
6083 +               schedule();
6084 +       }
6085 +
6086 +    kfree(data);
6087 +
6088 +out:
6089 +       __set_current_state(TASK_RUNNING);
6090 +       remove_wait_queue(&ssi_char_data[ch].tx_wait, &wait);
6091 +
6092 +out2:
6093 +       return ret;
6094 +}
6095 +
6096 +static int ssi_char_ioctl(struct inode *inode, struct file *file,
6097 +                               unsigned int cmd, unsigned long arg)
6098 +{
6099 +       int ch = (int)file->private_data;
6100 +       unsigned int state;
6101 +       struct ssi_rx_config rx_cfg;
6102 +       struct ssi_tx_config tx_cfg;
6103 +       int ret = 0;
6104 +
6105 +       switch (cmd) {
6106 +       case CS_SEND_BREAK:
6107 +               if_ssi_send_break(ch);
6108 +       break;
6109 +       case CS_FLUSH_RX:
6110 +               if_ssi_flush_rx(ch);
6111 +       break;
6112 +       case CS_FLUSH_TX:
6113 +               if_ssi_flush_tx(ch);
6114 +       break;
6115 +       case CS_SET_WAKELINE:
6116 +               if (copy_from_user(&state, (void __user *)arg,
6117 +                               sizeof(state)))
6118 +                       ret = -EFAULT;
6119 +               else
6120 +                       if_ssi_set_wakeline(ch, state);
6121 +       break;
6122 +       case CS_GET_WAKELINE:
6123 +               if_ssi_get_wakeline(ch, &state);
6124 +               if (copy_to_user((void __user *)arg, &state, sizeof(state)))
6125 +                       ret = -EFAULT;
6126 +       break;
6127 +       case CS_SET_RX: {
6128 +               if (copy_from_user(&rx_cfg, (void __user *)arg,
6129 +                               sizeof(rx_cfg)))
6130 +                       ret = -EFAULT;
6131 +               else
6132 +                       ret = if_ssi_set_rx(ch, &rx_cfg);
6133 +       }
6134 +               break;
6135 +       case CS_GET_RX:
6136 +               if_ssi_get_rx(ch, &rx_cfg);
6137 +               if (copy_to_user((void __user *)arg, &rx_cfg, sizeof(rx_cfg)))
6138 +                       ret = -EFAULT;
6139 +       break;
6140 +       case CS_SET_TX:
6141 +               if (copy_from_user(&tx_cfg, (void __user *)arg,
6142 +                               sizeof(tx_cfg)))
6143 +                       ret = -EFAULT;
6144 +               else
6145 +                       ret = if_ssi_set_tx(ch, &tx_cfg);
6146 +       break;
6147 +       case CS_GET_TX:
6148 +               if_ssi_get_tx(ch, &tx_cfg);
6149 +               if (copy_to_user((void __user *)arg, &tx_cfg, sizeof(tx_cfg)))
6150 +                       ret = -EFAULT;
6151 +       break;
6152 +       default:
6153 +               return -ENOIOCTLCMD;
6154 +       break;
6155 +       }
6156 +
6157 +       return ret;
6158 +}
6159 +
6160 +static int ssi_char_open(struct inode *inode, struct file *file)
6161 +{
6162 +       int ret = 0, ch = iminor(inode);
6163 +
6164 +       if (!channels_map[ch])
6165 +               return -ENODEV;
6166 +
6167 +       spin_lock_bh(&ssi_char_data[ch].lock);
6168 +#if 0
6169 +       if (ssi_char_data[ch].opened) {
6170 +               spin_unlock_bh(&ssi_char_data[ch].lock);
6171 +               return -EBUSY;
6172 +       }
6173 +#endif
6174 +       file->private_data = (void *)ch;
6175 +       ssi_char_data[ch].opened++;
6176 +       ssi_char_data[ch].poll_event = (POLLOUT | POLLWRNORM);
6177 +       spin_unlock_bh(&ssi_char_data[ch].lock);
6178 +
6179 +       ret = if_ssi_start(ch);
6180 +
6181 +       return ret;
6182 +}
6183 +
6184 +static int ssi_char_release(struct inode *inode, struct file *file)
6185 +{
6186 +       int ch = (int)file->private_data;
6187 +       struct char_queue       *entry;
6188 +       struct list_head        *cursor, *next;
6189 +
6190 +       if_ssi_stop(ch);
6191 +       spin_lock_bh(&ssi_char_data[ch].lock);
6192 +       ssi_char_data[ch].opened--;
6193 +
6194 +       if (!list_empty(&ssi_char_data[ch].rx_queue)) {
6195 +               list_for_each_safe(cursor, next, &ssi_char_data[ch].rx_queue) {
6196 +                       entry = list_entry(cursor, struct char_queue, list);
6197 +                       list_del(&entry->list);
6198 +                       kfree(entry);
6199 +               }
6200 +       }
6201 +
6202 +       if (!list_empty(&ssi_char_data[ch].tx_queue)) {
6203 +               list_for_each_safe(cursor, next, &ssi_char_data[ch].tx_queue) {
6204 +                       entry = list_entry(cursor, struct char_queue, list);
6205 +                       list_del(&entry->list);
6206 +                       kfree(entry);
6207 +               }
6208 +       }
6209 +
6210 +       spin_unlock_bh(&ssi_char_data[ch].lock);
6211 +
6212 +       return 0;
6213 +}
6214 +
6215 +static const struct file_operations ssi_char_fops = {
6216 +       .owner = THIS_MODULE,
6217 +       .read = ssi_char_read,
6218 +       .write = ssi_char_write,
6219 +       .poll = ssi_char_poll,
6220 +       .ioctl = ssi_char_ioctl,
6221 +       .open = ssi_char_open,
6222 +       .release = ssi_char_release,
6223 +       .fasync = ssi_char_fasync,
6224 +};
6225 +
6226 +static struct cdev ssi_char_cdev;
6227 +
6228 +static int __init ssi_char_init(void)
6229 +{
6230 +       char devname[] = "ssi_char";
6231 +       int ret, i;
6232 +
6233 +       pr_info("SSI character device version " DRIVER_VERSION "\n");
6234 +
6235 +       for (i = 0; i < SSI_MAX_CHAR_DEVS; i++) {
6236 +               init_waitqueue_head(&ssi_char_data[i].rx_wait);
6237 +               init_waitqueue_head(&ssi_char_data[i].tx_wait);
6238 +               init_waitqueue_head(&ssi_char_data[i].poll_wait);
6239 +               spin_lock_init(&ssi_char_data[i].lock);
6240 +               ssi_char_data[i].opened = 0;
6241 +               INIT_LIST_HEAD(&ssi_char_data[i].rx_queue);
6242 +               INIT_LIST_HEAD(&ssi_char_data[i].tx_queue);
6243 +       }
6244 +
6245 +       ret = if_ssi_init(port, channels_map);
6246 +       if (ret)
6247 +               return ret;
6248 +
6249 +       ret = alloc_chrdev_region(&ssi_char_dev, 0, SSI_MAX_CHAR_DEVS, devname);
6250 +       if (ret < 0) {
6251 +               pr_err("SSI character driver: Failed to register\n");
6252 +               return ret;
6253 +       }
6254 +
6255 +       cdev_init(&ssi_char_cdev, &ssi_char_fops);
6256 +       cdev_add(&ssi_char_cdev, ssi_char_dev, SSI_MAX_CHAR_DEVS);
6257 +
6258 +       return 0;
6259 +}
6260 +
6261 +static void __exit ssi_char_exit(void)
6262 +{
6263 +       cdev_del(&ssi_char_cdev);
6264 +       unregister_chrdev_region(ssi_char_dev, SSI_MAX_CHAR_DEVS);
6265 +       if_ssi_exit();
6266 +}
6267 +
6268 +MODULE_AUTHOR("Andras Domokos <andras.domokos@nokia.com>");
6269 +MODULE_DESCRIPTION("SSI character device");
6270 +MODULE_LICENSE("GPL");
6271 +MODULE_VERSION(DRIVER_VERSION);
6272 +
6273 +module_init(ssi_char_init);
6274 +module_exit(ssi_char_exit);
6275 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/ssi-char-debug.h kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/ssi-char-debug.h
6276 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/ssi-char-debug.h 1970-01-01 01:00:00.000000000 +0100
6277 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/ssi-char-debug.h 2011-09-04 11:37:54.000000000 +0200
6278 @@ -0,0 +1,39 @@
6279 +/*
6280 + * ssi-char-debug.h
6281 + *
6282 + * Part of the SSI character driver. Debugging related definitions.
6283 + *
6284 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
6285 + *
6286 + * Contact: Andras Domokos <andras.domokos@nokia.com>
6287 + *
6288 + * This program is free software; you can redistribute it and/or
6289 + * modify it under the terms of the GNU General Public License
6290 + * version 2 as published by the Free Software Foundation.
6291 + *
6292 + * This program is distributed in the hope that it will be useful, but
6293 + * WITHOUT ANY WARRANTY; without even the implied warranty of
6294 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
6295 + * General Public License for more details.
6296 + *
6297 + * You should have received a copy of the GNU General Public License
6298 + * along with this program; if not, write to the Free Software
6299 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
6300 + * 02110-1301 USA
6301 + */
6302 +
6303 +
6304 +#ifndef _SSI_CHAR_DEBUG_H
6305 +#define _SSI_CHAR_DEBUG_H
6306 +
6307 +#ifdef CONFIG_SSI_CHAR_DEBUG
6308 +#define DPRINTK(fmt, arg...) printk(KERN_DEBUG "%s(): " fmt, __func__, ##arg)
6309 +#define DENTER()       printk(KERN_DEBUG "ENTER %s()\n", __func__)
6310 +#define DLEAVE(a)      printk(KERN_DEBUG "LEAVE %s() %d\n", __func__, a)
6311 +#else
6312 +#define DPRINTK(fmt, arg...)   while (0)
6313 +#define DENTER()               while (0)
6314 +#define DLEAVE(a)              while (0)
6315 +#endif
6316 +
6317 +#endif /* _SSI_CHAR_DEBUG_H */
6318 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/ssi-char.h kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/ssi-char.h
6319 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/ssi-char.h       1970-01-01 01:00:00.000000000 +0100
6320 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/ssi-char.h       2011-09-04 11:37:54.000000000 +0200
6321 @@ -0,0 +1,36 @@
6322 +/*
6323 + * ssi-char.h
6324 + *
6325 + * Part of the SSI character device driver.
6326 + *
6327 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
6328 + *
6329 + * Contact: Andras Domokos <andras.domokos@nokia.com>
6330 + *
6331 + * This program is free software; you can redistribute it and/or
6332 + * modify it under the terms of the GNU General Public License
6333 + * version 2 as published by the Free Software Foundation.
6334 + *
6335 + * This program is distributed in the hope that it will be useful, but
6336 + * WITHOUT ANY WARRANTY; without even the implied warranty of
6337 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
6338 + * General Public License for more details.
6339 + *
6340 + * You should have received a copy of the GNU General Public License
6341 + * along with this program; if not, write to the Free Software
6342 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
6343 + * 02110-1301 USA
6344 + */
6345 +
6346 +
6347 +#ifndef _SSI_CHAR_H
6348 +#define _SSI_CHAR_H
6349 +
6350 +#include "ssi-if.h"
6351 +
6352 +/* how many char devices would be created at most */
6353 +#define SSI_MAX_CHAR_DEVS      8
6354 +
6355 +void if_notify(int ch, struct ssi_event *ev);
6356 +
6357 +#endif /* _SSI_CHAR_H */
6358 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/ssi-if.c kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/ssi-if.c
6359 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/ssi-if.c 1970-01-01 01:00:00.000000000 +0100
6360 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/ssi-if.c 2011-09-04 11:37:54.000000000 +0200
6361 @@ -0,0 +1,625 @@
6362 +/*
6363 + * ssi-if.c
6364 + *
6365 + * Part of the SSI character driver, implements the SSI interface.
6366 + *
6367 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
6368 + *
6369 + * Contact: Andras Domokos <andras.domokos@nokia.com>
6370 + *
6371 + * This program is free software; you can redistribute it and/or
6372 + * modify it under the terms of the GNU General Public License
6373 + * version 2 as published by the Free Software Foundation.
6374 + *
6375 + * This program is distributed in the hope that it will be useful, but
6376 + * WITHOUT ANY WARRANTY; without even the implied warranty of
6377 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
6378 + * General Public License for more details.
6379 + *
6380 + * You should have received a copy of the GNU General Public License
6381 + * along with this program; if not, write to the Free Software
6382 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
6383 + * 02110-1301 USA
6384 + */
6385 +
6386 +#include <linux/errno.h>
6387 +#include <linux/module.h>
6388 +#include <linux/init.h>
6389 +#include <linux/device.h>
6390 +#include <linux/err.h>
6391 +#include <linux/platform_device.h>
6392 +#include <asm/mach-types.h>
6393 +#include <linux/ioctl.h>
6394 +#include <linux/delay.h>
6395 +#include <linux/ktime.h>
6396 +#include <linux/bitmap.h>
6397 +
6398 +#include <linux/ssi_driver_if.h>
6399 +#include <linux/ssi_char.h>
6400 +
6401 +#include "ssi-char-debug.h"
6402 +#include "ssi-char.h"
6403 +#include "ssi-if.h"
6404 +
6405 +#define SSI_CHANNEL_STATE_UNAVAIL      (1 << 0)
6406 +#define SSI_CHANNEL_STATE_READING      (1 << 1)
6407 +#define SSI_CHANNEL_STATE_WRITING      (1 << 2)
6408 +
6409 +#define PORT1  0
6410 +#define PORT2  1
6411 +
6412 +#define SSI_RX_PARAM(cfg, mod, fsize, n, tmo) \
6413 +       do { \
6414 +               (cfg)->mode = mod; \
6415 +               (cfg)->frame_size = fsize; \
6416 +               (cfg)->channels = n; \
6417 +               (cfg)->timeout = tmo; \
6418 +       } while (0)
6419 +
6420 +#define SSI_TX_PARAM(cfg, mod, fsize, n, div, arb) \
6421 +       do { \
6422 +               (cfg)->mode = mod; \
6423 +               (cfg)->frame_size = fsize; \
6424 +               (cfg)->channels = n; \
6425 +               (cfg)->divisor = div; \
6426 +               (cfg)->arb_mode = arb; \
6427 +       } while (0)
6428 +
6429 +#define RXCONV(dst, src) \
6430 +       do { \
6431 +               (dst)->mode = (src)->mode; \
6432 +               (dst)->frame_size = (src)->frame_size; \
6433 +               (dst)->channels = (src)->channels; \
6434 +               (dst)->timeout = (src)->timeout; \
6435 +       } while (0)
6436 +
6437 +#define TXCONV(dst, src) \
6438 +       do { \
6439 +               (dst)->mode = (src)->mode; \
6440 +               (dst)->frame_size = (src)->frame_size; \
6441 +               (dst)->channels = (src)->channels; \
6442 +               (dst)->divisor = (src)->divisor; \
6443 +               (dst)->arb_mode = (src)->arb_mode; \
6444 +       } while (0)
6445 +
6446 +struct if_ssi_channel {
6447 +       struct ssi_device *dev;
6448 +       unsigned int channel_id;
6449 +       u32 *tx_data;
6450 +       unsigned int tx_count;
6451 +       u32 *rx_data;
6452 +       unsigned int rx_count;
6453 +       unsigned int opened;
6454 +       unsigned int state;
6455 +       spinlock_t lock;
6456 +};
6457 +
6458 +struct if_ssi_iface {
6459 +       struct if_ssi_channel channels[SSI_MAX_CHAR_DEVS];
6460 +       int bootstrap;
6461 +       spinlock_t lock;
6462 +};
6463 +
6464 +static void if_ssi_port_event(struct ssi_device *dev, unsigned int event,
6465 +                               void *arg);
6466 +static int __devinit if_ssi_probe(struct ssi_device *dev);
6467 +static int __devexit if_ssi_remove(struct ssi_device *dev);
6468 +
6469 +static struct ssi_device_driver if_ssi_char_driver = {
6470 +       .ctrl_mask = ANY_SSI_CONTROLLER,
6471 +       .probe = if_ssi_probe,
6472 +       .remove = __devexit_p(if_ssi_remove),
6473 +       .driver = {
6474 +               .name = "ssi_char"
6475 +       },
6476 +};
6477 +
6478 +static struct if_ssi_iface ssi_iface;
6479 +
6480 +static int if_ssi_read_on(int ch, u32 *data, unsigned int count)
6481 +{
6482 +       struct if_ssi_channel *channel;
6483 +       int ret;
6484 +
6485 +       channel = &ssi_iface.channels[ch];
6486 +
6487 +       spin_lock(&channel->lock);
6488 +       if (channel->state & SSI_CHANNEL_STATE_READING) {
6489 +               pr_err("Read still pending on channel %d\n", ch);
6490 +               spin_unlock(&channel->lock);
6491 +               return -EBUSY;
6492 +       }
6493 +       channel->state |= SSI_CHANNEL_STATE_READING;
6494 +       channel->rx_data = data;
6495 +       channel->rx_count = count;
6496 +       spin_unlock(&channel->lock);
6497 +
6498 +       ret = ssi_read(channel->dev, data, count/4);
6499 +
6500 +       return ret;
6501 +}
6502 +
6503 +static void if_ssi_read_done(struct ssi_device *dev)
6504 +{
6505 +       struct if_ssi_channel *channel;
6506 +       struct ssi_event ev;
6507 +
6508 +       channel = &ssi_iface.channels[dev->n_ch];
6509 +       spin_lock(&channel->lock);
6510 +       channel->state &= ~SSI_CHANNEL_STATE_READING;
6511 +       ev.event = SSI_EV_IN;
6512 +       ev.data = channel->rx_data;
6513 +       ev.count = channel->rx_count;
6514 +       spin_unlock(&channel->lock);
6515 +       if_notify(dev->n_ch, &ev);
6516 +}
6517 +
6518 +int if_ssi_read(int ch, u32 *data, unsigned int count)
6519 +{
6520 +       int ret = 0;
6521 +       spin_lock_bh(&ssi_iface.lock);
6522 +       ret = if_ssi_read_on(ch, data, count);
6523 +       spin_unlock_bh(&ssi_iface.lock);
6524 +       return ret;
6525 +}
6526 +
6527 +int if_ssi_poll(int ch)
6528 +{
6529 +       struct if_ssi_channel *channel;
6530 +       int ret = 0;
6531 +       channel = &ssi_iface.channels[ch];
6532 +       spin_lock_bh(&ssi_iface.lock);
6533 +       ret = ssi_poll(channel->dev);
6534 +       spin_unlock_bh(&ssi_iface.lock);
6535 +       return ret;
6536 +}
6537 +
6538 +static int if_ssi_write_on(int ch, u32 *address, unsigned int count)
6539 +{
6540 +       struct if_ssi_channel *channel;
6541 +       int ret;
6542 +
6543 +       channel = &ssi_iface.channels[ch];
6544 +
6545 +       spin_lock(&channel->lock);
6546 +       if (channel->state & SSI_CHANNEL_STATE_WRITING) {
6547 +               pr_err("Write still pending on channel %d\n", ch);
6548 +               spin_unlock(&channel->lock);
6549 +               return -EBUSY;
6550 +       }
6551 +
6552 +       channel->tx_data = address;
6553 +       channel->tx_count = count;
6554 +       channel->state |= SSI_CHANNEL_STATE_WRITING;
6555 +       spin_unlock(&channel->lock);
6556 +       ret = ssi_write(channel->dev, address, count/4);
6557 +       return ret;
6558 +}
6559 +
6560 +static void if_ssi_write_done(struct ssi_device *dev)
6561 +{
6562 +       struct if_ssi_channel *channel;
6563 +       struct ssi_event ev;
6564 +
6565 +       channel = &ssi_iface.channels[dev->n_ch];
6566 +
6567 +       spin_lock(&channel->lock);
6568 +       channel->state &= ~SSI_CHANNEL_STATE_WRITING;
6569 +       ev.event = SSI_EV_OUT;
6570 +       ev.data = channel->tx_data;
6571 +       ev.count = channel->tx_count;
6572 +       spin_unlock(&channel->lock);
6573 +       if_notify(dev->n_ch, &ev);
6574 +}
6575 +
6576 +int if_ssi_write(int ch, u32 *data, unsigned int count)
6577 +{
6578 +       int ret = 0;
6579 +
6580 +       spin_lock_bh(&ssi_iface.lock);
6581 +       ret = if_ssi_write_on(ch, data, count);
6582 +       spin_unlock_bh(&ssi_iface.lock);
6583 +       return ret;
6584 +}
6585 +
6586 +void if_ssi_send_break(int ch)
6587 +{
6588 +       struct if_ssi_channel *channel;
6589 +
6590 +       channel = &ssi_iface.channels[ch];
6591 +       spin_lock_bh(&ssi_iface.lock);
6592 +       ssi_ioctl(channel->dev, SSI_IOCTL_SEND_BREAK, NULL);
6593 +       spin_unlock_bh(&ssi_iface.lock);
6594 +}
6595 +
6596 +void if_ssi_flush_rx(int ch)
6597 +{
6598 +       struct if_ssi_channel *channel;
6599 +
6600 +       channel = &ssi_iface.channels[ch];
6601 +       spin_lock_bh(&ssi_iface.lock);
6602 +       ssi_ioctl(channel->dev, SSI_IOCTL_FLUSH_RX, NULL);
6603 +       spin_unlock_bh(&ssi_iface.lock);
6604 +}
6605 +
6606 +void if_ssi_flush_ch(int ch)
6607 +{
6608 +       struct if_ssi_channel *channel;
6609 +
6610 +       channel = &ssi_iface.channels[ch];
6611 +       spin_lock(&channel->lock);
6612 +       spin_unlock(&channel->lock);
6613 +}
6614 +
6615 +void if_ssi_flush_tx(int ch)
6616 +{
6617 +       struct if_ssi_channel *channel;
6618 +
6619 +       channel = &ssi_iface.channels[ch];
6620 +       spin_lock_bh(&ssi_iface.lock);
6621 +       ssi_ioctl(channel->dev, SSI_IOCTL_FLUSH_TX, NULL);
6622 +       spin_unlock_bh(&ssi_iface.lock);
6623 +}
6624 +
6625 +void if_ssi_get_wakeline(int ch, unsigned int *state)
6626 +{
6627 +       struct if_ssi_channel *channel;
6628 +
6629 +       channel = &ssi_iface.channels[ch];
6630 +       spin_lock_bh(&ssi_iface.lock);
6631 +       ssi_ioctl(channel->dev, SSI_IOCTL_WAKE, state);
6632 +       spin_unlock_bh(&ssi_iface.lock);
6633 +}
6634 +
6635 +void if_ssi_set_wakeline(int ch, unsigned int state)
6636 +{
6637 +       struct if_ssi_channel *channel;
6638 +
6639 +       channel = &ssi_iface.channels[ch];
6640 +       spin_lock_bh(&ssi_iface.lock);
6641 +       ssi_ioctl(channel->dev, state, NULL);
6642 +       spin_unlock_bh(&ssi_iface.lock);
6643 +}
6644 +
6645 +int if_ssi_set_rx(int ch, struct ssi_rx_config *cfg)
6646 +{
6647 +       int ret;
6648 +       struct if_ssi_channel *channel;
6649 +       struct ssr_ctx ctx;
6650 +
6651 +       RXCONV(&ctx, cfg);
6652 +       channel = &ssi_iface.channels[ch];
6653 +       spin_lock_bh(&ssi_iface.lock);
6654 +       ret = ssi_ioctl(channel->dev, SSI_IOCTL_SET_RX, &ctx);
6655 +       spin_unlock_bh(&ssi_iface.lock);
6656 +       return ret;
6657 +}
6658 +
6659 +void if_ssi_get_rx(int ch, struct ssi_rx_config *cfg)
6660 +{
6661 +       struct if_ssi_channel *channel;
6662 +       struct ssr_ctx ctx;
6663 +
6664 +       channel = &ssi_iface.channels[ch];
6665 +       spin_lock_bh(&ssi_iface.lock);
6666 +       ssi_ioctl(channel->dev, SSI_IOCTL_GET_RX, &ctx);
6667 +       RXCONV(cfg, &ctx);
6668 +       spin_unlock_bh(&ssi_iface.lock);
6669 +}
6670 +
6671 +int if_ssi_set_tx(int ch, struct ssi_tx_config *cfg)
6672 +{
6673 +       int ret;
6674 +       struct if_ssi_channel *channel;
6675 +       struct sst_ctx ctx;
6676 +
6677 +       TXCONV(&ctx, cfg);
6678 +       channel = &ssi_iface.channels[ch];
6679 +       spin_lock_bh(&ssi_iface.lock);
6680 +       ret = ssi_ioctl(channel->dev, SSI_IOCTL_SET_TX, &ctx);
6681 +       spin_unlock_bh(&ssi_iface.lock);
6682 +       return ret;
6683 +}
6684 +
6685 +void if_ssi_get_tx(int ch, struct ssi_tx_config *cfg)
6686 +{
6687 +       struct if_ssi_channel *channel;
6688 +       struct sst_ctx ctx;
6689 +
6690 +       channel = &ssi_iface.channels[ch];
6691 +       spin_lock_bh(&ssi_iface.lock);
6692 +       ssi_ioctl(channel->dev, SSI_IOCTL_GET_TX, &ctx);
6693 +       TXCONV(cfg, &ctx);
6694 +       spin_unlock_bh(&ssi_iface.lock);
6695 +}
6696 +
6697 +void if_ssi_cancel_read(int ch)
6698 +{
6699 +       struct if_ssi_channel *channel;
6700 +
6701 +       channel = &ssi_iface.channels[ch];
6702 +       spin_lock(&channel->lock);
6703 +       if (channel->state & SSI_CHANNEL_STATE_READING)
6704 +               ssi_read_cancel(channel->dev);
6705 +       channel->state &= ~SSI_CHANNEL_STATE_READING;
6706 +       spin_unlock(&channel->lock);
6707 +}
6708 +
6709 +void if_ssi_cancel_write(int ch)
6710 +{
6711 +       struct if_ssi_channel *channel;
6712 +
6713 +       channel = &ssi_iface.channels[ch];
6714 +       spin_lock(&channel->lock);
6715 +       if (channel->state & SSI_CHANNEL_STATE_WRITING)
6716 +               ssi_write_cancel(channel->dev);
6717 +       channel->state &= ~SSI_CHANNEL_STATE_WRITING;
6718 +       spin_unlock(&channel->lock);
6719 +}
6720 +
6721 +static int if_ssi_openchannel(struct if_ssi_channel *channel)
6722 +{
6723 +       int ret = 0;
6724 +
6725 +       spin_lock(&channel->lock);
6726 +
6727 +       if (channel->state == SSI_CHANNEL_STATE_UNAVAIL)
6728 +               return -ENODEV;
6729 +
6730 +       if (channel->opened) {
6731 +               ret = -EBUSY;
6732 +               goto leave;
6733 +       }
6734 +
6735 +       if (!channel->dev) {
6736 +               pr_err("Channel %d is not ready??\n",
6737 +                               channel->channel_id);
6738 +               ret = -ENODEV;
6739 +               goto leave;
6740 +       }
6741 +
6742 +       ret = ssi_open(channel->dev);
6743 +       if (ret < 0) {
6744 +               pr_err("Could not open channel %d\n",
6745 +                               channel->channel_id);
6746 +               goto leave;
6747 +       }
6748 +
6749 +       channel->opened = 1;
6750 +
6751 +leave:
6752 +       spin_unlock(&channel->lock);
6753 +       return ret;
6754 +}
6755 +
6756 +
6757 +static int if_ssi_closechannel(struct if_ssi_channel *channel)
6758 +{
6759 +       int ret = 0;
6760 +
6761 +       spin_lock(&channel->lock);
6762 +
6763 +       if (!channel->opened)
6764 +               goto leave;
6765 +
6766 +       if (!channel->dev) {
6767 +               pr_err("Channel %d is not ready??\n",
6768 +                               channel->channel_id);
6769 +               ret = -ENODEV;
6770 +               goto leave;
6771 +       }
6772 +
6773 +       /* Stop any pending read/write */
6774 +       if (channel->state & SSI_CHANNEL_STATE_READING) {
6775 +               ssi_read_cancel(channel->dev);
6776 +               channel->state &= ~SSI_CHANNEL_STATE_READING;
6777 +       }
6778 +       if (channel->state & SSI_CHANNEL_STATE_WRITING) {
6779 +               ssi_write_cancel(channel->dev);
6780 +               channel->state &= ~SSI_CHANNEL_STATE_WRITING;
6781 +       }
6782 +
6783 +       ssi_close(channel->dev);
6784 +
6785 +       channel->opened = 0;
6786 +leave:
6787 +       spin_unlock(&channel->lock);
6788 +       return ret;
6789 +}
6790 +
6791 +
6792 +int if_ssi_start(int ch)
6793 +{
6794 +       struct if_ssi_channel *channel;
6795 +       int ret = 0;
6796 +
6797 +       channel = &ssi_iface.channels[ch];
6798 +       spin_lock_bh(&ssi_iface.lock);
6799 +       channel->state = 0;
6800 +       ret = if_ssi_openchannel(channel);
6801 +       if (ret < 0) {
6802 +               pr_err("Could not open channel %d\n", ch);
6803 +               spin_unlock_bh(&ssi_iface.lock);
6804 +               goto error;
6805 +       }
6806 +       if_ssi_poll(ch);
6807 +       spin_unlock_bh(&ssi_iface.lock);
6808 +
6809 +error:
6810 +       return ret;
6811 +}
6812 +
6813 +void if_ssi_stop(int ch)
6814 +{
6815 +       struct if_ssi_channel *channel;
6816 +       channel = &ssi_iface.channels[ch];
6817 +       if_ssi_set_wakeline(ch, 1);
6818 +       spin_lock_bh(&ssi_iface.lock);
6819 +       if_ssi_closechannel(channel);
6820 +       spin_unlock_bh(&ssi_iface.lock);
6821 +}
6822 +
6823 +static int __devinit if_ssi_probe(struct ssi_device *dev)
6824 +{
6825 +       struct if_ssi_channel *channel;
6826 +       unsigned long *address;
6827 +       int ret = -ENXIO, port;
6828 +
6829 +       for (port = 0; port < SSI_MAX_PORTS; port++) {
6830 +               if (if_ssi_char_driver.ch_mask[port])
6831 +                       break;
6832 +       }
6833 +
6834 +       if (port == SSI_MAX_PORTS)
6835 +               return -ENXIO;
6836 +
6837 +       address = &if_ssi_char_driver.ch_mask[port];
6838 +
6839 +       spin_lock_bh(&ssi_iface.lock);
6840 +       if (test_bit(dev->n_ch, address) && (dev->n_p == port)) {
6841 +               ssi_set_read_cb(dev, if_ssi_read_done);
6842 +               ssi_set_write_cb(dev, if_ssi_write_done);
6843 +               ssi_set_port_event_cb(dev, if_ssi_port_event);
6844 +               channel = &ssi_iface.channels[dev->n_ch];
6845 +               channel->dev = dev;
6846 +               channel->state = 0;
6847 +               ret = 0;
6848 +       }
6849 +       spin_unlock_bh(&ssi_iface.lock);
6850 +
6851 +       return ret;
6852 +}
6853 +
6854 +static int __devexit if_ssi_remove(struct ssi_device *dev)
6855 +{
6856 +       struct if_ssi_channel *channel;
6857 +       unsigned long *address;
6858 +       int ret = -ENXIO, port;
6859 +
6860 +       for (port = 0; port < SSI_MAX_PORTS; port++) {
6861 +               if (if_ssi_char_driver.ch_mask[port])
6862 +                       break;
6863 +       }
6864 +
6865 +       if (port == SSI_MAX_PORTS)
6866 +               return -ENXIO;
6867 +
6868 +       address = &if_ssi_char_driver.ch_mask[port];
6869 +
6870 +       spin_lock_bh(&ssi_iface.lock);
6871 +       if (test_bit(dev->n_ch, address) && (dev->n_p == port)) {
6872 +               ssi_set_read_cb(dev, NULL);
6873 +               ssi_set_write_cb(dev, NULL);
6874 +               channel = &ssi_iface.channels[dev->n_ch];
6875 +               channel->dev = NULL;
6876 +               channel->state = SSI_CHANNEL_STATE_UNAVAIL;
6877 +               ret = 0;
6878 +       }
6879 +       spin_unlock_bh(&ssi_iface.lock);
6880 +
6881 +       return ret;
6882 +}
6883 +
6884 +static void if_ssi_port_event(struct ssi_device *dev, unsigned int event,
6885 +                               void *arg)
6886 +{
6887 +       struct ssi_event ev;
6888 +       int i;
6889 +
6890 +       ev.event = SSI_EV_EXCEP;
6891 +       ev.data = (u32 *)0;
6892 +       ev.count = 0;
6893 +
6894 +       switch (event) {
6895 +       case SSI_EVENT_BREAK_DETECTED:
6896 +               ev.data = (u32 *)SSI_HWBREAK;
6897 +               spin_lock_bh(&ssi_iface.lock);
6898 +               for (i = 0; i < SSI_MAX_CHAR_DEVS; i++) {
6899 +                       if (ssi_iface.channels[i].opened)
6900 +                               if_notify(i, &ev);
6901 +               }
6902 +               spin_unlock_bh(&ssi_iface.lock);
6903 +               break;
6904 +       case SSI_EVENT_SSR_DATAAVAILABLE:
6905 +               i = (int)arg;
6906 +               ev.event = SSI_EV_AVAIL;
6907 +               spin_lock_bh(&ssi_iface.lock);
6908 +               if (ssi_iface.channels[i].opened)
6909 +                       if_notify(i, &ev);
6910 +               spin_unlock_bh(&ssi_iface.lock);
6911 +               break;
6912 +       case SSI_EVENT_CAWAKE_UP:
6913 +               break;
6914 +       case SSI_EVENT_CAWAKE_DOWN:
6915 +               break;
6916 +       case SSI_EVENT_ERROR:
6917 +               break;
6918 +       default:
6919 +               printk(KERN_DEBUG "%s, Unknown event(%d)\n", __func__, event);
6920 +               break;
6921 +       }
6922 +}
6923 +
6924 +int __init if_ssi_init(unsigned int port, unsigned int *channels_map)
6925 +{
6926 +       struct if_ssi_channel *channel;
6927 +       int     i, ret = 0;
6928 +
6929 +       port -= 1;
6930 +       if (port >= SSI_MAX_PORTS)
6931 +               return -EINVAL;
6932 +
6933 +       ssi_iface.bootstrap = 1;
6934 +       spin_lock_init(&ssi_iface.lock);
6935 +
6936 +       for (i = 0; i < SSI_MAX_PORTS; i++)
6937 +               if_ssi_char_driver.ch_mask[i] = 0;
6938 +
6939 +       for (i = 0; i < SSI_MAX_CHAR_DEVS; i++) {
6940 +               channel = &ssi_iface.channels[i];
6941 +               channel->dev = NULL;
6942 +               channel->opened = 0;
6943 +               channel->state = 0;
6944 +               channel->channel_id = i;
6945 +               spin_lock_init(&channel->lock);
6946 +               channel->state = SSI_CHANNEL_STATE_UNAVAIL;
6947 +       }
6948 +
6949 +       for (i = 0; (i < SSI_MAX_CHAR_DEVS) && channels_map[i]; i++) {
6950 +               if ((channels_map[i] - 1) < SSI_MAX_CHAR_DEVS)
6951 +                       if_ssi_char_driver.ch_mask[port] |= (1 << ((channels_map[i] - 1)));
6952 +       }
6953 +
6954 +       ret = register_ssi_driver(&if_ssi_char_driver);
6955 +       if (ret)
6956 +               pr_err("Error while registering SSI driver %d", ret);
6957 +
6958 +       return ret;
6959 +}
6960 +
6961 +int __exit if_ssi_exit(void)
6962 +{
6963 +       struct if_ssi_channel *channel;
6964 +       unsigned long *address;
6965 +       int i, port;
6966 +
6967 +       for (port = 0; port < SSI_MAX_PORTS; port++) {
6968 +               if (if_ssi_char_driver.ch_mask[port])
6969 +                       break;
6970 +       }
6971 +
6972 +       if (port == SSI_MAX_PORTS)
6973 +               return -ENXIO;
6974 +
6975 +       address = &if_ssi_char_driver.ch_mask[port];
6976 +
6977 +       for (i = 0; i < SSI_MAX_CHAR_DEVS; i++) {
6978 +               channel = &ssi_iface.channels[i];
6979 +               if (channel->opened) {
6980 +                       if_ssi_set_wakeline(i, 1);
6981 +                       if_ssi_closechannel(channel);
6982 +               }
6983 +       }
6984 +       unregister_ssi_driver(&if_ssi_char_driver);
6985 +       return 0;
6986 +}
6987 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/ssi-if.h kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/ssi-if.h
6988 --- kernel-2.6.28-20094102.6+0m5/drivers/misc/ssi-char/ssi-if.h 1970-01-01 01:00:00.000000000 +0100
6989 +++ kernel-2.6.28-20094803.3+0m5/drivers/misc/ssi-char/ssi-if.h 2011-09-04 11:37:54.000000000 +0200
6990 @@ -0,0 +1,70 @@
6991 +/*
6992 + * ssi-if.h
6993 + *
6994 + * Part of the SSI character driver.
6995 + *
6996 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
6997 + *
6998 + * Contact: Andras Domokos <andras.domokos@nokia.com>
6999 + *
7000 + * This program is free software; you can redistribute it and/or
7001 + * modify it under the terms of the GNU General Public License
7002 + * version 2 as published by the Free Software Foundation.
7003 + *
7004 + * This program is distributed in the hope that it will be useful, but
7005 + * WITHOUT ANY WARRANTY; without even the implied warranty of
7006 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7007 + * General Public License for more details.
7008 + *
7009 + * You should have received a copy of the GNU General Public License
7010 + * along with this program; if not, write to the Free Software
7011 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
7012 + * 02110-1301 USA
7013 + */
7014 +
7015 +
7016 +#ifndef _SSI_IF_H
7017 +#define _SSI_IF_H
7018 +
7019 +#define SSI_EV_MASK            (0xffff << 0)
7020 +#define SSI_EV_TYPE_MASK       (0x0f << 16)
7021 +#define SSI_EV_IN              (0x01 << 16)
7022 +#define SSI_EV_OUT             (0x02 << 16)
7023 +#define SSI_EV_EXCEP           (0x03 << 16)
7024 +#define SSI_EV_AVAIL           (0x04 << 16)
7025 +#define SSI_EV_TYPE(event)     ((event) & SSI_EV_TYPE_MASK)
7026 +
7027 +#define SSI_HWBREAK            1
7028 +#define SSI_ERROR              2
7029 +
7030 +struct ssi_event {
7031 +    unsigned int event;
7032 +    u32 *data;
7033 +    unsigned int count;
7034 +};
7035 +
7036 +int if_ssi_init(unsigned int port, unsigned int *channels_map);
7037 +int if_ssi_exit(void);
7038 +
7039 +int if_ssi_start(int ch);
7040 +void if_ssi_stop(int ch);
7041 +
7042 +void if_ssi_send_break(int ch);
7043 +void if_ssi_flush_rx(int ch);
7044 +void if_ssi_flush_tx(int ch);
7045 +void if_ssi_bootstrap(int ch);
7046 +void if_ssi_set_wakeline(int ch, unsigned int state);
7047 +void if_ssi_get_wakeline(int ch, unsigned int *state);
7048 +int if_ssi_set_rx(int ch, struct ssi_rx_config *cfg);
7049 +void if_ssi_get_rx(int ch, struct ssi_rx_config *cfg);
7050 +int if_ssi_set_tx(int ch, struct ssi_tx_config *cfg);
7051 +void if_ssi_get_tx(int ch, struct ssi_tx_config *cfg);
7052 +
7053 +int if_ssi_read(int ch, u32 *data, unsigned int count);
7054 +int if_ssi_poll(int ch);
7055 +int if_ssi_write(int ch, u32 *data, unsigned int count);
7056 +
7057 +void if_ssi_cancel_read(int ch);
7058 +void if_ssi_cancel_write(int ch);
7059 +
7060 +#endif /* _SSI_IF_H */
7061 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/mmc/card/block.c kernel-2.6.28-20094803.3+0m5/drivers/mmc/card/block.c
7062 --- kernel-2.6.28-20094102.6+0m5/drivers/mmc/card/block.c       2011-09-04 11:36:23.000000000 +0200
7063 +++ kernel-2.6.28-20094803.3+0m5/drivers/mmc/card/block.c       2011-09-04 11:37:54.000000000 +0200
7064 @@ -83,7 +83,14 @@ static void mmc_blk_put(struct mmc_blk_d
7065         mutex_lock(&open_lock);
7066         md->usage--;
7067         if (md->usage == 0) {
7068 +               int devmaj = MAJOR(disk_devt(md->disk));
7069                 int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT;
7070 +
7071 +               if (!devmaj)
7072 +                       devidx = md->disk->first_minor >> MMC_SHIFT;
7073 +
7074 +               blk_cleanup_queue(md->queue.queue);
7075 +
7076                 __clear_bit(devidx, dev_use);
7077  
7078                 put_disk(md->disk);
7079 @@ -312,6 +319,15 @@ static int mmc_blk_issue_rq(struct mmc_q
7080  
7081                 mmc_wait_for_req(card->host, &brq.mrq);
7082  
7083 +               /* Give up early if the card has gone away */
7084 +               if (brq.cmd.error == -ENODEV || brq.data.error == -ENODEV || brq.stop.error == -ENODEV) {
7085 +                       req->cmd_flags |= REQ_QUIET;
7086 +                       spin_lock_irq(&md->lock);
7087 +                       ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
7088 +                       spin_unlock_irq(&md->lock);
7089 +                       break;
7090 +               }
7091 +
7092                 mmc_queue_bounce_post(mq);
7093  
7094                 /*
7095 @@ -363,6 +379,11 @@ static int mmc_blk_issue_rq(struct mmc_q
7096                                 cmd.arg = card->rca << 16;
7097                                 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
7098                                 err = mmc_wait_for_cmd(card->host, &cmd, 5);
7099 +                               if (err == -ENODEV) {
7100 +                                       /* Card was removed so quiet errors */
7101 +                                       req->cmd_flags |= REQ_QUIET;
7102 +                                       goto cmd_err;
7103 +                               }
7104                                 if (err) {
7105                                         printk(KERN_ERR "%s: error %d requesting status\n",
7106                                                req->rq_disk->disk_name, err);
7107 @@ -583,8 +604,11 @@ static int mmc_blk_probe(struct mmc_card
7108                 return PTR_ERR(md);
7109  
7110         err = mmc_blk_set_blksize(md, card);
7111 -       if (err)
7112 -               goto out;
7113 +       if (err) {
7114 +               mmc_cleanup_queue(&md->queue);
7115 +               mmc_blk_put(md);
7116 +               return err;
7117 +       }
7118  
7119         string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
7120                         cap_str, sizeof(cap_str));
7121 @@ -595,11 +619,6 @@ static int mmc_blk_probe(struct mmc_card
7122         mmc_set_drvdata(card, md);
7123         add_disk(md->disk);
7124         return 0;
7125 -
7126 - out:
7127 -       mmc_blk_put(md);
7128 -
7129 -       return err;
7130  }
7131  
7132  static void mmc_blk_remove(struct mmc_card *card)
7133 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/mmc/card/queue.c kernel-2.6.28-20094803.3+0m5/drivers/mmc/card/queue.c
7134 --- kernel-2.6.28-20094102.6+0m5/drivers/mmc/card/queue.c       2008-12-25 00:26:37.000000000 +0100
7135 +++ kernel-2.6.28-20094803.3+0m5/drivers/mmc/card/queue.c       2011-09-04 11:37:54.000000000 +0200
7136 @@ -91,9 +91,9 @@ static void mmc_request(struct request_q
7137         int ret;
7138  
7139         if (!mq) {
7140 -               printk(KERN_ERR "MMC: killing requests for dead queue\n");
7141                 while ((req = elv_next_request(q)) != NULL) {
7142                         do {
7143 +                               req->cmd_flags |= REQ_QUIET;
7144                                 ret = __blk_end_request(req, -EIO,
7145                                                         blk_rq_cur_bytes(req));
7146                         } while (ret);
7147 @@ -228,17 +228,18 @@ void mmc_cleanup_queue(struct mmc_queue
7148         struct request_queue *q = mq->queue;
7149         unsigned long flags;
7150  
7151 -       /* Mark that we should start throwing out stragglers */
7152 -       spin_lock_irqsave(q->queue_lock, flags);
7153 -       q->queuedata = NULL;
7154 -       spin_unlock_irqrestore(q->queue_lock, flags);
7155 -
7156         /* Make sure the queue isn't suspended, as that will deadlock */
7157         mmc_queue_resume(mq);
7158  
7159         /* Then terminate our worker thread */
7160         kthread_stop(mq->thread);
7161  
7162 +       /* Empty the queue */
7163 +       spin_lock_irqsave(q->queue_lock, flags);
7164 +       q->queuedata = NULL;
7165 +       blk_start_queue(q);
7166 +       spin_unlock_irqrestore(q->queue_lock, flags);
7167 +
7168         if (mq->bounce_sg)
7169                 kfree(mq->bounce_sg);
7170         mq->bounce_sg = NULL;
7171 @@ -250,8 +251,6 @@ void mmc_cleanup_queue(struct mmc_queue
7172                 kfree(mq->bounce_buf);
7173         mq->bounce_buf = NULL;
7174  
7175 -       blk_cleanup_queue(mq->queue);
7176 -
7177         mq->card = NULL;
7178  }
7179  EXPORT_SYMBOL(mmc_cleanup_queue);
7180 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/mmc/host/omap_hsmmc.c kernel-2.6.28-20094803.3+0m5/drivers/mmc/host/omap_hsmmc.c
7181 --- kernel-2.6.28-20094102.6+0m5/drivers/mmc/host/omap_hsmmc.c  2011-09-04 11:36:23.000000000 +0200
7182 +++ kernel-2.6.28-20094803.3+0m5/drivers/mmc/host/omap_hsmmc.c  2011-09-04 11:37:54.000000000 +0200
7183 @@ -1058,9 +1058,9 @@ static void omap_hsmmc_request(struct mm
7184                                         ;
7185                                 host->reqs_blocked += 1;
7186                         }
7187 -                       req->cmd->error = -EBADF;
7188 +                       req->cmd->error = -ENODEV;
7189                         if (req->data)
7190 -                               req->data->error = -EBADF;
7191 +                               req->data->error = -ENODEV;
7192                         enable_irq(host->irq);
7193                         mmc_request_done(mmc, req);
7194                         return;
7195 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_acx.c kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_acx.c
7196 --- kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_acx.c       2011-09-04 11:36:23.000000000 +0200
7197 +++ kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_acx.c       2011-09-04 11:37:54.000000000 +0200
7198 @@ -1040,6 +1040,34 @@ out:
7199         return ret;
7200  }
7201  
7202 +int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
7203 +                         u8 max_consecutive)
7204 +{
7205 +       struct wl1251_acx_bet_enable *acx;
7206 +       int ret;
7207 +
7208 +       wl1251_debug(DEBUG_ACX, "acx bet enable");
7209 +
7210 +       acx = kzalloc(sizeof(*acx), GFP_KERNEL);
7211 +       if (!acx) {
7212 +               ret = -ENOMEM;
7213 +               goto out;
7214 +       }
7215 +
7216 +       acx->enable = mode;
7217 +       acx->max_consecutive = max_consecutive;
7218 +
7219 +       ret = wl1251_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
7220 +       if (ret < 0) {
7221 +               wl1251_warning("wl1251 acx bet enable failed: %d", ret);
7222 +               goto out;
7223 +       }
7224 +
7225 +out:
7226 +       kfree(acx);
7227 +       return ret;
7228 +}
7229 +
7230  int wl1251_acx_ip_config(struct wl1251 *wl, bool enable, u8 *address,
7231                          u8 version)
7232  {
7233 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_acx.h kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_acx.h
7234 --- kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_acx.h       2011-09-04 11:36:23.000000000 +0200
7235 +++ kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_acx.h       2011-09-04 11:37:54.000000000 +0200
7236 @@ -1191,7 +1191,6 @@ struct wl1251_acx_mem_map {
7237         u32 num_rx_mem_blocks;
7238  } __attribute__ ((packed));
7239  
7240 -
7241  struct wl1251_acx_wr_tbtt_and_dtim {
7242  
7243         struct acx_header header;
7244 @@ -1222,6 +1221,31 @@ struct wl1251_acx_arp_filter {
7245                                bytes of the the address are ignored.*/
7246  } __attribute__((packed));
7247  
7248 +enum wl1251_acx_bet_mode {
7249 +       WL1251_ACX_BET_DISABLE = 0,
7250 +       WL1251_ACX_BET_ENABLE = 1,
7251 +};
7252 +
7253 +struct wl1251_acx_bet_enable {
7254 +       struct acx_header header;
7255 +
7256 +       /*
7257 +        * Specifies if beacon early termination procedure is enabled or
7258 +        * disabled, see enum wl1251_acx_bet_mode.
7259 +        */
7260 +       u8 enable;
7261 +
7262 +       /*
7263 +        * Specifies the maximum number of consecutive beacons that may be
7264 +        * early terminated. After this number is reached at least one full
7265 +        * beacon must be correctly received in FW before beacon ET
7266 +        * resumes. Range 0 - 255.
7267 +        */
7268 +       u8 max_consecutive;
7269 +
7270 +       u8 padding[2];
7271 +} __attribute__ ((packed));
7272 +
7273  /*************************************************************************
7274  
7275      Host Interrupt Register (WiLink -> Host)
7276 @@ -1384,4 +1408,7 @@ int wl1251_acx_mem_cfg(struct wl1251 *wl
7277  int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim);
7278  int wl1251_acx_ip_config(struct wl1251 *wl, bool enable, u8 *address,
7279                          u8 version);
7280 +int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
7281 +                         u8 max_consecutive);
7282 +
7283  #endif /* __WL1251_ACX_H__ */
7284 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_boot.c kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_boot.c
7285 --- kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_boot.c      2011-09-04 11:36:23.000000000 +0200
7286 +++ kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_boot.c      2011-09-04 11:37:54.000000000 +0200
7287 @@ -305,7 +305,7 @@ int wl1251_boot_run_firmware(struct wl12
7288                 ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
7289                 ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
7290                 REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
7291 -               BT_PTA_PREDICTION_EVENT_ID;
7292 +               BT_PTA_PREDICTION_EVENT_ID | PS_REPORT_EVENT_ID;
7293  
7294         ret = wl1251_event_unmask(wl);
7295         if (ret < 0) {
7296 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_event.c kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_event.c
7297 --- kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_event.c     2011-09-04 11:36:23.000000000 +0200
7298 +++ kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_event.c     2011-09-04 11:37:54.000000000 +0200
7299 @@ -31,10 +31,6 @@
7300  static int wl1251_event_scan_complete(struct wl1251 *wl,
7301                                       struct event_mailbox *mbox)
7302  {
7303 -       wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d",
7304 -                    mbox->scheduled_scan_status,
7305 -                    mbox->scheduled_scan_channels);
7306 -
7307         if (wl->scanning) {
7308                 mutex_unlock(&wl->mutex);
7309                 ieee80211_scan_completed(wl->hw);
7310 @@ -46,11 +42,36 @@ static int wl1251_event_scan_complete(st
7311         return 0;
7312  }
7313  
7314 -static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
7315 -{
7316 -       wl1251_debug(DEBUG_EVENT, "MBOX DUMP:");
7317 -       wl1251_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector);
7318 -       wl1251_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
7319 +#define WL1251_PS_ENTRY_RETRIES  3
7320 +static int wl1251_event_ps_report(struct wl1251 *wl,
7321 +                                 struct event_mailbox *mbox)
7322 +{
7323 +       int ret = 0;
7324 +
7325 +       wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status);
7326 +
7327 +       switch (mbox->ps_status) {
7328 +       case ENTER_POWER_SAVE_FAIL:
7329 +               if (!wl->psm) {
7330 +                       wl->ps_entry_retry = 0;
7331 +                       break;
7332 +               }
7333 +
7334 +               if (wl->ps_entry_retry < WL1251_PS_ENTRY_RETRIES) {
7335 +                       ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
7336 +                       wl->ps_entry_retry++;
7337 +               } else {
7338 +                       wl1251_error("Power save entry failed, giving up");
7339 +                       wl->ps_entry_retry = 0;
7340 +               }
7341 +               break;
7342 +       case ENTER_POWER_SAVE_SUCCESS:
7343 +       default:
7344 +               wl->ps_entry_retry = 0;
7345 +               break;
7346 +       }
7347 +
7348 +       return 0;
7349  }
7350  
7351  static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
7352 @@ -58,10 +79,7 @@ static int wl1251_event_process(struct w
7353         int ret;
7354         u32 vector;
7355  
7356 -       wl1251_event_mbox_dump(mbox);
7357 -
7358         vector = mbox->events_vector & ~(mbox->events_mask);
7359 -       wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector);
7360  
7361         if (vector & SCAN_COMPLETE_EVENT_ID) {
7362                 ret = wl1251_event_scan_complete(wl, mbox);
7363 @@ -79,7 +97,14 @@ static int wl1251_event_process(struct w
7364                 }
7365         }
7366  
7367 -       if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) {
7368 +       if (vector & PS_REPORT_EVENT_ID) {
7369 +               wl1251_debug(DEBUG_EVENT, "PS_REPORT_EVENT_ID");
7370 +               ret = wl1251_event_ps_report(wl, mbox);
7371 +               if (ret < 0)
7372 +                       return ret;
7373 +       }
7374 +
7375 +       if (wl->vif && (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID)) {
7376                 wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
7377                 /* need to unlock mutex to avoid deadlocking with rtnl */
7378                 mutex_unlock(&wl->mutex);
7379 @@ -97,11 +122,16 @@ static int wl1251_event_process(struct w
7380                 }
7381         }
7382  
7383 -       if (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID)
7384 +       if (wl->vif && (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID)) {
7385 +               wl1251_debug(DEBUG_EVENT, "ROAMING_TRIGGER_LOW_RSSI_EVENT");
7386                 ieee80211_rssi_changed(wl->vif, IEEE80211_RSSI_STATE_LOW);
7387 +       }
7388  
7389 -       if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID)
7390 +       if (wl->vif && (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID)) {
7391 +               wl1251_debug(DEBUG_EVENT,
7392 +                            "ROAMING_TRIGGER_REGAINED_RSSI_EVENT");
7393                 ieee80211_rssi_changed(wl->vif, IEEE80211_RSSI_STATE_HIGH);
7394 +       }
7395  
7396         return 0;
7397  }
7398 @@ -121,9 +151,6 @@ void wl1251_event_mbox_config(struct wl1
7399  {
7400         wl->mbox_ptr[0] = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
7401         wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
7402 -
7403 -       wl1251_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
7404 -                    wl->mbox_ptr[0], wl->mbox_ptr[1]);
7405  }
7406  
7407  int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
7408 @@ -131,8 +158,6 @@ int wl1251_event_handle(struct wl1251 *w
7409         struct event_mailbox mbox;
7410         int ret;
7411  
7412 -       wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
7413 -
7414         if (mbox_num > 1)
7415                 return -EINVAL;
7416  
7417 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_event.h kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_event.h
7418 --- kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_event.h     2011-09-04 11:36:23.000000000 +0200
7419 +++ kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_event.h     2011-09-04 11:37:54.000000000 +0200
7420 @@ -75,6 +75,13 @@ enum {
7421         EVENT_MBOX_ALL_EVENT_ID                  = 0x7fffffff,
7422  };
7423  
7424 +enum {
7425 +       ENTER_POWER_SAVE_FAIL =  0,
7426 +       ENTER_POWER_SAVE_SUCCESS,
7427 +       EXIT_POWER_SAVE_FAIL,
7428 +       EXIT_POWER_SAVE_SUCCESS
7429 +};
7430 +
7431  struct event_debug_report {
7432         u8 debug_event_id;
7433         u8 num_params;
7434 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251.h kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251.h
7435 --- kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251.h   2011-09-04 11:36:23.000000000 +0200
7436 +++ kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251.h   2011-09-04 11:37:54.000000000 +0200
7437 @@ -356,7 +356,7 @@ struct wl1251 {
7438         /* Are we currently scanning */
7439         bool scanning;
7440  
7441 -       u32 last_event;
7442 +       unsigned long last_event;
7443  
7444         /* Our association ID */
7445         u16 aid;
7446 @@ -381,6 +381,8 @@ struct wl1251 {
7447         /* PSM mode requested */
7448         bool psm_requested;
7449  
7450 +       u8 ps_entry_retry;
7451 +
7452         u16 beacon_int;
7453         u8 dtim_period;
7454  
7455 @@ -423,6 +425,8 @@ int wl1251_plt_stop(struct wl1251 *wl);
7456  
7457  #define WL1251_DEFAULT_CHANNEL 0
7458  
7459 +#define WL1251_DEFAULT_BET_CONSECUTIVE 10
7460 +
7461  #define CHIP_ID_1251_PG10                 (0x7010101)
7462  #define CHIP_ID_1251_PG11                 (0x7020101)
7463  #define CHIP_ID_1251_PG12                 (0x7030101)
7464 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_main.c kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_main.c
7465 --- kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_main.c      2011-09-04 11:36:23.000000000 +0200
7466 +++ kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_main.c      2011-09-04 11:37:54.000000000 +0200
7467 @@ -939,6 +939,7 @@ static void wl1251_op_stop(struct ieee80
7468         wl->next_tx_complete = 0;
7469         wl->elp = false;
7470         wl->psm = 0;
7471 +       wl->ps_entry_retry = 0;
7472         wl->tx_queue_stopped = false;
7473         wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
7474         wl->channel = WL1251_DEFAULT_CHANNEL;
7475 @@ -1092,6 +1093,7 @@ static int wl1251_op_config_interface(st
7476         struct wl1251 *wl = hw->priv;
7477         struct sk_buff *beacon;
7478         DECLARE_MAC_BUF(mac);
7479 +       bool do_join = false;
7480         int ret;
7481  
7482         wl1251_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %s",
7483 @@ -1105,23 +1107,21 @@ static int wl1251_op_config_interface(st
7484         if (ret < 0)
7485                 goto out;
7486  
7487 +       if (!is_zero_ether_addr(conf->bssid))
7488 +               do_join = true;
7489 +
7490         memcpy(wl->bssid, conf->bssid, ETH_ALEN);
7491  
7492 -       ret = wl1251_build_null_data(wl);
7493 -       if (ret < 0)
7494 -               goto out_sleep;
7495 +       if (do_join) {
7496 +               ret = wl1251_build_null_data(wl);
7497 +               if (ret < 0)
7498 +                       goto out_sleep;
7499 +       }
7500  
7501         wl->ssid_len = conf->ssid_len;
7502         if (wl->ssid_len)
7503                 memcpy(wl->ssid, conf->ssid, wl->ssid_len);
7504  
7505 -       if (wl->bss_type != BSS_TYPE_IBSS) {
7506 -               ret = wl1251_join(wl, wl->bss_type, wl->channel,
7507 -                                 wl->beacon_int, wl->dtim_period);
7508 -               if (ret < 0)
7509 -                       goto out_sleep;
7510 -       }
7511 -
7512         if (conf->changed & IEEE80211_IFCC_BEACON) {
7513                 beacon = ieee80211_beacon_get(hw, vif);
7514                 wl1251_update_support_rates((struct wl12xx_beacon_template *)
7515 @@ -1142,7 +1142,9 @@ static int wl1251_op_config_interface(st
7516  
7517                 if (ret < 0)
7518                         goto out_sleep;
7519 +       }
7520  
7521 +       if (do_join) {
7522                 ret = wl1251_join(wl, wl->bss_type, wl->channel,
7523                                   wl->beacon_int, wl->dtim_period);
7524                 if (ret < 0)
7525 @@ -1177,18 +1179,7 @@ static int wl1251_op_config(struct ieee8
7526         if (ret < 0)
7527                 goto out;
7528  
7529 -       if (channel != wl->channel) {
7530 -               wl->channel = channel;
7531 -
7532 -               ret = wl1251_join(wl, wl->bss_type, wl->channel,
7533 -                                 wl->beacon_int, wl->dtim_period);
7534 -               if (ret < 0)
7535 -                       goto out_sleep;
7536 -       }
7537 -
7538 -       ret = wl1251_build_null_data(wl);
7539 -       if (ret < 0)
7540 -               goto out_sleep;
7541 +       wl->channel = channel;
7542  
7543         if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
7544                 wl1251_debug(DEBUG_PSM, "psm enabled");
7545 @@ -1215,7 +1206,7 @@ static int wl1251_op_config(struct ieee8
7546         if (conf->power_level != wl->power_level) {
7547                 ret = wl1251_acx_tx_power(wl, conf->power_level);
7548                 if (ret < 0)
7549 -                       goto out;
7550 +                       goto out_sleep;
7551  
7552                 wl->power_level = conf->power_level;
7553         }
7554 @@ -1939,6 +1930,7 @@ static int __devinit wl1251_probe(struct
7555         wl->elp = false;
7556         wl->psm = 0;
7557         wl->psm_requested = false;
7558 +       wl->ps_entry_retry = 0;
7559         wl->tx_queue_stopped = false;
7560         wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
7561         wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
7562 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_ps.c kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_ps.c
7563 --- kernel-2.6.28-20094102.6+0m5/drivers/net/wireless/wl12xx/wl1251_ps.c        2011-09-04 11:36:23.000000000 +0200
7564 +++ kernel-2.6.28-20094803.3+0m5/drivers/net/wireless/wl12xx/wl1251_ps.c        2011-09-04 11:37:54.000000000 +0200
7565 @@ -151,6 +151,11 @@ int wl1251_ps_set_mode(struct wl1251 *wl
7566                 if (ret < 0)
7567                         return ret;
7568  
7569 +               ret = wl1251_acx_bet_enable(wl, WL1251_ACX_BET_ENABLE,
7570 +                                           WL1251_DEFAULT_BET_CONSECUTIVE);
7571 +               if (ret < 0)
7572 +                       return ret;
7573 +
7574                 ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
7575                 if (ret < 0)
7576                         return ret;
7577 @@ -168,6 +173,12 @@ int wl1251_ps_set_mode(struct wl1251 *wl
7578                 if (ret < 0)
7579                         return ret;
7580  
7581 +               /* disable BET */
7582 +               ret = wl1251_acx_bet_enable(wl, WL1251_ACX_BET_DISABLE,
7583 +                                           WL1251_DEFAULT_BET_CONSECUTIVE);
7584 +               if (ret < 0)
7585 +                       return ret;
7586 +
7587                 /* disable beacon filtering */
7588                 ret = wl1251_acx_beacon_filter_opt(wl, false);
7589                 if (ret < 0)
7590 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/usb/gadget/file_storage.c kernel-2.6.28-20094803.3+0m5/drivers/usb/gadget/file_storage.c
7591 --- kernel-2.6.28-20094102.6+0m5/drivers/usb/gadget/file_storage.c      2011-09-04 11:36:23.000000000 +0200
7592 +++ kernel-2.6.28-20094803.3+0m5/drivers/usb/gadget/file_storage.c      2011-09-04 11:37:54.000000000 +0200
7593 @@ -606,6 +606,10 @@ enum fsg_buffer_state {
7594  struct fsg_dev;
7595  
7596  struct fsg_buffhd {
7597 +       struct rb_node                  rb_node;
7598 +       sector_t                        sector;
7599 +       int                             sectors;
7600 +
7601         void                            *buf;
7602         size_t                          buflen;
7603         enum fsg_buffer_state           state;
7604 @@ -694,6 +698,9 @@ struct fsg_dev {
7605         struct fsg_buffhd       buffhds[NUM_BUFFERS];
7606         int                     num_buffers;
7607  
7608 +       /* Tree to find direct I/O's with overlapping sectors */
7609 +       struct rb_root          bio_tree;
7610 +
7611         int                     thread_wakeup_needed;
7612         struct completion       thread_notifier;
7613         struct task_struct      *thread_task;
7614 @@ -1055,6 +1062,58 @@ static struct usb_gadget_strings stringt
7615         .strings        = strings,
7616  };
7617  
7618 +/*
7619 + *     Find overlapped bio in fsg->bio_tree rb tree.
7620 + */
7621 +static int fsg_rbtree_find(struct fsg_dev *fsg, sector_t s,
7622 +               unsigned int sectors)
7623 +{
7624 +       struct rb_node *n;
7625 +       struct fsg_buffhd *tmp;
7626 +       int found = 0;
7627 +
7628 +       spin_lock_irq(&fsg->lock);
7629 +       n = fsg->bio_tree.rb_node;
7630 +       while (n) {
7631 +               tmp = rb_entry(n, struct fsg_buffhd, rb_node);
7632 +               if (s + sectors <= tmp->sector)
7633 +                       n = n->rb_left;
7634 +               else if (s >= tmp->sector + tmp->sectors)
7635 +                       n = n->rb_right;
7636 +               else {
7637 +                       found = 1;
7638 +                       break;
7639 +               }
7640 +       }
7641 +       spin_unlock_irq(&fsg->lock);
7642 +       return found;
7643 +}
7644 +
7645 +/*
7646 + * Insert a node into the fsg->bio_tree rb tree.
7647 + */
7648 +static void fsg_rbtree_insert(struct fsg_dev *fsg, struct fsg_buffhd *node)
7649 +{
7650 +       struct rb_node **p;
7651 +       struct rb_node *parent = NULL;
7652 +       struct fsg_buffhd *tmp;
7653 +
7654 +       spin_lock_irq(&fsg->lock);
7655 +       p = &fsg->bio_tree.rb_node;
7656 +
7657 +       while (*p) {
7658 +               parent = *p;
7659 +               tmp = rb_entry(parent, struct fsg_buffhd, rb_node);
7660 +               if (node->sector < tmp->sector)
7661 +                       p = &(*p)->rb_left;
7662 +               else
7663 +                       p = &(*p)->rb_right;
7664 +       }
7665 +       rb_link_node(&node->rb_node, parent, p);
7666 +       rb_insert_color(&node->rb_node, &fsg->bio_tree);
7667 +       spin_unlock_irq(&fsg->lock);
7668 +}
7669 +
7670  /** UGLY UGLY HACK: Windows problems with multiple
7671   * configurations.
7672   *
7673 @@ -1721,7 +1780,8 @@ static void direct_read_end_io(struct bi
7674   * or b) more than one bio must be submitted
7675   */
7676  /* FIXME: Needs an equivalent of readahead */
7677 -static ssize_t direct_read(struct file *file, char *buf, size_t amount, loff_t *pos)
7678 +static ssize_t direct_read(struct file *file, struct fsg_buffhd *bh,
7679 +               size_t amount, loff_t *pos)
7680  {
7681         DECLARE_COMPLETION_ONSTACK(wait);
7682         unsigned max_pages = (amount >> PAGE_SHIFT) + 1;
7683 @@ -1729,7 +1789,8 @@ static ssize_t direct_read(struct file *
7684         ssize_t totlen = 0;
7685         struct page *page;
7686         struct bio *bio;
7687 -       char *p = buf;
7688 +       char *p = bh->buf;
7689 +       int rc;
7690  
7691         if (!amount)
7692                 return 0;
7693 @@ -1767,6 +1828,15 @@ static ssize_t direct_read(struct file *
7694                 return -EINVAL;
7695         }
7696  
7697 +       while (fsg_rbtree_find(bh->fsg, bio->bi_sector,
7698 +               bio_sectors(bio))) {
7699 +               rc = sleep_thread(bh->fsg);
7700 +               if (rc) {
7701 +                       bio_put(bio);
7702 +                       return rc;
7703 +               }
7704 +       }
7705 +
7706         submit_bio(READ, bio);
7707  
7708         wait_for_completion(&wait);
7709 @@ -1865,7 +1935,7 @@ static int do_read(struct fsg_dev *fsg)
7710                 /* Perform the read */
7711                 file_offset_tmp = file_offset;
7712                 if (curlun->direct)
7713 -                       nread = direct_read(curlun->filp, bh->buf,
7714 +                       nread = direct_read(curlun->filp, bh,
7715                                         amount, &file_offset_tmp);
7716                 else
7717                         nread = vfs_read(curlun->filp,
7718 @@ -1920,6 +1990,7 @@ static void direct_write_end_io(struct b
7719  {
7720         struct fsg_buffhd *bh = bio->bi_private;
7721         struct fsg_dev *fsg = bh->fsg;
7722 +       unsigned long flags;
7723  
7724         if (err) {
7725                 /* FIXME: how to let host know about this error */
7726 @@ -1927,11 +1998,13 @@ static void direct_write_end_io(struct b
7727                 clear_bit(BIO_UPTODATE, &bio->bi_flags);
7728         }
7729  
7730 +       /* FIXME: smp barriers are not necessary for this this driver */
7731         smp_wmb();
7732 -       spin_lock(&fsg->lock);
7733 +       spin_lock_irqsave(&fsg->lock, flags);
7734 +       rb_erase(&bh->rb_node, &fsg->bio_tree);
7735         bh->state = BUF_STATE_EMPTY;
7736         wakeup_thread(fsg);
7737 -       spin_unlock(&fsg->lock);
7738 +       spin_unlock_irqrestore(&fsg->lock, flags);
7739  
7740         bio_put(bio);
7741  }
7742 @@ -1949,6 +2022,7 @@ static ssize_t direct_write(struct file
7743         struct page *page;
7744         struct bio *bio;
7745         char *p = bh->buf;
7746 +       int rc;
7747  
7748         if (!amount)
7749                 return 0;
7750 @@ -1987,6 +2061,16 @@ static ssize_t direct_write(struct file
7751         }
7752  
7753         bh->state = BUF_STATE_BUSY;
7754 +       bh->sector = bio->bi_sector;
7755 +       bh->sectors = bio_sectors(bio);
7756 +       while (fsg_rbtree_find(bh->fsg, bh->sector, bh->sectors)) {
7757 +               rc = sleep_thread(bh->fsg);
7758 +               if (rc) {
7759 +                       bio_put(bio);
7760 +                       return rc;
7761 +               }
7762 +       }
7763 +       fsg_rbtree_insert(bh->fsg, bh);
7764  
7765         submit_bio(WRITE, bio);
7766  
7767 @@ -4456,6 +4540,7 @@ static int __init fsg_bind(struct usb_ga
7768                 bh->next = bh + 1;
7769         }
7770         fsg->buffhds[fsg->num_buffers - 1].next = &fsg->buffhds[0];
7771 +       fsg->bio_tree = RB_ROOT;
7772  
7773         snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
7774                         init_utsname()->sysname, init_utsname()->release,
7775 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/usb/musb/musb_core.c kernel-2.6.28-20094803.3+0m5/drivers/usb/musb/musb_core.c
7776 --- kernel-2.6.28-20094102.6+0m5/drivers/usb/musb/musb_core.c   2011-09-04 11:36:23.000000000 +0200
7777 +++ kernel-2.6.28-20094803.3+0m5/drivers/usb/musb/musb_core.c   2011-09-04 11:37:54.000000000 +0200
7778 @@ -235,6 +235,19 @@ static int musb_charger_detect(struct mu
7779                         /* we always reset transceiver */
7780                         check_charger = 1;
7781  
7782 +                       /* HACK: ULPI tends to get stuck when booting with
7783 +                        * the cable connected
7784 +                        */
7785 +                       r = musb_readb(musb->mregs, MUSB_DEVCTL);
7786 +                       if ((r & MUSB_DEVCTL_VBUS)
7787 +                                       == (3 << MUSB_DEVCTL_VBUS_SHIFT)) {
7788 +                               musb_save_ctx_and_suspend(&musb->g, 0);
7789 +                               musb_restore_ctx_and_resume(&musb->g);
7790 +                               if (musb->board && musb->board->set_pm_limits)
7791 +                                       musb->board->set_pm_limits(
7792 +                                                       musb->controller, 1);
7793 +                       }
7794 +
7795                         /* disable RESET and RESUME interrupts */
7796                         r = musb_readb(musb->mregs, MUSB_INTRUSBE);
7797                         r &= ~(MUSB_INTR_RESUME | MUSB_INTR_RESET);
7798 @@ -2113,19 +2126,8 @@ static void musb_irq_work(struct work_st
7799  {
7800         struct musb *musb = container_of(data, struct musb, irq_work);
7801         static int old_state, old_ma, old_suspend;
7802 -       u8 devctl;
7803  
7804         if (musb->xceiv->state != old_state) {
7805 -               devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
7806 -               if (musb->xceiv->state == OTG_STATE_B_IDLE &&
7807 -                                       (devctl & MUSB_DEVCTL_VBUS))
7808 -                       goto keep_limit;
7809 -
7810 -               /* clear/set requirements for musb to work with DPS on omap3 */
7811 -               if (musb->board && musb->board->set_pm_limits)
7812 -                       musb->board->set_pm_limits(musb->controller,
7813 -                               (musb->xceiv->state == OTG_STATE_B_PERIPHERAL));
7814 -keep_limit:
7815                 old_state = musb->xceiv->state;
7816                 sysfs_notify(&musb->controller->kobj, NULL, "mode");
7817         }
7818 @@ -2457,6 +2459,12 @@ bad_config:
7819         if (status)
7820                 goto fail2;
7821  
7822 +       /* Resets the controller. Has to be done. Without this, most likely
7823 +        * the state machine inside the transceiver doesn't get fixed properly
7824 +        */
7825 +       musb_save_ctx_and_suspend(&musb->g, 0);
7826 +       musb_restore_ctx_and_resume(&musb->g);
7827 +
7828         return 0;
7829  
7830  fail2:
7831 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/usb/musb/musb_core.h kernel-2.6.28-20094803.3+0m5/drivers/usb/musb/musb_core.h
7832 --- kernel-2.6.28-20094102.6+0m5/drivers/usb/musb/musb_core.h   2011-09-04 11:36:23.000000000 +0200
7833 +++ kernel-2.6.28-20094803.3+0m5/drivers/usb/musb/musb_core.h   2011-09-04 11:37:54.000000000 +0200
7834 @@ -360,6 +360,7 @@ struct musb {
7835         struct clk              *clock;
7836         irqreturn_t             (*isr)(int, void *);
7837         struct work_struct      irq_work;
7838 +       struct work_struct      vbus_work;
7839  
7840  /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
7841  #define MUSB_PORT_STAT_RESUME  (1 << 31)
7842 diff -Nurp kernel-2.6.28-20094102.6+0m5/drivers/usb/musb/omap2430.c kernel-2.6.28-20094803.3+0m5/drivers/usb/musb/omap2430.c
7843 --- kernel-2.6.28-20094102.6+0m5/drivers/usb/musb/omap2430.c    2011-09-04 11:36:23.000000000 +0200
7844 +++ kernel-2.6.28-20094803.3+0m5/drivers/usb/musb/omap2430.c    2011-09-04 11:37:54.000000000 +0200
7845 @@ -49,6 +49,17 @@
7846  
7847  static struct timer_list musb_idle_timer;
7848  
7849 +static void musb_vbus_work(struct work_struct *data)
7850 +{
7851 +       struct musb *musb = container_of(data, struct musb, vbus_work);
7852 +       u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
7853 +
7854 +       /* clear/set requirements for musb to work with DPS on omap3 */
7855 +       if (musb->board && musb->board->set_pm_limits && !musb->is_charger)
7856 +               musb->board->set_pm_limits(musb->controller,
7857 +                                       (devctl & MUSB_DEVCTL_VBUS));
7858 +}
7859 +
7860  static void musb_do_idle(unsigned long _musb)
7861  {
7862         struct musb     *musb = (void *)_musb;
7863 @@ -276,6 +287,7 @@ int __init musb_platform_init(struct mus
7864         musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON;
7865  
7866         setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
7867 +       INIT_WORK(&musb->vbus_work, musb_vbus_work);
7868  
7869         return 0;
7870  }
7871 @@ -448,6 +460,9 @@ void musb_restore_ctx_and_resume(struct
7872  
7873         /* Restore register context */
7874         musb_restore_ctx(musb);
7875 +
7876 +       /* set constraints */
7877 +       schedule_work(&musb->vbus_work);
7878         spin_unlock_irqrestore(&musb->lock, flags);
7879  }
7880  EXPORT_SYMBOL_GPL(musb_restore_ctx_and_resume);
7881 diff -Nurp kernel-2.6.28-20094102.6+0m5/include/linux/ssi_driver_if.h kernel-2.6.28-20094803.3+0m5/include/linux/ssi_driver_if.h
7882 --- kernel-2.6.28-20094102.6+0m5/include/linux/ssi_driver_if.h  2011-09-04 11:36:23.000000000 +0200
7883 +++ kernel-2.6.28-20094803.3+0m5/include/linux/ssi_driver_if.h  2011-09-04 11:37:54.000000000 +0200
7884 @@ -31,6 +31,10 @@
7885  /* The number of ports handled by the driver. (MAX:2) */
7886  #define SSI_MAX_PORTS          1
7887  
7888 +#define SSI_MAX_FRAME_SIZE     0x1f
7889 +#define SSI_MAX_RX_TIMEOUT     0x1ff
7890 +#define SSI_MAX_TX_DIVISOR     0x7f
7891 +
7892  #define ANY_SSI_CONTROLLER     -1
7893  #define ANY_CHANNEL            -1
7894  #define CHANNEL(channel)       (1 << (channel))
7895 @@ -42,6 +46,7 @@ enum {
7896         SSI_EVENT_POST_SPEED_CHANGE,
7897         SSI_EVENT_CAWAKE_UP,
7898         SSI_EVENT_CAWAKE_DOWN,
7899 +       SSI_EVENT_SSR_DATAAVAILABLE,
7900  };
7901  
7902  enum {
7903 @@ -52,6 +57,10 @@ enum {
7904         SSI_IOCTL_FLUSH_RX,
7905         SSI_IOCTL_FLUSH_TX,
7906         SSI_IOCTL_CAWAKE,
7907 +       SSI_IOCTL_SET_RX,
7908 +       SSI_IOCTL_GET_RX,
7909 +       SSI_IOCTL_SET_TX,
7910 +       SSI_IOCTL_GET_TX,
7911         SSI_IOCTL_TX_CH_FULL,
7912         SSI_IOCTL_CH_DATAACCEPT,
7913  };
7914 @@ -142,6 +151,7 @@ int ssi_write(struct ssi_device *dev, u3
7915  void ssi_write_cancel(struct ssi_device *dev);
7916  int ssi_read(struct ssi_device *dev, u32 *data, unsigned int w_count);
7917  void ssi_read_cancel(struct ssi_device *dev);
7918 +int ssi_poll(struct ssi_device *dev);
7919  int ssi_ioctl(struct ssi_device *dev, unsigned int command, void *arg);
7920  void ssi_close(struct ssi_device *dev);
7921  void ssi_set_read_cb(struct ssi_device *dev,
7922 diff -Nurp kernel-2.6.28-20094102.6+0m5/include/linux/ssi_char.h kernel-2.6.28-20094803.3+0m5/include/linux/ssi_char.h
7923 --- kernel-2.6.28-20094102.6+0m5/include/linux/ssi_char.h       1970-01-01 01:00:00.000000000 +0100
7924 +++ kernel-2.6.28-20094803.3+0m5/include/linux/ssi_char.h       2011-09-04 11:37:54.000000000 +0200
7925 @@ -0,0 +1,71 @@
7926 +/*
7927 + * ssi_char.h
7928 + *
7929 + * Part of the SSI character device driver.
7930 + *
7931 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
7932 + *
7933 + * Contact: Andras Domokos <andras.domokos@nokia.com>
7934 + *
7935 + * This program is free software; you can redistribute it and/or
7936 + * modify it under the terms of the GNU General Public License
7937 + * version 2 as published by the Free Software Foundation.
7938 + *
7939 + * This program is distributed in the hope that it will be useful, but
7940 + * WITHOUT ANY WARRANTY; without even the implied warranty of
7941 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7942 + * General Public License for more details.
7943 + *
7944 + * You should have received a copy of the GNU General Public License
7945 + * along with this program; if not, write to the Free Software
7946 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
7947 + * 02110-1301 USA
7948 + */
7949 +
7950 +
7951 +#ifndef SSI_CHAR_H
7952 +#define SSI_CHAR_H
7953 +
7954 +#define SSI_CHAR_BASE          'S'
7955 +#define CS_IOW(num, dtype)     _IOW(SSI_CHAR_BASE, num, dtype)
7956 +#define CS_IOR(num, dtype)     _IOR(SSI_CHAR_BASE, num, dtype)
7957 +#define CS_IOWR(num, dtype)    _IOWR(SSI_CHAR_BASE, num, dtype)
7958 +#define CS_IO(num)             _IO(SSI_CHAR_BASE, num)
7959 +
7960 +#define CS_SEND_BREAK          CS_IO(1)
7961 +#define CS_FLUSH_RX            CS_IO(2)
7962 +#define CS_FLUSH_TX            CS_IO(3)
7963 +#define CS_BOOTSTRAP           CS_IO(4)
7964 +#define CS_SET_WAKELINE                CS_IOW(5, unsigned int)
7965 +#define CS_GET_WAKELINE                CS_IOR(6, unsigned int)
7966 +#define CS_SET_RX              CS_IOW(7, struct ssi_rx_config)
7967 +#define CS_GET_RX              CS_IOW(8, struct ssi_rx_config)
7968 +#define CS_SET_TX              CS_IOW(9, struct ssi_tx_config)
7969 +#define CS_GET_TX              CS_IOW(10, struct ssi_tx_config)
7970 +
7971 +#define SSI_MODE_SLEEP         0
7972 +#define SSI_MODE_STREAM                1
7973 +#define SSI_MODE_FRAME         2
7974 +
7975 +#define SSI_ARBMODE_RR         0
7976 +#define SSI_ARBMODE_PRIO       1
7977 +
7978 +#define WAKE_UP                        0
7979 +#define WAKE_DOWN              1
7980 +
7981 +struct ssi_tx_config {
7982 +       u32 mode;
7983 +       u32 frame_size;
7984 +       u32 channels;
7985 +       u32 divisor;
7986 +       u32 arb_mode;
7987 +};
7988 +
7989 +struct ssi_rx_config {
7990 +       u32 mode;
7991 +       u32 frame_size;
7992 +       u32 channels;
7993 +       u32 timeout;
7994 +};
7995 +
7996 +#endif /* SSI_CHAR_H */
7997 diff -Nurp kernel-2.6.28-20094102.6+0m5/lib/Kconfig.debug kernel-2.6.28-20094803.3+0m5/lib/Kconfig.debug
7998 --- kernel-2.6.28-20094102.6+0m5/lib/Kconfig.debug      2008-12-25 00:26:37.000000000 +0100
7999 +++ kernel-2.6.28-20094803.3+0m5/lib/Kconfig.debug      2011-09-04 11:37:54.000000000 +0200
8000 @@ -731,6 +731,12 @@ config FAULT_INJECTION_DEBUG_FS
8001         help
8002           Enable configuration of fault-injection capabilities via debugfs.
8003  
8004 +config PANIC_INFO_BUFF
8005 +       tristate "Buffer to be printed at panic"
8006 +       depends on DEBUG_FS
8007 +       help
8008 +         Provide a small buffer which will be printed at panic.
8009 +
8010  config FAULT_INJECTION_STACKTRACE_FILTER
8011         bool "stacktrace filter for fault-injection capabilities"
8012         depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT
8013 diff -Nurp kernel-2.6.28-20094102.6+0m5/mm/memory.c kernel-2.6.28-20094803.3+0m5/mm/memory.c
8014 --- kernel-2.6.28-20094102.6+0m5/mm/memory.c    2008-12-25 00:26:37.000000000 +0100
8015 +++ kernel-2.6.28-20094803.3+0m5/mm/memory.c    2011-09-04 11:37:54.000000000 +0200
8016 @@ -1110,6 +1110,7 @@ no_page_table:
8017         }
8018         return page;
8019  }
8020 +EXPORT_SYMBOL_GPL(follow_page);
8021  
8022  /* Can we do the FOLL_ANON optimization? */
8023  static inline int use_zero_page(struct vm_area_struct *vma)
8024 diff -Nurp kernel-2.6.28-20094102.6+0m5/mm/swapfile.c kernel-2.6.28-20094803.3+0m5/mm/swapfile.c
8025 --- kernel-2.6.28-20094102.6+0m5/mm/swapfile.c  2011-09-04 11:36:23.000000000 +0200
8026 +++ kernel-2.6.28-20094803.3+0m5/mm/swapfile.c  2011-09-04 11:37:54.000000000 +0200
8027 @@ -1103,9 +1103,14 @@ sector_t map_swap_page(struct swap_info_
8028                 /* Update the free pages gap */
8029                 sis->gap_next += 1;
8030         } else {
8031 -               /* Always read from the existing re-mapping */
8032 -               BUG_ON(!old);
8033 -               offset = old;
8034 +               /*
8035 +                * Always read from the existing re-mapping
8036 +                * if there is one. There may not be because
8037 +                * 'swapin_readahead()' has won a race with
8038 +                * 'add_to_swap()'.
8039 +                */
8040 +               if (old)
8041 +                       offset = old;
8042         }
8043         spin_unlock(&sis->remap_lock);
8044  
8045 diff -Nurp kernel-2.6.28-20094102.6+0m5/net/bluetooth/hci_conn.c kernel-2.6.28-20094803.3+0m5/net/bluetooth/hci_conn.c
8046 --- kernel-2.6.28-20094102.6+0m5/net/bluetooth/hci_conn.c       2011-09-04 11:36:23.000000000 +0200
8047 +++ kernel-2.6.28-20094803.3+0m5/net/bluetooth/hci_conn.c       2011-09-04 11:37:54.000000000 +0200
8048 @@ -211,6 +211,7 @@ struct hci_conn *hci_conn_add(struct hci
8049         conn->type  = type;
8050         conn->mode  = HCI_CM_ACTIVE;
8051         conn->state = BT_OPEN;
8052 +       conn->auth_type = HCI_AT_GENERAL_BONDING;
8053  
8054         conn->power_save = 1;
8055         conn->disc_timeout = HCI_DISCONN_TIMEOUT;
8056 diff -Nurp kernel-2.6.28-20094102.6+0m5/net/mac80211/mlme.c kernel-2.6.28-20094803.3+0m5/net/mac80211/mlme.c
8057 --- kernel-2.6.28-20094102.6+0m5/net/mac80211/mlme.c    2011-09-04 11:36:23.000000000 +0200
8058 +++ kernel-2.6.28-20094803.3+0m5/net/mac80211/mlme.c    2011-09-04 11:37:54.000000000 +0200
8059 @@ -34,7 +34,6 @@
8060  #define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
8061  #define IEEE80211_ASSOC_MAX_TRIES 3
8062  #define IEEE80211_MONITORING_INTERVAL (2 * HZ)
8063 -#define IEEE80211_PROBE_IDLE_TIME (60 * HZ)
8064  #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
8065  #define IEEE80211_SCAN_INTERVAL (2 * HZ)
8066  #define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
8067 @@ -784,6 +783,7 @@ static void ieee80211_direct_probe(struc
8068                 printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n",
8069                        sdata->dev->name, print_mac(mac, ifsta->bssid));
8070                 ifsta->state = IEEE80211_STA_MLME_DISABLED;
8071 +               ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
8072                 ieee80211_sta_send_apinfo(sdata, ifsta);
8073                 return;
8074         }
8075 @@ -1025,6 +1025,8 @@ EXPORT_SYMBOL(ieee80211_rssi_changed);
8076  void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
8077                              struct ieee80211_hdr *hdr)
8078  {
8079 +       struct ieee80211_local *local = sdata->local;
8080 +
8081         /*
8082          * We can postpone the sta.timer whenever receiving unicast frames
8083          * from AP because we know that the connection is working both ways
8084 @@ -1033,7 +1035,8 @@ void ieee80211_sta_rx_notify(struct ieee
8085          * data idle periods for sending the periodical probe request to
8086          * the AP.
8087          */
8088 -       if (!is_multicast_ether_addr(hdr->addr1))
8089 +       if (!is_multicast_ether_addr(hdr->addr1) &&
8090 +           !(local->hw.flags & IEEE80211_HW_BEACON_FILTER))
8091                 mod_timer(&sdata->u.sta.timer,
8092                           jiffies + IEEE80211_MONITORING_INTERVAL);
8093  }
8094 @@ -1046,6 +1049,12 @@ void ieee80211_beacon_loss_work(struct w
8095         struct ieee80211_if_sta *ifsta = &sdata->u.sta;
8096         struct ieee80211_local *local = sdata->local;
8097  
8098 +       if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATED) {
8099 +               printk(KERN_DEBUG "%s reports beacon loss when not "
8100 +                      "associated\n", sdata->dev->name);
8101 +               return;
8102 +       }
8103 +
8104         printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM "
8105                "- sending probe request\n", sdata->dev->name,
8106                sdata->u.sta.bssid);
8107 @@ -1112,8 +1121,7 @@ static void ieee80211_associated(struct
8108          * Beacon filtering is only enabled with power save and then the
8109          * stack should not check for beacon loss.
8110          */
8111 -       if (!((local->hw.flags & IEEE80211_HW_BEACON_FILTER) &&
8112 -             (local->hw.conf.flags & IEEE80211_CONF_PS)) &&
8113 +       if (!(local->hw.flags & IEEE80211_HW_BEACON_FILTER) &&
8114             time_after(jiffies,
8115                        ifsta->last_beacon + IEEE80211_MONITORING_INTERVAL)) {
8116                 printk(KERN_DEBUG "%s: beacon loss from AP %pM "
8117 @@ -1125,11 +1133,6 @@ static void ieee80211_associated(struct
8118  
8119         }
8120  
8121 -       if (time_after(jiffies, sta->last_rx + IEEE80211_PROBE_IDLE_TIME)) {
8122 -               ifsta->flags |= IEEE80211_STA_PROBEREQ_POLL;
8123 -               send_probe = true;
8124 -       }
8125 -
8126   unlock:
8127         rcu_read_unlock();
8128  
8129 @@ -1148,7 +1151,7 @@ static void ieee80211_associated(struct
8130         if (disassoc)
8131                 ieee80211_set_disassoc(sdata, ifsta, true, true,
8132                                         WLAN_REASON_PREV_AUTH_NOT_VALID);
8133 -       else
8134 +       else if (!(local->hw.flags & IEEE80211_HW_BEACON_FILTER))
8135                 mod_timer(&ifsta->timer, jiffies +
8136                                       IEEE80211_MONITORING_INTERVAL);
8137  }
8138 diff -Nurp kernel-2.6.28-20094102.6+0m5/net/wireless/reg.c kernel-2.6.28-20094803.3+0m5/net/wireless/reg.c
8139 --- kernel-2.6.28-20094102.6+0m5/net/wireless/reg.c     2011-09-04 11:36:23.000000000 +0200
8140 +++ kernel-2.6.28-20094803.3+0m5/net/wireless/reg.c     2011-09-04 11:37:54.000000000 +0200
8141 @@ -637,7 +637,7 @@ static void print_rd_rules(const struct
8142         const struct ieee80211_freq_range *freq_range = NULL;
8143         const struct ieee80211_power_rule *power_rule = NULL;
8144  
8145 -       printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), "
8146 +       printk(KERN_DEBUG "\t(start_freq - end_freq @ bandwidth), "
8147                 "(max_antenna_gain, max_eirp)\n");
8148  
8149         for (i = 0; i < rd->n_reg_rules; i++) {
8150 @@ -648,7 +648,7 @@ static void print_rd_rules(const struct
8151                 /* There may not be documentation for max antenna gain
8152                  * in certain regions */
8153                 if (power_rule->max_antenna_gain)
8154 -                       printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), "
8155 +                       printk(KERN_DEBUG "\t(%d KHz - %d KHz @ %d KHz), "
8156                                 "(%d mBi, %d mBm)\n",
8157                                 freq_range->start_freq_khz,
8158                                 freq_range->end_freq_khz,
8159 @@ -656,7 +656,7 @@ static void print_rd_rules(const struct
8160                                 power_rule->max_antenna_gain,
8161                                 power_rule->max_eirp);
8162                 else
8163 -                       printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), "
8164 +                       printk(KERN_DEBUG "\t(%d KHz - %d KHz @ %d KHz), "
8165                                 "(N/A, %d mBm)\n",
8166                                 freq_range->start_freq_khz,
8167                                 freq_range->end_freq_khz,
8168 @@ -669,15 +669,15 @@ static void print_regdomain(const struct
8169  {
8170  
8171         if (is_world_regdom(rd->alpha2))
8172 -               printk(KERN_INFO "cfg80211: World regulatory "
8173 +               printk(KERN_DEBUG "cfg80211: World regulatory "
8174                         "domain updated:\n");
8175         else {
8176                 if (is_unknown_alpha2(rd->alpha2))
8177 -                       printk(KERN_INFO "cfg80211: Regulatory domain "
8178 +                       printk(KERN_DEBUG "cfg80211: Regulatory domain "
8179                                 "changed to driver built-in settings "
8180                                 "(unknown country)\n");
8181                 else
8182 -                       printk(KERN_INFO "cfg80211: Regulatory domain "
8183 +                       printk(KERN_DEBUG "cfg80211: Regulatory domain "
8184                                 "changed to country: %c%c\n",
8185                                 rd->alpha2[0], rd->alpha2[1]);
8186         }
8187 @@ -686,7 +686,7 @@ static void print_regdomain(const struct
8188  
8189  void print_regdomain_info(const struct ieee80211_regdomain *rd)
8190  {
8191 -       printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n",
8192 +       printk(KERN_DEBUG "cfg80211: Regulatory domain: %c%c\n",
8193                 rd->alpha2[0], rd->alpha2[1]);
8194         print_rd_rules(rd);
8195  }
8196 @@ -805,7 +805,7 @@ int regulatory_init(void)
8197  #ifdef CONFIG_WIRELESS_OLD_REGULATORY
8198         cfg80211_regdomain = static_regdom(ieee80211_regdom);
8199  
8200 -       printk(KERN_INFO "cfg80211: Using static regulatory domain info\n");
8201 +       printk(KERN_DEBUG "cfg80211: Using static regulatory domain info\n");
8202         print_regdomain_info(cfg80211_regdomain);
8203         /* The old code still requests for a new regdomain and if
8204          * you have CRDA you get it updated, otherwise you get
8205 diff -Nurp kernel-2.6.28-20094102.6+0m5/sound/soc/codecs/tlv320aic3x.c kernel-2.6.28-20094803.3+0m5/sound/soc/codecs/tlv320aic3x.c
8206 --- kernel-2.6.28-20094102.6+0m5/sound/soc/codecs/tlv320aic3x.c 2011-09-04 11:36:23.000000000 +0200
8207 +++ kernel-2.6.28-20094803.3+0m5/sound/soc/codecs/tlv320aic3x.c 2011-09-04 11:37:54.000000000 +0200
8208 @@ -51,6 +51,9 @@
8209  
8210  #define AIC3X_VERSION "0.2"
8211  
8212 +static int hp_dac_lim = 9;
8213 +module_param(hp_dac_lim, int, 0);
8214 +
8215  /* codec private data */
8216  struct aic3x_priv {
8217         unsigned int sysclk;
8218 @@ -294,6 +297,40 @@ static DECLARE_TLV_DB_SCALE(hpout_tlv, 0
8219   */
8220  static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1);
8221  
8222 +#define SOC_DOUBLE_R_TLV_TLV320ALC3X(xname, reg_left, reg_right, xshift, xmax,\
8223 +                                xinvert, tlv_array) \
8224 +{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
8225 +       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
8226 +                SNDRV_CTL_ELEM_ACCESS_READWRITE,\
8227 +       .tlv.p = (tlv_array), \
8228 +       .info = tlv320alc3x_info_volsw, \
8229 +       .get = snd_soc_get_volsw_2r,\
8230 +       .put = snd_soc_put_volsw_2r,\
8231 +       .private_value = (unsigned long)&(struct soc_mixer_control) \
8232 +               {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
8233 +               .max = xmax, .invert = xinvert} }
8234 +
8235 +static int tlv320alc3x_info_volsw(struct snd_kcontrol *kcontrol,
8236 +       struct snd_ctl_elem_info *uinfo)
8237 +{
8238 +       struct soc_mixer_control *mc =
8239 +               (struct soc_mixer_control *)kcontrol->private_value;
8240 +       int max = mc->max;
8241 +
8242 +       if (hp_dac_lim != max && hp_dac_lim >= 2 && hp_dac_lim <= 9)
8243 +               max = hp_dac_lim;
8244 +
8245 +       if (max == 1)
8246 +               uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
8247 +       else
8248 +               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
8249 +
8250 +       uinfo->count = 2;
8251 +       uinfo->value.integer.min = 0;
8252 +       uinfo->value.integer.max = max;
8253 +       return 0;
8254 +}
8255 +
8256  static const struct snd_kcontrol_new aic3x_snd_controls[] = {
8257         /* Output */
8258         SOC_DOUBLE_R_TLV("PCM Playback Volume",
8259 @@ -327,8 +364,8 @@ static const struct snd_kcontrol_new aic
8260                          0, 118, 1, output_stage_tlv),
8261         SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
8262                      0x01, 0),
8263 -       SOC_DOUBLE_R_TLV("HP DAC Output Volume", HPLOUT_CTRL, HPROUT_CTRL, 4,
8264 -                        9, 0, hpout_tlv),
8265 +       SOC_DOUBLE_R_TLV_TLV320ALC3X("HP DAC Output Volume", HPLOUT_CTRL,
8266 +                        HPROUT_CTRL, 4, 9, 0, hpout_tlv),
8267         SOC_DOUBLE_R_TLV("HP PGA Bypass Playback Volume",
8268                          PGAL_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL,
8269                          0, 118, 1, output_stage_tlv),
8270 @@ -341,8 +378,8 @@ static const struct snd_kcontrol_new aic
8271                          0, 118, 1, output_stage_tlv),
8272         SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
8273                      0x01, 0),
8274 -       SOC_DOUBLE_R_TLV("HPCOM DAC Output Volume", HPLCOM_CTRL, HPRCOM_CTRL,
8275 -                        4, 9, 0, hpout_tlv),
8276 +       SOC_DOUBLE_R_TLV_TLV320ALC3X("HPCOM DAC Output Volume", HPLCOM_CTRL,
8277 +                        HPRCOM_CTRL, 4, 9, 0, hpout_tlv),
8278         SOC_DOUBLE_R_TLV("HPCOM PGA Bypass Playback Volume",
8279                          PGAL_2_HPLCOM_VOL, PGAR_2_HPRCOM_VOL,
8280                          0, 118, 1, output_stage_tlv),
8281 diff -Nurp kernel-2.6.28-20094102.6+0m5/sound/soc/omap/rx51.c kernel-2.6.28-20094803.3+0m5/sound/soc/omap/rx51.c
8282 --- kernel-2.6.28-20094102.6+0m5/sound/soc/omap/rx51.c  2011-09-04 11:36:23.000000000 +0200
8283 +++ kernel-2.6.28-20094803.3+0m5/sound/soc/omap/rx51.c  2011-09-04 11:37:54.000000000 +0200
8284 @@ -59,6 +59,9 @@ enum {
8285         RX51_JACK_TVOUT,        /* stereo output with tv-out */
8286  };
8287  
8288 +static int hp_lim = 63;
8289 +module_param(hp_lim, int, 0);
8290 +
8291  static int rx51_new_hw_audio;
8292  static int rx51_spk_func;
8293  static int rx51_jack_func;
8294 @@ -563,8 +566,16 @@ enum {
8295  static int rx51_ext_info_volsw(struct snd_kcontrol *kcontrol,
8296                                struct snd_ctl_elem_info *uinfo)
8297  {
8298 +       int ext_api = (kcontrol->private_value >> 26) & 0x0f;
8299         int max = (kcontrol->private_value >> 16) & 0xff;
8300  
8301 +       if (ext_api == RX51_EXT_API_TPA6130)
8302 +               if (hp_lim != max && hp_lim >= 2 && hp_lim <= 63) {
8303 +                       kcontrol->private_value &= ~(0xff << 16);
8304 +                       kcontrol->private_value |= (hp_lim << 16);
8305 +                       max = hp_lim;
8306 +               }
8307 +
8308         if (max == 1)
8309                 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
8310         else