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
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
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
18 +# CONFIG_SSI_CHAR_DEBUG is not set
20 # CONFIG_IDE is not set
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
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
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)
48 struct prm_setup_times prm_setup = {
50 + .clksetup = 111, /* must equal Volt offset + voltsetup2 */
51 .voltsetup_time1 = 270,
52 .voltsetup_time2 = 150,
55 + /* Time between wakeup event to when the sysoff goes high */
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
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[] = {
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
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},
85 static struct twl4030_script sleep_on_script = {
86 @@ -433,7 +441,10 @@ static struct twl4030_ins wakeup_seq[] =
88 * Reenable everything.
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},
97 static struct twl4030_script wakeup_script = {
98 @@ -461,14 +472,10 @@ static struct twl4030_ins wrst_seq[] = {
99 * Enable sysclk output.
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),
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},
117 @@ -490,54 +497,31 @@ static struct twl4030_script *twl4030_sc
119 static struct twl4030_resconfig twl4030_rconfig[] = {
121 - { .resource = RES_VDD1, .devgroup = -1, .type = 1, .type2 = -1,
123 - { .resource = RES_VDD2, .devgroup = -1, .type = 1, .type2 = -1,
125 - { .resource = RES_VPLL1, .devgroup = -1, .type = 1, .type2 = -1,
127 - { .resource = RES_VPLL2, .devgroup = -1, .type = -1, .type2 = 3,
129 - { .resource = RES_VAUX1, .devgroup = -1, .type = -1, .type2 = 3,
131 - { .resource = RES_VAUX2, .devgroup = -1, .type = -1, .type2 = 3,
133 - { .resource = RES_VAUX3, .devgroup = -1, .type = -1, .type2 = 3,
135 - { .resource = RES_VAUX4, .devgroup = -1, .type = -1, .type2 = 3,
137 - { .resource = RES_VMMC1, .devgroup = -1, .type = -1, .type2 = 3,
139 - { .resource = RES_VMMC2, .devgroup = -1, .type = -1, .type2 = 3,
141 - { .resource = RES_VDAC, .devgroup = -1, .type = -1, .type2 = 3,
143 - { .resource = RES_VSIM, .devgroup = -1, .type = -1, .type2 = 3,
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,
165 - { .resource = RES_RESET, .devgroup = -1, .type = 1, .type2 = -1,
167 - { .resource = RES_Main_Ref, .devgroup = -1, .type = 1, .type2 = -1,
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 },
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
293 #define MMCHS_SYSSTATUS 0x0014
294 #define MMCHS_SYSSTATUS_RESETDONE (1 << 0)
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)
302 static struct platform_device dummy_pdev = {
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.
309 + if (!cpu_is_omap2430()) {
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);
317 if (mmc->slots[0].internal_clock) {
320 @@ -608,6 +622,14 @@ static int twl_mmc2_set_power(struct dev
322 ret = twl_mmc_set_voltage(c, vdd);
324 + if (!cpu_is_omap2430()) {
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);
332 ret = twl_mmc_set_voltage(c, 0);
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);
339 + struct twl_mmc_controller *c = &hsmmc[1];
341 /* VCC can be turned off if card is asleep */
344 - err = twl_mmc2_set_power(dev, slot, 0, 0);
345 + err = twl_mmc_set_voltage(c, 0);
347 - err = twl_mmc2_set_power(dev, slot, 1, vdd);
348 + err = twl_mmc_set_voltage(c, vdd);
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;
357 DEBUG_FILE_COUNTERS = 0,
359 - DEBUG_FILE_RESOURCES
360 + DEBUG_FILE_RESOURCES,
361 + DEBUG_FILE_WAIT_SDRC_COUNT
364 struct pm_module_def {
365 @@ -428,9 +429,21 @@ static int pm_dbg_show_timers(struct seq
369 +static int pm_dbg_show_sdrc_wait_count(struct seq_file *s, void *unused)
371 + unsigned int *sdrc_counters = omap3_get_sdrc_counters();
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]);
378 static int pm_dbg_open(struct inode *inode, struct file *file)
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,
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);
394 pwrdm_for_each(pwrdms_setup, (void *)d);
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);
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
412 static void (*saved_idle)(void);
414 +static unsigned int *_sdrc_counters;
415 +static unsigned int save_sdrc_counters[2];
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))
428 + * Force write last pad into memory, as this can fail in some
429 + * cases according to errata XYZ
431 + omap_ctrl_writel(omap_ctrl_readl(OMAP343X_PADCONF_ETK_D14),
432 + OMAP343X_CONTROL_MEM_WKUP + 0x2a0);
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);
441 + memcpy(save_sdrc_counters, _sdrc_counters, sizeof(save_sdrc_counters));
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();
450 + memcpy(_sdrc_counters, save_sdrc_counters, sizeof(save_sdrc_counters));
452 omap_uart_resume_idle(0);
453 omap_uart_resume_idle(1);
454 @@ -802,6 +816,12 @@ err:
458 +/* return a pointer to the sdrc counters */
459 +unsigned int *omap3_get_sdrc_counters(void)
461 + return _sdrc_counters;
464 static void omap3_pm_idle(void)
467 @@ -1251,6 +1271,10 @@ void omap_push_sram_idle(void)
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
473 + _sdrc_counters = (unsigned *)((u8 *)_omap_sram_idle + omap34xx_cpu_suspend_sz - 8);
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
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)
488 * This is the physical address of the register as specified
489 @@ -703,35 +704,70 @@ skip_l2_inval:
491 /* Make sure SDRC accesses are ok */
494 +/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this. */
495 + ldr r4, cm_idlest_ckgen
499 + beq wait_dpll3_lock
501 ldr r4, cm_idlest1_core
508 + bne wait_sdrc_ready
509 + /* allow DLL powerdown upon hw idle req */
515 - /* Is dll in lock mode? */
516 +is_dll_in_lock_mode:
517 ldr r4, sdrc_dlla_ctrl
521 /* wait till dll locks */
522 +wait_dll_lock_timed:
523 + ldr r4, wait_dll_lock_counter
525 + str r4, wait_dll_lock_counter
526 ldr r4, sdrc_dlla_status
527 + mov r6, #8 /* Wait 20uS for lock */
537 + /* disable/reenable DLL if locked */
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 */
545 + orr r6, r6, #(1<<3) /* enable dll */
548 + str r5, [r4] /* restore old value */
549 + ldr r4, kick_counter
551 + str r4, kick_counter
552 + b wait_dll_lock_timed
559 .word CM_IDLEST1_CORE_V
561 + .word CM_IDLEST_CKGEN_V
563 .word SDRC_DLLA_STATUS_V
565 @@ -766,5 +802,10 @@ cache_pred_disable_mask:
569 + /* these 2 words need to be at the end !!! */
572 +wait_dll_lock_counter:
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
580 * 'va': mpu virtual address
582 * 'c': contiguous memory area
583 - * 'd': dicontiguous memory area
584 + * 'd': discontiguous memory area
585 * 'a': anonymous memory allocation
586 * '()': optional feature
588 @@ -385,14 +385,13 @@ static void sgtable_fill_vmalloc(struct
591 va_end = _va + PAGE_SIZE * i;
592 - flush_cache_vmap(_va, va_end);
595 static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
598 * Actually this is not necessary at all, just exists for
599 - * consistency of the code readibility.
600 + * consistency of the code readability.
604 @@ -420,15 +419,13 @@ static void sgtable_fill_kmalloc(struct
609 - clean_dcache_area(va, len);
612 static inline void sgtable_drain_kmalloc(struct sg_table *sgt)
615 * Actually this is not necessary at all, just exists for
616 - * consistency of the code readibility
617 + * consistency of the code readability
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
625 #define PWR_TIMEOUT 500 /* Sleep/wake timout in msec */
626 #define EXTEND "_EXT_END" /* Extmem end addr in DSP binary */
628 +#define DSP_CACHE_LINE 128
630 extern char *iva_img;
632 /* ----------------------------------- Globals */
633 @@ -679,8 +681,48 @@ DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR
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)
643 + unsigned long offset;
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__,
652 + page = follow_page(vma, start, FOLL_GET);
654 + pr_err("%s: no page for %08lx\n", __func__, start);
656 + } else if (IS_ERR(page)) {
657 + pr_err("%s: err page for %08lx(%lu)\n", __func__, start,
659 + return IS_ERR(page);
662 + offset = start & ~PAGE_MASK;
663 + kaddr = page_address(page) + offset;
664 + rest = min_t(ssize_t, PAGE_SIZE - offset, len);
666 + MEM_FlushCache(kaddr, rest, ftype);
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)
683 @@ -690,14 +732,19 @@ static int memory_check_vma(unsigned lon
687 - down_read(¤t->mm->mmap_sem);
689 while ((vma = find_vma(current->mm, start)) != NULL) {
692 + if (vma->vm_flags & (VM_IO | VM_PFNMAP))
695 + if (vma->vm_start > start)
698 - if (vma->vm_start > start) {
700 + size = min_t(ssize_t, vma->vm_end - start, len);
701 + err = memory_sync_page(vma, start, size, ftype);
706 if (end <= vma->vm_end)
708 @@ -708,8 +755,6 @@ static int memory_check_vma(unsigned lon
712 - up_read(¤t->mm->mmap_sem);
717 @@ -734,18 +779,15 @@ static DSP_STATUS proc_memory_sync(DSP_H
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(¤t->mm->mmap_sem);
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;
734 - (void)SYNC_EnterCS(hProcLock);
735 - MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
736 - (void)SYNC_LeaveCS(hProcLock);
738 + up_read(¤t->mm->mmap_sem);
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
749 -FlushCacheDRI(IMG_UINT32 ui32Type, IMG_UINT32 ui32Virt, IMG_UINT32 ui32Length)
750 +FlushCacheDRI(IMG_UINT32 ui32Type, IMG_VOID *pvVirt, IMG_UINT32 ui32Length)
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));
759 - dmac_inv_range((const void *)ui32Virt,
760 - (const void *)(ui32Virt + ui32Length));
761 + dmac_inv_range((const void *)pvVirt,
762 + (const void *)(pvVirt + ui32Length));
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));
771 - dmac_clean_range((const void *)ui32Virt,
772 - (const void *)(ui32Virt + ui32Length));
773 + dmac_clean_range((const void *)pvVirt,
774 + (const void *)(pvVirt + ui32Length));
778 @@ -821,18 +821,51 @@ FlushCacheDRI(IMG_UINT32 ui32Type, IMG_U
783 +PVRSRVIsWrappedExtMemoryBW(PVRSRV_PER_PROCESS_DATA *psPerProc,
784 + PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER *psCacheFlushIN)
786 + PVRSRV_ERROR eError;
787 + IMG_HANDLE hDevCookieInt;
789 + PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
790 + psCacheFlushIN->hDevCookie,
791 + PVRSRV_HANDLE_TYPE_DEV_NODE);
793 + eError = PVRSRVIsWrappedExtMemoryKM(
796 + &(psCacheFlushIN->ui32Length),
797 + &(psCacheFlushIN->pvVirt));
803 PVRSRVCacheFlushDRIBW(IMG_UINT32 ui32BridgeID,
804 PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER * psCacheFlushIN,
805 PVRSRV_BRIDGE_RETURN * psRetOUT,
806 PVRSRV_PER_PROCESS_DATA * psPerProc)
808 + PVRSRV_ERROR eError;
809 PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CACHE_FLUSH_DRM);
811 - psRetOUT->eError = FlushCacheDRI(psCacheFlushIN->ui32Type,
812 - psCacheFlushIN->ui32Virt,
813 - psCacheFlushIN->ui32Length);
814 + down_read(¤t->mm->mmap_sem);
816 + eError = PVRSRVIsWrappedExtMemoryBW(psPerProc, psCacheFlushIN);
818 + if (eError == PVRSRV_OK) {
819 + psRetOUT->eError = FlushCacheDRI(psCacheFlushIN->ui32Type,
820 + psCacheFlushIN->pvVirt,
821 + psCacheFlushIN->ui32Length);
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));
829 + up_read(¤t->mm->mmap_sem);
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;
840 PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_WRAP_EXT_MEMORY);
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
847 #include "pdump_km.h"
849 +#include <linux/kernel.h>
851 #define MIN(a,b) (a > b ? b : a)
854 @@ -988,6 +990,34 @@ BM_IsWrapped(IMG_HANDLE hDevMemHeap,
858 +BM_IsWrappedCheckSize(IMG_HANDLE hDevMemHeap,
859 + IMG_UINT32 ui32Offset,
860 + IMG_SYS_PHYADDR sSysAddr,
861 + IMG_UINT32 ui32ByteSize)
864 + BM_CONTEXT *psBMContext;
867 + IMG_BOOL ret = IMG_FALSE;
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);
875 + if (pBuf != NULL) {
876 + if (pBuf->pMapping->uSize >= ui32ByteSize)
886 BM_Wrap(IMG_HANDLE hDevMemHeap,
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
893 IMG_UINT32 ui32Offset, IMG_SYS_PHYADDR sSysAddr);
896 + BM_IsWrappedCheckSize(IMG_HANDLE hDevMemHeap,
897 + IMG_UINT32 ui32Offset,
898 + IMG_SYS_PHYADDR sSysAddr,
899 + IMG_UINT32 ui32ByteSize);
902 BM_Wrap(IMG_HANDLE hDevMemHeap,
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
909 #include "pvr_bridge_km.h"
911 #include "linux/kernel.h"
912 +#include "linux/pagemap.h"
914 static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
915 IMG_HANDLE hDevMemHeap,
916 @@ -595,13 +596,92 @@ static PVRSRV_ERROR UnwrapExtMemoryCallB
920 - OSReleasePhysPageAddr(hOSWrapMem);
921 + OSReleasePhysPageAddr(hOSWrapMem, IMG_TRUE);
928 + PVRSRV_ERROR IMG_CALLCONV PVRSRVIsWrappedExtMemoryKM(IMG_HANDLE hDevCookie,
929 + PVRSRV_PER_PROCESS_DATA
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;
945 + IMG_UINT32 ui32ReturnedByteSize = *pui32ByteSize;
947 + eError = PVRSRV_ERROR_OUT_OF_MEMORY;
949 + psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
950 + PVR_ASSERT(psDeviceNode != IMG_NULL);
951 + psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
953 + hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].hDevMemHeap;
956 + ui32PageOffset = ((IMG_UINT32)*pvLinAddr) & ~PAGE_MASK;
957 + *pvLinAddr = (IMG_VOID *)((IMG_UINT32)*pvLinAddr & PAGE_MASK);
958 + ui32ReturnedByteSize += ui32PageOffset;
960 + /* let's start by getting the address of the first page */
961 + eError = OSAcquirePhysPageAddr(*pvLinAddr,
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;
972 + OSReleasePhysPageAddr(hOSWrapMem, IMG_FALSE);
973 + hOSWrapMem = IMG_NULL;
975 + /* now check if this memory address is already wrapped */
976 + if (BM_IsWrappedCheckSize(hDevMemHeap,
980 + /* already wrapped */
981 + eError = PVRSRV_OK;
983 + /* not mapped in this heap */
984 + /* try the alternative heap */
985 + hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].hDevMemHeap;
987 + if (BM_IsWrappedCheckSize(hDevMemHeap,
991 + /* already wrapped */
992 + eError = PVRSRV_OK;
994 + eError = PVRSRV_ERROR_BAD_MAPPING;
1001 + *pui32ByteSize = ui32ReturnedByteSize;
1007 PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
1008 PVRSRV_PER_PROCESS_DATA *
1010 @@ -631,6 +711,13 @@ IMG_EXPORT
1011 IMG_SYS_PHYADDR *pPageList = psExtSysPAddr;
1012 IMG_UINT32 ui32PageCount;
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;
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,
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
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:
1060 - OSReleasePhysPageAddr(hOSWrapMem);
1061 + OSReleasePhysPageAddr(hOSWrapMem, IMG_TRUE);
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
1070 psTimerCBData->bActive = IMG_TRUE;
1072 + psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
1073 add_timer(&psTimerCBData->sTimer);
1076 @@ -1400,7 +1401,8 @@ exit_unlock:
1080 -PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
1081 +PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem,
1082 + IMG_BOOL bUseLock)
1084 sWrapMemInfo *psInfo = (sWrapMemInfo *) hOSWrapMem;
1086 @@ -1415,7 +1417,8 @@ PVRSRV_ERROR OSReleasePhysPageAddr(IMG_H
1088 struct vm_area_struct *psVMArea;
1090 - down_read(¤t->mm->mmap_sem);
1092 + down_read(¤t->mm->mmap_sem);
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);
1100 - up_read(¤t->mm->mmap_sem);
1102 + up_read(¤t->mm->mmap_sem);
1107 @@ -1459,7 +1464,9 @@ PVRSRV_ERROR OSReleasePhysPageAddr(IMG_H
1108 psVMArea->vm_flags);
1111 - up_read(¤t->mm->mmap_sem);
1113 + up_read(¤t->mm->mmap_sem);
1118 @@ -1514,10 +1521,11 @@ PVRSRV_ERROR OSReleasePhysPageAddr(IMG_H
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)
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) {
1137 - ": OSCpuVToPageList: Couldn't allocate information structure");
1138 + ": OSCpuVToPageList: Couldn't allocate information structure\n");
1139 return PVRSRV_ERROR_OUT_OF_MEMORY;
1141 memset(psInfo, 0, sizeof(*psInfo));
1142 @@ -1556,7 +1564,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1144 if (psInfo->psPhysAddr == NULL) {
1146 - ": OSCpuVToPageList: Couldn't allocate page array");
1147 + ": OSCpuVToPageList: Couldn't allocate page array\n");
1151 @@ -1564,21 +1572,26 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1152 kmalloc(psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL);
1153 if (psInfo->ppsPages == NULL) {
1155 - ": OSCpuVToPageList: Couldn't allocate page array");
1156 + ": OSCpuVToPageList: Couldn't allocate page array\n");
1160 - down_read(¤t->mm->mmap_sem);
1162 + down_read(¤t->mm->mmap_sem);
1165 get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages,
1166 1, 0, psInfo->ppsPages, NULL);
1167 - up_read(¤t->mm->mmap_sem);
1170 + up_read(¤t->mm->mmap_sem);
1173 if (iNumPagesMapped >= 0) {
1175 if (iNumPagesMapped != psInfo->iNumPages) {
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);
1181 for (ui = 0; ui < iNumPagesMapped; ui++) {
1182 @@ -1605,15 +1618,16 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1186 - ": OSCpuVToPageList: get_user_pages failed (%d), trying something else",
1187 + ": OSCpuVToPageList: get_user_pages failed (%d), trying something else \n",
1190 - down_read(¤t->mm->mmap_sem);
1192 + down_read(¤t->mm->mmap_sem);
1194 psVMArea = find_vma(current->mm, ulStartAddrOrig);
1195 if (psVMArea == NULL) {
1197 - ": OSCpuVToPageList: Couldn't find memory region containing start address %lx",
1198 + ": OSCpuVToPageList: Couldn't find memory region containing start address %lx \n",
1201 goto error_release_mmap_sem;
1202 @@ -1624,14 +1638,14 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1204 if (ulStartAddrOrig < psVMArea->vm_start) {
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",
1209 goto error_release_mmap_sem;
1212 if (ulBeyondEndAddrOrig > psVMArea->vm_end) {
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;
1219 @@ -1639,14 +1653,14 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1220 if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) !=
1221 (VM_IO | VM_RESERVED)) {
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;
1229 if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE)) {
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;
1236 @@ -1662,7 +1676,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
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",
1244 for (uj = 0; uj < ui; uj++) {
1245 @@ -1693,7 +1707,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1247 if ((psVMArea->vm_flags & VM_PFNMAP) == 0) {
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;
1254 @@ -1714,10 +1728,11 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_V
1255 psInfo->eType = WRAP_TYPE_FIND_VMA_PFN;
1258 - ": OSCpuVToPageList: Region can't be locked down");
1259 + ": OSCpuVToPageList: Region can't be locked down\n");
1262 - up_read(¤t->mm->mmap_sem);
1264 + up_read(¤t->mm->mmap_sem);
1267 CheckPagesContiguous(psInfo);
1268 @@ -1727,9 +1742,11 @@ exit_check:
1271 error_release_mmap_sem:
1272 - up_read(¤t->mm->mmap_sem);
1274 + up_read(¤t->mm->mmap_sem);
1277 psInfo->eType = WRAP_TYPE_CLEANUP;
1278 - OSReleasePhysPageAddr((IMG_HANDLE) psInfo);
1279 + OSReleasePhysPageAddr((IMG_HANDLE) psInfo, bUseLock);
1280 return PVRSRV_ERROR_GENERIC;
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);
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);
1305 +static IMG_BOOL IsPowerLocked(void)
1307 + return mutex_is_locked(&hPowerAndFreqLock) || gbDvfsActive;
1311 PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
1312 IMG_BOOL bSystemPowerEvent)
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
1324 - if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID)
1325 - || OSIsResourceLocked(&psSysData->sPowerStateChangeResource,
1327 + if (IsPowerLocked())
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
1338 typedef struct PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER_TAG {
1339 IMG_UINT32 ui32BridgeFlags;
1340 + IMG_HANDLE hDevCookie;
1341 IMG_UINT32 ui32Type;
1342 - IMG_UINT32 ui32Virt;
1344 IMG_UINT32 ui32Length;
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 @@
1353 PVRSRV_ERROR IMG_CALLCONV
1354 + PVRSRVIsWrappedExtMemoryKM(IMG_HANDLE hDevCookie,
1355 + PVRSRV_PER_PROCESS_DATA *psPerProc,
1356 + IMG_UINT32 *pui32ByteSize,
1357 + IMG_VOID **pvLinAddr);
1360 + PVRSRV_ERROR IMG_CALLCONV
1361 PVRSRVUnwrapExtMemoryKM(PVRSRV_KERNEL_MEM_INFO * psMemInfo);
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
1368 #define SGX_GENERAL_HEAP_SIZE (0x05000000-0x00401000)
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)
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)
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_
1386 if (psDevInfo->hTimer == IMG_NULL) {
1389 + * the magic calculation below sets the hardware lock-up
1390 + * detection and recovery timer interval to ~150msecs
1392 psDevInfo->hTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
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
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)
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)
1416 struct et8ek8_sensor *sensor = s->priv;
1417 + enum v4l2_power old_state = sensor->power;
1420 /* If we are already in this mode, do nothing */
1421 - if (sensor->power == new_state)
1422 + if (old_state == new_state)
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 */
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);
1435 @@ -806,10 +807,11 @@ static int et8ek8_ioctl_s_power(struct v
1437 if (new_state == V4L2_POWER_ON) {
1438 /* Standby -> streaming */
1439 + sensor->power = V4L2_POWER_ON;
1440 rval = et8ek8_configure(s);
1442 et8ek8_stream_off(s);
1443 - if (sensor->power == V4L2_POWER_OFF)
1444 + if (old_state == V4L2_POWER_OFF)
1445 et8ek8_power_off(s);
1448 @@ -820,9 +822,7 @@ static int et8ek8_ioctl_s_power(struct v
1453 - sensor->power = new_state;
1455 + sensor->power = (rval == 0) ? new_state : old_state;
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_
1466 + isp_af->stat.config_counter++;
1467 ispstat_bufs_set_size(&isp_af->stat, isp_af->buf_size);
1469 spin_unlock_irqrestore(isp_af->lock, irqflags);
1470 @@ -299,8 +300,8 @@ void isp_af_try_enable(struct isp_af_dev
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)
1479 struct device *dev = to_device(isp_af);
1481 @@ -337,14 +338,14 @@ int omap34xx_isp_af_config(struct isp_af
1485 -EXPORT_SYMBOL(omap34xx_isp_af_config);
1486 +EXPORT_SYMBOL(isp_af_config);
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
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)
1497 struct device *dev = to_device(isp_af);
1498 @@ -374,7 +375,7 @@ int omap34xx_isp_af_request_statistics(s
1502 -EXPORT_SYMBOL(omap34xx_isp_af_request_statistics);
1503 +EXPORT_SYMBOL(isp_af_request_statistics);
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);
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
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
1537 EXPORT_SYMBOL(isp_configure_interface);
1539 -void omap34xx_isp_hist_dma_done(struct device *dev)
1540 +void isp_hist_dma_done(struct device *dev)
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);
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.
1557 -static irqreturn_t omap34xx_isp_isr(int irq, void *_pdev)
1558 +static irqreturn_t isp_isr(int irq, void *_pdev)
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;
1566 - int wait_hs_vs = 0;
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)
1575 + if (irqstatus & HS_VS && bufs->wait_stats && !bufs->wait_hs_vs)
1576 + bufs->wait_stats = 0;
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.
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,
1597 + (ISPPRV_PCR_BUSY | ISPPRV_PCR_EN))) {
1598 + isppreview_config_shadow_registers(
1600 + isppreview_enable(&isp->isp_prev, 1);
1605 @@ -811,6 +819,13 @@ static irqreturn_t omap34xx_isp_isr(int
1607 goto out_ignore_buff;
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);
1619 @@ -965,7 +980,6 @@ static irqreturn_t omap34xx_isp_isr(int
1621 /* current and next buffer might have invalid data */
1622 isp_hist_mark_invalid_buf(&isp->isp_hist);
1623 - irqstatus &= ~HIST_DONE;
1626 if (ret != HIST_BUF_WAITING_DMA)
1627 @@ -974,7 +988,7 @@ static irqreturn_t omap34xx_isp_isr(int
1628 irqstatus &= ~HIST_DONE;
1631 - if (irqdis->isp_callbk[CBK_CATCHALL]) {
1632 + if (irqdis->isp_callbk[CBK_CATCHALL] && irqstatus) {
1633 irqdis->isp_callbk[CBK_CATCHALL](
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);
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;
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 *
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.
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);
1669 @@ -1814,48 +1832,48 @@ int isp_handle_private(struct device *de
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);
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);
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);
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,
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);
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,
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);
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);
1726 @@ -2029,7 +2047,7 @@ static void isp_save_ctx(struct device *
1727 ispccdc_save_context(dev);
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);
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;
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");
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
1757 #include "ispccdc.h"
1759 #define LSC_TABLE_INIT_SIZE 50052
1760 +#define PTR_FREE ((u32)(-ENOMEM))
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[]
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
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.
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)
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;
1789 - if (userspace_add == NULL)
1792 - ccdc_struct = userspace_add;
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);
1801 - if (ISP_ABS_CCDC_LPF & ccdc_struct->flag)
1802 - ispccdc_enable_lpf(isp_ccdc, 1);
1804 - ispccdc_enable_lpf(isp_ccdc, 0);
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;
1813 - ispccdc_enable_black_clamp(isp_ccdc, 1);
1814 - ispccdc_config_black_clamp(isp_ccdc, bclamp_t);
1816 - ispccdc_enable_black_clamp(isp_ccdc, 1);
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;
1824 - ispccdc_enable_black_clamp(isp_ccdc, 0);
1825 - ispccdc_config_black_clamp(isp_ccdc, bclamp_t);
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;
1835 - ispccdc_config_black_comp(isp_ccdc, blcomp_t);
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 *)
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"
1852 - while (((unsigned long)isp_ccdc->fpc_table_add
1854 - != (unsigned long)isp_ccdc->fpc_table_add)
1855 - isp_ccdc->fpc_table_add++;
1857 - isp_ccdc->fpc_table_add_m = iommu_kmap(
1860 - virt_to_phys(isp_ccdc->fpc_table_add),
1863 - /* FIXME: Correct unwinding */
1864 - BUG_ON(IS_ERR_VALUE(isp_ccdc->fpc_table_add_m));
1866 - if (copy_from_user(isp_ccdc->fpc_table_add,
1867 - (u32 *)fpc_t.fpcaddr,
1869 - goto copy_from_user_err;
1871 - fpc_t.fpcaddr = isp_ccdc->fpc_table_add_m;
1872 - ispccdc_config_fpc(isp_ccdc, fpc_t);
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())
1880 - if (ISP_ABS_CCDC_CULL & ccdc_struct->update) {
1881 - if (copy_from_user(&cull_t, (struct ispccdc_culling *)
1882 - ccdc_struct->cull,
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,
1896 + DPRINTK_ISPCCDC("ISP_CTRL =0x%x\n",
1897 + isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
1899 + switch (pipe->ccdc_in) {
1901 + DPRINTK_ISPCCDC("ccdc input format is CCDC_RAW\n");
1903 + case CCDC_YUV_SYNC:
1904 + DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_SYNC\n");
1907 + DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_BT\n");
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);
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);
1929 - if (ISP_ABS_TBL_LSC & ccdc_struct->update) {
1930 - if (copy_from_user(isp_ccdc->lsc_gain_table,
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);
1937 + switch (pipe->ccdc_out) {
1938 + case CCDC_OTHERS_VP:
1939 + DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_VP\n");
1941 + case CCDC_OTHERS_MEM:
1942 + DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_MEM\n");
1944 + case CCDC_YUV_RSZ:
1945 + DPRINTK_ISPCCDC("ccdc output format is CCDC_YUV_RSZ\n");
1951 - if (ISP_ABS_CCDC_COLPTN & ccdc_struct->update)
1952 - ispccdc_config_imgattr(isp_ccdc, ccdc_struct->colptn);
1956 -copy_from_user_err:
1957 - dev_err(isp->dev, "ccdc: Config: copy from user error");
1962 - * Set the value to be used for CCDC_CFG.WENLOG.
1963 - * w - Value of wenlog.
1965 -void ispccdc_set_wenlog(struct isp_ccdc_device *isp_ccdc, u32 wenlog)
1967 - isp_ccdc->wenlog = wenlog;
1968 + DPRINTK_ISPCCDC("###ISP_CTRL in ccdc =0x%x\n",
1969 + isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
1971 + DPRINTK_ISPCCDC("###ISP_IRQ0ENABLE in ccdc =0x%x\n",
1972 + isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
1974 + DPRINTK_ISPCCDC("###ISP_IRQ0STATUS in ccdc =0x%x\n",
1975 + isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
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,
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,
2004 + DPRINTK_ISPCCDC("###CCDC COLPTN=0x%x\n",
2005 + isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2007 + DPRINTK_ISPCCDC("###CCDC CFG=0x%x\n",
2008 + isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2010 + DPRINTK_ISPCCDC("###CCDC VP_OUT=0x%x\n",
2011 + isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
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,
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));
2040 - * ispccdc_request - Reserves the CCDC module.
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.
2051 - * Returns 0 if successful, or -EBUSY if CCDC module is busy.
2052 + * Returns always 0 when completed.
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)
2058 struct device *dev = to_device(isp_ccdc);
2059 + u32 bclamp_val = 0;
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");
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);
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);
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);
2096 - * ispccdc_free - Frees the CCDC module.
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.
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
2106 -int ispccdc_free(struct isp_ccdc_device *isp_ccdc)
2107 +static void ispccdc_enable_black_clamp(struct isp_ccdc_device *isp_ccdc,
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");
2116 + struct device *dev = to_device(isp_ccdc);
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));
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;
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.
2137 - * Always returns 0.
2138 + * Returns 0 if successful, or -EINVAL if FPC Address is not on the 64 byte
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)
2145 - struct isp_device *isp = to_isp_device(isp_ccdc);
2146 + struct device *dev = to_device(isp_ccdc);
2149 - if (!isp_ccdc->lsc_ispmmu_addr)
2151 + fpc_val = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
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);
2165 + DPRINTK_ISPCCDC("FPC Address should be on 64byte boundary\n");
2168 + isp_reg_writel(dev, fpc_val | (fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
2169 + OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
2174 - * ispccdc_allocate_lsc - Allocate space for Lens Shading Compensation table
2175 - * @table_size: LSC gain table size.
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.
2182 -static int ispccdc_allocate_lsc(struct isp_ccdc_device *isp_ccdc,
2184 +static void ispccdc_enable_fpc(struct isp_ccdc_device *isp_ccdc, u8 enable)
2186 - struct isp_device *isp = to_isp_device(isp_ccdc);
2188 - if (table_size == 0)
2190 + struct device *dev = to_device(isp_ccdc);
2192 - if ((isp_ccdc->lsc_config.size >= table_size)
2193 - && isp_ccdc->lsc_gain_table)
2195 + isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC,
2196 + ~ISPCCDC_FPC_FPCEN, enable ? ISPCCDC_FPC_FPCEN : 0);
2199 - ispccdc_free_lsc(isp_ccdc);
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.
2205 +static void ispccdc_config_black_comp(struct isp_ccdc_device *isp_ccdc,
2206 + struct ispccdc_blcomp blcomp)
2208 + struct device *dev = to_device(isp_ccdc);
2209 + u32 blcomp_val = 0;
2211 - isp_ccdc->lsc_ispmmu_addr = iommu_vmalloc(isp->iommu, 0, table_size,
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;
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;
2227 + isp_reg_writel(dev, blcomp_val, OMAP3_ISP_IOMEM_CCDC,
2232 - * ispccdc_program_lsc - Program Lens Shading Compensation table.
2233 - * @table_size: LSC gain table size.
2235 - * Returns 0 if successful, or -EINVAL if there's no mapped address for the
2237 + * ispccdc_config_vp - Configures the Video Port Configuration parameters.
2238 + * @vpcfg: Structure containing the Video Port input frequency, and the 10 bit
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)
2245 - if (!isp_ccdc->lsc_ispmmu_addr)
2247 + struct device *dev = to_device(isp_ccdc);
2248 + u32 fmtcfg_vp = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2251 - if (isp_ccdc->lsc_initialized)
2253 + fmtcfg_vp &= ISPCCDC_FMTCFG_VPIN_MASK & ISPCCDC_FMTCFG_VPIF_FRQ_MASK;
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;
2259 + switch (vpcfg.bitshift_sel) {
2261 + fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
2264 + fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
2267 + fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
2270 + fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
2273 + switch (vpcfg.freq_sel) {
2275 + fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY2;
2278 + fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY3;
2281 + fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY4;
2284 + fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY5;
2287 + fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY6;
2290 + isp_reg_writel(dev, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
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.
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
2303 -int ispccdc_load_lsc(struct isp_ccdc_device *isp_ccdc, u8 *table_addr,
2305 +static void ispccdc_enable_vp(struct isp_ccdc_device *isp_ccdc, u8 enable)
2309 - if (!is_isplsc_activated())
2314 + struct device *dev = to_device(isp_ccdc);
2316 - ret = ispccdc_allocate_lsc(isp_ccdc, table_size);
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);
2326 + isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
2327 + ~ISPCCDC_FMTCFG_VPEN,
2328 + enable ? ISPCCDC_FMTCFG_VPEN : 0);
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.
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)
2343 struct device *dev = to_device(isp_ccdc);
2346 - if (!is_isplsc_activated())
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;
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;
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,
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
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)
2383 struct device *dev = to_device(isp_ccdc);
2385 - if (!is_isplsc_activated())
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);
2394 - isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC,
2395 - ISPCCDC_LSC_CONFIG, 0x1);
2397 - isp_ccdc->lsc_state = 1;
2399 - /* Postpone enabling LSC */
2400 - isp_ccdc->lsc_enable = 1;
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;
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);
2413 -void ispccdc_lsc_error_handler(struct isp_ccdc_device *isp_ccdc)
2415 + * ispccdc_config_alaw - Configures the input width for A-law.
2416 + * @ipwidth: Input width for A-law
2418 +static void ispccdc_config_alaw(struct isp_ccdc_device *isp_ccdc,
2419 + enum alaw_ipwidth ipwidth)
2421 - int lsc_enable = isp_ccdc->lsc_state;
2423 - ispccdc_enable_lsc(isp_ccdc, 0);
2424 + struct device *dev = to_device(isp_ccdc);
2426 - isp_ccdc->lsc_enable = lsc_enable;
2427 + isp_reg_writel(dev, ipwidth << ISPCCDC_ALAW_GWDI_SHIFT,
2428 + OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
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.
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
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)
2453 - isp_ccdc->ccdcin_woffset = left + (left % 2);
2454 - isp_ccdc->ccdcin_hoffset = top + (top % 2);
2456 - isp_ccdc->crop_w = width - (width % 16);
2457 - isp_ccdc->crop_h = height + (height % 2);
2458 + struct device *dev = to_device(isp_ccdc);
2460 - DPRINTK_ISPCCDC("\n\tOffsets L %d T %d W %d H %d\n",
2461 - isp_ccdc->ccdcin_woffset,
2462 - isp_ccdc->ccdcin_hoffset,
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);
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.
2475 - * Configures the default configuration for the CCDC to work with.
2477 - * The valid values for the input are CCDC_RAW (0), CCDC_YUV_SYNC (1),
2478 - * CCDC_YUV_BT (2), and CCDC_OTHERS (3).
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).
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.
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)
2492 struct device *dev = to_device(isp_ccdc);
2495 - struct ispccdc_vp vpcfg;
2496 - struct ispccdc_syncif syncif;
2497 - struct ispccdc_bclamp blkcfg;
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;
2516 - syn_mode = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
2518 - switch (pipe->ccdc_out) {
2519 - case CCDC_YUV_RSZ:
2520 - syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
2521 - syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
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;
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);
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);
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;
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);
2567 - DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output\n");
2571 - isp_reg_writel(dev, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
2573 - switch (pipe->ccdc_in) {
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;
2583 - syncif.ipmod = RAW;
2585 - ispccdc_config_sync_if(isp_ccdc, syncif);
2586 - ispccdc_config_imgattr(isp_ccdc, colptn);
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);
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;
2606 - syncif.ipmod = YUV16;
2608 - ispccdc_config_imgattr(isp_ccdc, 0);
2609 - ispccdc_config_sync_if(isp_ccdc, syncif);
2611 - blkcfg.dcsubval = 0;
2612 - ispccdc_config_black_clamp(isp_ccdc, blkcfg);
2619 - DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Input\n");
2623 - ispccdc_print_status(isp_ccdc, pipe);
2624 - isp_print_status(dev);
2626 + isp_reg_writel(dev, colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
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
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.
2638 + * Returns 0 if the LSC configuration is valid, or -EINVAL if invalid.
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)
2646 struct device *dev = to_device(isp_ccdc);
2647 - u32 syn_mode = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
2648 - ISPCCDC_SYN_MODE);
2650 - syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
2652 - if (syncif.fldstat)
2653 - syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
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;
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;
2666 - switch (syncif.ipmod) {
2670 - syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
2673 - syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
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");
2682 - syn_mode &= ISPCCDC_SYN_MODE_DATSIZ_MASK;
2683 - switch (syncif.datsz) {
2685 - syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
2688 - syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
2691 - syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
2694 - syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
2697 + if (lsc_cfg->offset & 3) {
2698 + dev_dbg(dev, "CCDC: LSC: Offset must be a multiple of 4\n");
2702 - if (syncif.fldmode)
2703 - syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
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");
2711 - if (syncif.datapol)
2712 - syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
2714 - syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
2718 - if (syncif.fldpol)
2719 - syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
2721 - syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
2722 + input_width = pipe->ccdc_in_w;
2723 + input_height = pipe->ccdc_in_h;
2726 - syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
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;
2734 + paxel_height = 1 << paxel_shift_y;
2735 + min_height = ((input_height + lsc_cfg->initial_y + paxel_height - 1)
2736 + >> paxel_shift_y) + 1;
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");
2743 + if (lsc_cfg->offset < (min_width * 4)) {
2744 + dev_dbg(dev, "CCDC: LSC: Offset is too small\n");
2747 + if ((lsc_cfg->size / lsc_cfg->offset) < min_height) {
2748 + dev_dbg(dev, "CCDC: LSC: Wrong size/offset combination\n");
2755 - syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
2757 - syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
2759 + * ispccdc_program_lsc - Program Lens Shading Compensation table address.
2761 +static void ispccdc_program_lsc(struct isp_ccdc_device *isp_ccdc)
2763 + isp_reg_writel(to_device(isp_ccdc), isp_ccdc->lsc_table_inuse,
2764 + OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
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);
2775 + * ispccdc_config_lsc - Configures the lens shading compensation module
2777 +static void ispccdc_config_lsc(struct isp_ccdc_device *isp_ccdc)
2779 + struct device *dev = to_device(isp_ccdc);
2780 + struct ispccdc_lsc_config *lsc_cfg = &isp_ccdc->lsc_config;
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);
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);
2794 - isp_reg_writel(dev, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
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);
2801 - if (!(syncif.bt_r656_en)) {
2802 - isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC,
2803 - ISPCCDC_REC656IF, ~ISPCCDC_REC656IF_R656ON);
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);
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.
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.
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)
2831 struct device *dev = to_device(isp_ccdc);
2832 - u32 bclamp_val = 0;
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);
2842 + isp_reg_or(dev, OMAP3_ISP_IOMEM_MAIN,
2843 + ISP_CTRL, ISPCTRL_SBL_SHARED_RPORTB
2844 + | ISPCTRL_SBL_RD_RAM_EN);
2846 + isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC,
2847 + ISPCCDC_LSC_CONFIG, ISPCCDC_LSC_ENABLE);
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);
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.
2873 +static void ispccdc_setup_lsc(struct isp_ccdc_device *isp_ccdc,
2874 + struct isp_pipeline *pipe)
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;
2887 + ispccdc_config_lsc(isp_ccdc);
2888 + ispccdc_program_lsc(isp_ccdc);
2890 + isp_ccdc->update_lsc_config = 0;
2893 +void ispccdc_lsc_error_handler(struct isp_ccdc_device *isp_ccdc)
2895 + ispccdc_enable_lsc(isp_ccdc, 0);
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.
2905 - * Enables or disables the optical black clamp. When disabled, the digital
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
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)
2920 - struct device *dev = to_device(isp_ccdc);
2921 + isp_ccdc->ccdcin_woffset = left + (left % 2);
2922 + isp_ccdc->ccdcin_hoffset = top + (top % 2);
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);
2931 + DPRINTK_ISPCCDC("\n\tOffsets L %d T %d W %d H %d\n",
2932 + isp_ccdc->ccdcin_woffset,
2933 + isp_ccdc->ccdcin_hoffset,
2935 + isp_ccdc->crop_h);
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
2946 + * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
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
2955 + * Returns 0 if successful, or -EINVAL if the offset is not in 32 byte
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)
2962 struct device *dev = to_device(isp_ccdc);
2965 - fpc_val = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
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);
2976 - DPRINTK_ISPCCDC("FPC Address should be on 64byte boundary\n");
2977 + DPRINTK_ISPCCDC("ISP_ERR : Offset should be in 32 byte"
2981 - isp_reg_writel(dev, fpc_val | (fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
2982 - OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
2987 - * ispccdc_enable_fpc - Enables the Faulty Pixel Correction.
2988 - * @enable: 0 Disables FPC, 1 Enables FPC.
2990 -void ispccdc_enable_fpc(struct isp_ccdc_device *isp_ccdc, u8 enable)
2992 - struct device *dev = to_device(isp_ccdc);
2993 + isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
2994 + ~ISPCCDC_SDOFST_FINV);
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);
3001 + switch (oddeven) {
3003 + isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3004 + (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
3007 + isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3008 + (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
3011 + isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3012 + (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
3015 + isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3016 + (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
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.
3031 + * Sets the memory address where the output will be saved.
3033 + * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
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)
3040 struct device *dev = to_device(isp_ccdc);
3041 - u32 blcomp_val = 0;
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);
3052 + DPRINTK_ISPCCDC("ISP_ERR : Address should be in 32 byte"
3057 - isp_reg_writel(dev, blcomp_val, OMAP3_ISP_IOMEM_CCDC,
3062 - * ispccdc_config_vp - Configures the Video Port Configuration parameters.
3063 - * @vpcfg: Structure containing the Video Port input frequency, and the 10 bit
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
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)
3075 struct device *dev = to_device(isp_ccdc);
3076 - u32 fmtcfg_vp = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
3078 + u32 syn_mode = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
3079 + ISPCCDC_SYN_MODE);
3081 - fmtcfg_vp &= ISPCCDC_FMTCFG_VPIN_MASK & ISPCCDC_FMTCFG_VPIF_FRQ_MASK;
3082 + syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
3084 - switch (vpcfg.bitshift_sel) {
3086 - fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
3089 - fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
3090 + if (syncif.fldstat)
3091 + syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
3093 + syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
3095 + syn_mode &= ISPCCDC_SYN_MODE_INPMOD_MASK;
3096 + isp_ccdc->syncif_ipmod = syncif.ipmod;
3098 + switch (syncif.ipmod) {
3102 - fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
3104 + syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
3107 - fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
3109 + syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
3112 - switch (vpcfg.freq_sel) {
3114 - fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY2;
3117 - fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY3;
3119 + syn_mode &= ISPCCDC_SYN_MODE_DATSIZ_MASK;
3120 + switch (syncif.datsz) {
3122 + syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
3125 - fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY4;
3127 + syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
3130 - fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY5;
3132 + syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
3135 - fmtcfg_vp |= ISPCCDC_FMTCFG_VPIF_FRQ_BY6;
3137 + syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
3140 - isp_reg_writel(dev, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
3144 - * ispccdc_enable_vp - Enables the Video Port.
3145 - * @enable: 0 Disables VP, 1 Enables VP
3147 -void ispccdc_enable_vp(struct isp_ccdc_device *isp_ccdc, u8 enable)
3149 - struct device *dev = to_device(isp_ccdc);
3150 + if (syncif.fldmode)
3151 + syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
3153 + syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
3155 - isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
3156 - ~ISPCCDC_FMTCFG_VPEN,
3157 - enable ? ISPCCDC_FMTCFG_VPEN : 0);
3159 + if (syncif.datapol)
3160 + syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
3162 + syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
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.
3169 - * Configures the Reformatter register values if line alternating is disabled.
3170 - * Else, just enabling line alternating is enough.
3172 -void ispccdc_config_reformatter(struct isp_ccdc_device *isp_ccdc,
3173 - struct ispccdc_refmt refmt)
3175 - struct device *dev = to_device(isp_ccdc);
3176 - u32 fmtcfg_val = 0;
3178 - fmtcfg_val = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
3181 - fmtcfg_val |= ISPCCDC_FMTCFG_LNALT;
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;
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);
3215 - isp_reg_writel(dev, fmtcfg_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
3217 + if (syncif.fldpol)
3218 + syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
3220 + syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
3223 - * ispccdc_enable_reformatter - Enables the Reformatter.
3224 - * @enable: 0 Disables Reformatter, 1- Enables Data Reformatter
3226 -void ispccdc_enable_reformatter(struct isp_ccdc_device *isp_ccdc, u8 enable)
3228 - struct device *dev = to_device(isp_ccdc);
3230 + syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
3232 + syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
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;
3240 + syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
3242 + syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
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.
3249 -void ispccdc_config_culling(struct isp_ccdc_device *isp_ccdc,
3250 - struct ispccdc_culling cull)
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);
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);
3268 + syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
3269 + ISPCCDC_SYN_MODE_VDHDOUT);
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);
3276 - isp_reg_writel(dev, culling_val, OMAP3_ISP_IOMEM_CCDC,
3278 + if (!(syncif.bt_r656_en)) {
3279 + isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC,
3280 + ISPCCDC_REC656IF, ~ISPCCDC_REC656IF_R656ON);
3285 - * ispccdc_enable_lpf - Enables the Low-Pass Filter (LPF).
3286 - * @enable: 0 Disables LPF, 1 Enables LPF
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.
3292 +void ispccdc_set_wenlog(struct isp_ccdc_device *isp_ccdc, u32 wenlog)
3294 - struct device *dev = to_device(isp_ccdc);
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;
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.
3309 + * Configures the default configuration for the CCDC to work with.
3311 + * The valid values for the input are CCDC_RAW (0), CCDC_YUV_SYNC (1),
3312 + * CCDC_YUV_BT (2), and CCDC_OTHERS (3).
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).
3317 + * Returns 0 if successful, or -EINVAL if wrong I/O combination or wrong input
3318 + * or output values.
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)
3325 struct device *dev = to_device(isp_ccdc);
3327 - isp_reg_writel(dev, ipwidth << ISPCCDC_ALAW_GWDI_SHIFT,
3328 - OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
3331 + struct ispccdc_vp vpcfg;
3332 + struct ispccdc_syncif syncif;
3333 + struct ispccdc_bclamp blkcfg;
3336 - * ispccdc_enable_alaw - Enables the A-law compression.
3337 - * @enable: 0 - Disables A-law, 1 - Enables A-law
3339 -void ispccdc_enable_alaw(struct isp_ccdc_device *isp_ccdc, u8 enable)
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;
3359 + syn_mode = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
3361 + switch (pipe->ccdc_out) {
3362 + case CCDC_YUV_RSZ:
3363 + syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
3364 + syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
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;
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);
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);
3396 - isp_reg_and_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW,
3397 - ~ISPCCDC_ALAW_CCDTBL,
3398 - enable ? ISPCCDC_ALAW_CCDTBL : 0);
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;
3407 - * ispccdc_config_imgattr - Configures the sensor image specific attributes.
3408 - * @colptn: Color pattern of the sensor.
3410 -void ispccdc_config_imgattr(struct isp_ccdc_device *isp_ccdc, u32 colptn)
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);
3421 + DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output\n");
3425 - isp_reg_writel(dev, colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
3427 + isp_reg_writel(dev, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
3429 -void ispccdc_config_shadow_registers(struct isp_ccdc_device *isp_ccdc)
3431 - if (isp_ccdc->lsc_enable) {
3432 - ispccdc_enable_lsc(isp_ccdc, 1);
3433 - isp_ccdc->lsc_enable = 0;
3434 + switch (pipe->ccdc_in) {
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;
3444 + syncif.ipmod = RAW;
3446 + ispccdc_config_sync_if(isp_ccdc, syncif);
3447 + ispccdc_config_imgattr(isp_ccdc, colptn);
3449 + blkcfg.dcsubval = 64;
3450 + ispccdc_config_black_clamp(isp_ccdc, blkcfg);
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;
3461 + syncif.ipmod = YUV16;
3463 + ispccdc_config_imgattr(isp_ccdc, 0);
3464 + ispccdc_config_sync_if(isp_ccdc, syncif);
3466 + blkcfg.dcsubval = 0;
3467 + ispccdc_config_black_clamp(isp_ccdc, blkcfg);
3474 + DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Input\n");
3478 + ispccdc_print_status(isp_ccdc, pipe);
3479 + isp_print_status(dev);
3484 @@ -1199,156 +1097,339 @@ int ispccdc_s_pipeline(struct isp_ccdc_d
3485 OMAP3_ISP_IOMEM_CCDC,
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);
3495 + ispccdc_setup_lsc(isp_ccdc, pipe);
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
3505 - * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
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
3512 + * ispccdc_enable - Enables the CCDC module.
3513 + * @enable: 0 Disables CCDC, 1 Enables CCDC
3515 - * Returns 0 if successful, or -EINVAL if the offset is not in 32 byte
3517 + * Client should configure all the sub modules in CCDC before this.
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)
3523 + struct isp_device *isp = to_isp_device(isp_ccdc);
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);
3537 + * Returns zero if the CCDC is idle and the image has been written to
3540 +int ispccdc_sbl_busy(void *_isp_ccdc)
3542 + struct isp_ccdc_device *isp_ccdc = _isp_ccdc;
3543 struct device *dev = to_device(isp_ccdc);
3545 - if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
3546 - isp_reg_writel(dev, (offset & 0xFFFF),
3547 - OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF);
3549 - DPRINTK_ISPCCDC("ISP_ERR : Offset should be in 32 byte"
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);
3563 + * ispccdc_busy - Gets busy state of the CCDC.
3565 +int ispccdc_busy(struct isp_ccdc_device *isp_ccdc)
3567 + struct device *dev = to_device(isp_ccdc);
3569 + return isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
3573 +void ispccdc_config_shadow_registers(struct isp_ccdc_device *isp_ccdc)
3575 + unsigned long flags;
3577 + spin_lock_irqsave(&isp_ccdc->lock, flags);
3578 + if (isp_ccdc->shadow_update)
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;
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;
3599 + spin_unlock_irqrestore(&isp_ccdc->lock, flags);
3603 + * ispccdc_config - Sets CCDC configuration from userspace
3604 + * @userspace_add: Structure containing CCDC configuration sent from userspace.
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.
3610 +int ispccdc_config(struct isp_ccdc_device *isp_ccdc,
3611 + void *userspace_add)
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;
3622 + if (userspace_add == NULL)
3625 + ccdc_struct = userspace_add;
3627 + spin_lock_irqsave(&isp_ccdc->lock, flags);
3628 + isp_ccdc->shadow_update = 1;
3629 + spin_unlock_irqrestore(&isp_ccdc->lock, flags);
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);
3638 + if (ISP_ABS_CCDC_LPF & ccdc_struct->flag)
3639 + ispccdc_enable_lpf(isp_ccdc, 1);
3641 + ispccdc_enable_lpf(isp_ccdc, 0);
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))) {
3652 + ispccdc_enable_black_clamp(isp_ccdc, 1);
3653 + ispccdc_config_black_clamp(isp_ccdc, bclamp_t);
3655 + ispccdc_enable_black_clamp(isp_ccdc, 1);
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))) {
3665 + ispccdc_enable_black_clamp(isp_ccdc, 0);
3666 + ispccdc_config_black_clamp(isp_ccdc, bclamp_t);
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))) {
3678 + ispccdc_config_black_comp(isp_ccdc, blcomp_t);
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 *)
3689 + isp_ccdc->fpc_table_add = kmalloc(64 + fpc_t.fpnum * 4,
3690 + GFP_KERNEL | GFP_DMA);
3691 + if (!isp_ccdc->fpc_table_add) {
3695 + while (((unsigned long)isp_ccdc->fpc_table_add
3697 + != (unsigned long)isp_ccdc->fpc_table_add)
3698 + isp_ccdc->fpc_table_add++;
3700 + isp_ccdc->fpc_table_add_m = iommu_kmap(
3703 + virt_to_phys(isp_ccdc->fpc_table_add),
3706 + /* FIXME: Correct unwinding */
3707 + BUG_ON(IS_ERR_VALUE(isp_ccdc->fpc_table_add_m));
3709 + if (copy_from_user(isp_ccdc->fpc_table_add,
3710 + (u32 *)fpc_t.fpcaddr,
3711 + fpc_t.fpnum * 4)) {
3716 + fpc_t.fpcaddr = isp_ccdc->fpc_table_add_m;
3717 + ispccdc_config_fpc(isp_ccdc, fpc_t);
3719 + ispccdc_enable_fpc(isp_ccdc, 1);
3720 + } else if (ISP_ABS_CCDC_FPC & ccdc_struct->update)
3721 + ispccdc_enable_fpc(isp_ccdc, 0);
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))) {
3730 + ispccdc_config_culling(isp_ccdc, cull_t);
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,
3741 + ret = ispccdc_validate_config_lsc(isp_ccdc, &cfg,
3742 + isp->running == ISP_RUNNING ?
3743 + &isp->pipeline : NULL);
3746 + memcpy(&isp_ccdc->lsc_config, &cfg,
3747 + sizeof(isp_ccdc->lsc_config));
3748 + isp_ccdc->lsc_request_enable = 1;
3750 + isp_ccdc->lsc_request_enable = 0;
3752 + isp_ccdc->update_lsc_config = 1;
3755 - isp_reg_and(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3756 - ~ISPCCDC_SDOFST_FINV);
3757 + if (ISP_ABS_TBL_LSC & ccdc_struct->update) {
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;
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)) {
3777 + isp_ccdc->update_lsc_table = 1;
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);
3786 - switch (oddeven) {
3788 - isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3789 - (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
3792 - isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3793 - (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
3796 - isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3797 - (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
3800 - isp_reg_or(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
3801 - (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
3807 + if (ISP_ABS_CCDC_COLPTN & ccdc_struct->update)
3808 + ispccdc_config_imgattr(isp_ccdc, ccdc_struct->colptn);
3811 + if (ret == -EFAULT)
3812 + dev_err(to_device(isp_ccdc),
3813 + "ccdc: user provided bad configuration data address");
3815 + if (ret == -ENOMEM)
3816 + dev_err(to_device(isp_ccdc),
3817 + "ccdc: can not allocate memory");
3819 + isp_ccdc->shadow_update = 0;
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.
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.
3831 - * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
3833 + * Returns 0 if successful, or -EBUSY if CCDC module is busy.
3835 -int ispccdc_set_outaddr(struct isp_ccdc_device *isp_ccdc, u32 addr)
3836 +int ispccdc_request(struct isp_ccdc_device *isp_ccdc)
3838 struct device *dev = to_device(isp_ccdc);
3840 - if ((addr & ISP_32B_BOUNDARY_BUF) == addr) {
3841 - isp_reg_writel(dev, addr, OMAP3_ISP_IOMEM_CCDC,
3842 - ISPCCDC_SDR_ADDR);
3845 - DPRINTK_ISPCCDC("ISP_ERR : Address should be in 32 byte"
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");
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);
3866 - * ispccdc_enable - Enables the CCDC module.
3867 - * @enable: 0 Disables CCDC, 1 Enables CCDC
3868 + * ispccdc_free - Frees the CCDC module.
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.
3873 + * Returns 0 if successful, or -EINVAL if module has been already freed.
3875 -void ispccdc_enable(struct isp_ccdc_device *isp_ccdc, u8 enable)
3876 +int ispccdc_free(struct isp_ccdc_device *isp_ccdc)
3878 - struct isp_device *isp = to_isp_device(isp_ccdc);
3881 - if (isp_ccdc->lsc_enable
3882 - && isp->pipeline.ccdc_in == CCDC_RAW)
3883 - ispccdc_enable_lsc(isp_ccdc, 1);
3886 - int lsc_enable = isp_ccdc->lsc_state;
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");
3897 - isp_reg_and_or(isp->dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR,
3898 - ~ISPCCDC_PCR_EN, enable ? ISPCCDC_PCR_EN : 0);
3902 - * Returns zero if the CCDC is idle and the image has been written to
3905 -int ispccdc_sbl_busy(void *_isp_ccdc)
3907 - struct isp_ccdc_device *isp_ccdc = _isp_ccdc;
3908 - struct device *dev = to_device(isp_ccdc);
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);
3922 - * ispccdc_busy - Gets busy state of the CCDC.
3924 -int ispccdc_busy(struct isp_ccdc_device *isp_ccdc)
3926 - struct device *dev = to_device(isp_ccdc);
3928 - return isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
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));
3940 @@ -1370,129 +1451,6 @@ void ispccdc_restore_context(struct devi
3944 - * ispccdc_print_status - Prints the values of the CCDC Module registers
3946 - * Also prints other debug information stored in the CCDC module.
3948 -void ispccdc_print_status(struct isp_ccdc_device *isp_ccdc,
3949 - struct isp_pipeline *pipe)
3951 - if (!is_ispccdc_debug_enabled())
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,
3964 - DPRINTK_ISPCCDC("ISP_CTRL =0x%x\n",
3965 - isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
3967 - switch (pipe->ccdc_in) {
3969 - DPRINTK_ISPCCDC("ccdc input format is CCDC_RAW\n");
3971 - case CCDC_YUV_SYNC:
3972 - DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_SYNC\n");
3975 - DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_BT\n");
3981 - switch (pipe->ccdc_out) {
3982 - case CCDC_OTHERS_VP:
3983 - DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_VP\n");
3985 - case CCDC_OTHERS_MEM:
3986 - DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_MEM\n");
3988 - case CCDC_YUV_RSZ:
3989 - DPRINTK_ISPCCDC("ccdc output format is CCDC_YUV_RSZ\n");
3995 - DPRINTK_ISPCCDC("###ISP_CTRL in ccdc =0x%x\n",
3996 - isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
3998 - DPRINTK_ISPCCDC("###ISP_IRQ0ENABLE in ccdc =0x%x\n",
3999 - isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
4001 - DPRINTK_ISPCCDC("###ISP_IRQ0STATUS in ccdc =0x%x\n",
4002 - isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN,
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,
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,
4031 - DPRINTK_ISPCCDC("###CCDC COLPTN=0x%x\n",
4032 - isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4034 - DPRINTK_ISPCCDC("###CCDC CFG=0x%x\n",
4035 - isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
4037 - DPRINTK_ISPCCDC("###CCDC VP_OUT=0x%x\n",
4038 - isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC,
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,
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));
4067 * isp_ccdc_init - CCDC module initialization.
4070 @@ -1501,24 +1459,34 @@ int __init isp_ccdc_init(struct device *
4072 struct isp_device *isp = dev_get_drvdata(dev);
4073 struct isp_ccdc_device *isp_ccdc = &isp->isp_ccdc;
4076 isp_ccdc->ccdc_inuse = 0;
4077 ispccdc_config_crop(isp_ccdc, 0, 0, 0, 0);
4078 mutex_init(&isp_ccdc->mutexlock);
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;
4093 + isp_ccdc->update_lsc_config = 0;
4094 + isp_ccdc->lsc_request_enable = 1;
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;
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))
4110 + p = da_to_va(isp->iommu, isp_ccdc->lsc_table_inuse);
4111 + memset(p, 0x40, LSC_TABLE_INIT_SIZE);
4113 + isp_ccdc->shadow_update = 0;
4114 + spin_lock_init(&isp_ccdc->lock);
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;
4122 - if (is_isplsc_activated()) {
4123 - ispccdc_free_lsc(isp_ccdc);
4124 - kfree(isp_ccdc->lsc_gain_table_tmp);
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);
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
4137 #include <mach/isp_user.h>
4139 -#define is_isplsc_activated() 1
4141 /* Enumeration constants for CCDC input output format */
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
4157 struct isp_ccdc_device {
4159 @@ -166,102 +172,39 @@ struct isp_ccdc_device {
4164 - u8 lsc_initialized;
4166 struct mutex mutexlock; /* For checking/modifying ccdc_inuse */
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;
4176 -int ispccdc_request(struct isp_ccdc_device *isp_ccdc);
4178 -int ispccdc_free(struct isp_ccdc_device *isp_ccdc);
4180 -void ispccdc_config_crop(struct isp_ccdc_device *isp_ccdc, u32 left, u32 top,
4181 - u32 height, u32 width);
4183 -void ispccdc_config_sync_if(struct isp_ccdc_device *isp_ccdc,
4184 - struct ispccdc_syncif syncif);
4186 -int ispccdc_config_black_clamp(struct isp_ccdc_device *isp_ccdc,
4187 - struct ispccdc_bclamp bclamp);
4189 -void ispccdc_enable_black_clamp(struct isp_ccdc_device *isp_ccdc, u8 enable);
4191 -int ispccdc_config_fpc(struct isp_ccdc_device *isp_ccdc,
4192 - struct ispccdc_fpc fpc);
4194 -void ispccdc_enable_fpc(struct isp_ccdc_device *isp_ccdc, u8 enable);
4196 -void ispccdc_config_black_comp(struct isp_ccdc_device *isp_ccdc,
4197 - struct ispccdc_blcomp blcomp);
4199 -void ispccdc_config_vp(struct isp_ccdc_device *isp_ccdc, struct ispccdc_vp vp);
4201 -void ispccdc_enable_vp(struct isp_ccdc_device *isp_ccdc, u8 enable);
4203 -void ispccdc_config_reformatter(struct isp_ccdc_device *isp_ccdc,
4204 - struct ispccdc_refmt refmt);
4206 -void ispccdc_enable_reformatter(struct isp_ccdc_device *isp_ccdc, u8 enable);
4208 -void ispccdc_config_culling(struct isp_ccdc_device *isp_ccdc,
4209 - struct ispccdc_culling culling);
4211 -void ispccdc_enable_lpf(struct isp_ccdc_device *isp_ccdc, u8 enable);
4213 -void ispccdc_config_alaw(struct isp_ccdc_device *isp_ccdc,
4214 - enum alaw_ipwidth ipwidth);
4216 -void ispccdc_enable_alaw(struct isp_ccdc_device *isp_ccdc, u8 enable);
4218 -int ispccdc_load_lsc(struct isp_ccdc_device *isp_ccdc, u8 *table_addr,
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;
4231 -void ispccdc_enable_lsc(struct isp_ccdc_device *isp_ccdc, u8 enable);
4232 + int shadow_update;
4236 void ispccdc_lsc_error_handler(struct isp_ccdc_device *isp_ccdc);
4238 -void ispccdc_config_imgattr(struct isp_ccdc_device *isp_ccdc, u32 colptn);
4240 -void ispccdc_config_shadow_registers(struct isp_ccdc_device *isp_ccdc);
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);
4247 int ispccdc_s_pipeline(struct isp_ccdc_device *isp_ccdc,
4248 struct isp_pipeline *pipe);
4250 -int ispccdc_config_outlineoffset(struct isp_ccdc_device *isp_ccdc, u32 offset,
4251 - u8 oddeven, u8 numlines);
4253 -int ispccdc_set_outaddr(struct isp_ccdc_device *isp_ccdc, u32 addr);
4255 void ispccdc_enable(struct isp_ccdc_device *isp_ccdc, u8 enable);
4257 int ispccdc_sbl_busy(void *_isp_ccdc);
4259 int ispccdc_busy(struct isp_ccdc_device *isp_ccdc);
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);
4268 void ispccdc_restore_context(struct device *dev);
4270 -void ispccdc_print_status(struct isp_ccdc_device *isp_ccdc,
4271 - struct isp_pipeline *pipe);
4273 -int omap34xx_isp_ccdc_config(struct isp_ccdc_device *isp_ccdc,
4274 - void *userspace_add);
4276 -void ispccdc_set_wenlog(struct isp_ccdc_device *isp_ccdc, u32 wenlog);
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 {
4284 /* Wait for this many hs_vs before anything else. */
4286 + /* Ignore statistic's interrupts until first good hs_vs. */
4291 @@ -361,7 +363,7 @@ struct isp_device {
4292 struct iommu *iommu;
4295 -void omap34xx_isp_hist_dma_done(struct device *dev);
4296 +void isp_hist_dma_done(struct device *dev);
4298 void isp_flush(struct device *dev);
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);
4306 isp_hist->update = 0;
4307 + isp_hist->stat.config_counter++;
4308 spin_unlock_irqrestore(&isp_hist->lock, irqflags);
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);
4315 - omap34xx_isp_hist_dma_done(dev);
4316 + isp_hist_dma_done(dev);
4318 isp_hist->waiting_dma = 0;
4320 @@ -568,8 +569,8 @@ static void isp_hist_update_params(struc
4322 * Returns 0 on success configuration.
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)
4329 struct device *dev = to_device(isp_hist);
4330 unsigned long irqflags;
4331 @@ -632,15 +633,15 @@ int omap34xx_isp_hist_config(struct isp_
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.
4339 * This API allows the user to request for histogram statistics.
4341 * Returns 0 on successful request.
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)
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
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.
4357 -void isphist_save_context(struct device *dev)
4358 +void isp_hist_save_context(struct device *dev)
4360 isp_save_context(dev, isphist_reg_list);
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.
4367 -void isphist_restore_context(struct device *dev)
4368 +void isp_hist_restore_context(struct device *dev)
4370 isp_restore_context(dev, isphist_reg_list);
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);
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
4398 ispstat_bufs_set_size(&isp_h3a->stat, isp_h3a->buf_size);
4399 isp_h3a->update = 0;
4400 + isp_h3a->stat.config_counter++;
4402 spin_unlock_irqrestore(isp_h3a->lock, irqflags);
4404 @@ -404,14 +405,14 @@ static void isph3a_aewb_set_params(struc
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.
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.
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)
4420 struct device *dev = to_device(isp_h3a);
4421 @@ -454,7 +455,7 @@ int omap34xx_isph3a_aewb_config(struct i
4425 -EXPORT_SYMBOL(omap34xx_isph3a_aewb_config);
4426 +EXPORT_SYMBOL(isph3a_aewb_config);
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.
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)
4439 struct device *dev = to_device(isp_h3a);
4440 unsigned long irqflags;
4441 @@ -517,7 +518,7 @@ int omap34xx_isph3a_aewb_request_statist
4445 -EXPORT_SYMBOL(omap34xx_isph3a_aewb_request_statistics);
4446 +EXPORT_SYMBOL(isph3a_aewb_request_statistics);
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;
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);
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);
4467 void isph3a_save_context(struct device *dev);
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"
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);
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
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)
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;
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;
4502 - spin_lock_irqsave(&isp_prev->lock, flags);
4503 isp_prev->shadow_update = 0;
4504 - spin_unlock_irqrestore(&isp_prev->lock, flags);
4509 - spin_lock_irqsave(&isp_prev->lock, flags);
4510 isp_prev->shadow_update = 0;
4511 - spin_unlock_irqrestore(&isp_prev->lock, flags);
4513 dev_err(dev, "preview: Config: Copy From User Error\n");
4516 -EXPORT_SYMBOL_GPL(omap34xx_isp_preview_config);
4517 +EXPORT_SYMBOL_GPL(isppreview_config);
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
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)
4530 struct device *dev = to_device(isp_prev);
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) {}
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);
4543 void isppreview_set_skip(struct isp_prev_device *isp_prev, u32 h, u32 v);
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 @@
4550 #define ISPHIST_HV_INFO_MASK 0x3FFF3FFF
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
4560 #include "smia-sensor.h"
4562 #define DEFAULT_XCLK 9600000 /* [Hz] */
4563 -#define DEFAULT_EXPOSURE 33946 /* [us] */
4565 +#define SMIA_CTRL_GAIN 0
4566 +#define SMIA_CTRL_EXPOSURE 1
4567 +#define SMIA_NCTRLS 2
4569 +#define CID_TO_CTRL(id) ((id) == V4L2_CID_GAIN ? SMIA_CTRL_GAIN : \
4570 + (id) == V4L2_CID_EXPOSURE ? \
4571 + SMIA_CTRL_EXPOSURE : \
4574 +#define VS6555_RESET_SHIFT_HACK 1
4576 /* Register definitions */
4579 #define REG_COARSE_EXPOSURE 0x0202
4580 #define REG_ANALOG_GAIN 0x0204
4582 +struct smia_sensor;
4584 +struct smia_sensor_type {
4585 + u8 manufacturer_id;
4588 + int ev_table_size;
4592 +/* Current values for V4L2 controls */
4593 +struct smia_control {
4597 + s32 default_value;
4599 + int (*set)(struct smia_sensor *, s32 value);
4602 +struct smia_sensor {
4603 + struct i2c_client *i2c_client;
4604 + struct i2c_driver driver;
4606 + /* Sensor information */
4607 + struct smia_sensor_type *type;
4608 + u8 revision_number;
4611 + /* V4L2 current control values */
4612 + struct smia_control controls[SMIA_NCTRLS];
4614 + struct smia_reglist *current_reglist;
4615 + struct v4l2_int_device *v4l2_int_device;
4616 + struct v4l2_fract timeperframe;
4618 + struct smia_sensor_platform_data *platform_data;
4620 + const struct firmware *fw;
4621 + struct smia_meta_reglist *meta_reglist;
4623 + enum v4l2_power power;
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);
4633 +/* SMIA-model gain is stored in precalculated tables here. In the model,
4634 + * reg = (c0-gain*c1) / (gain*m1-m0)
4636 + * The constants c0, m0, c1 and m1 depend on sensor.
4639 +/* Analog gain table for VS6555.
4642 + * m1 = -1 (erroneously -16 in silicon)
4646 +static u16 smia_gain_vs6555[] = {
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 */
4691 +/* Analog gain table for TCM8330MD.
4695 + * c1 = 36 (MMS uses 29)
4698 +static u16 smia_gain_tcm8330md[] = {
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 */
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
4741 - u8 manufacturer_id;
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 },
4750 + 0x01, 0x022b, "vs6555",
4751 + ARRAY_SIZE(smia_gain_vs6555), smia_gain_vs6555
4754 + 0x0c, 0x208a, "tcm8330md",
4755 + ARRAY_SIZE(smia_gain_tcm8330md), smia_gain_tcm8330md
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;
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.
4768 +static int smia_set_gain(struct smia_sensor *sensor, s32 gain)
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;
4775 + if (sensor->power == V4L2_POWER_OFF)
4778 + return smia_i2c_write_reg(sensor->i2c_client,
4779 + SMIA_REG_16BIT, REG_ANALOG_GAIN,
4780 + sensor->type->ev_table[gain]);
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.
4788 +static int smia_set_exposure(struct smia_sensor *sensor, s32 exptime)
4790 + int exposure_rows;
4792 + exptime = clamp(exptime, sensor->controls[SMIA_CTRL_EXPOSURE].minimum,
4793 + sensor->controls[SMIA_CTRL_EXPOSURE].maximum);
4795 + exposure_rows = smia_exposure_us_to_rows(sensor, &exptime);
4796 + sensor->controls[SMIA_CTRL_EXPOSURE].value = exptime;
4798 + if (sensor->power == V4L2_POWER_OFF)
4801 + return smia_i2c_write_reg(sensor->i2c_client,
4802 + SMIA_REG_16BIT, REG_COARSE_EXPOSURE, exposure_rows);
4805 static int smia_stream_on(struct v4l2_int_device *s)
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);
4812 +static int smia_update_controls(struct v4l2_int_device *s)
4814 + struct smia_sensor *sensor = s->priv;
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;
4829 + /* Adjust V4L2 control values and write them to the sensor */
4831 + for (i = 0; i < ARRAY_SIZE(sensor->controls); i++) {
4833 + if (!sensor->controls[i].set)
4835 + rval = sensor->controls[i].set(sensor,
4836 + sensor->controls[i].value);
4843 /* Must be called with power already enabled on the sensor */
4844 static int smia_configure(struct v4l2_int_device *s)
4846 @@ -223,17 +452,6 @@ static int smia_configure(struct v4l2_in
4850 - rval = smia_i2c_write_reg(sensor->i2c_client, SMIA_REG_8BIT,
4851 - REG_ANALOG_GAIN+1,
4852 - sensor->ctrl_gain << 4);
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));
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
4868 + rval = smia_update_controls(s);
4872 rval = sensor->platform_data->configure_interface(
4874 sensor->current_reglist->mode.window_width,
4875 @@ -313,21 +535,13 @@ static struct v4l2_queryctrl smia_ctrls[
4877 .id = V4L2_CID_GAIN,
4878 .type = V4L2_CTRL_TYPE_INTEGER,
4879 - .name = "Analog gain",
4883 - .default_value = 0,
4884 + .name = "Analog gain [0.1 EV]",
4885 .flags = V4L2_CTRL_FLAG_SLIDER,
4888 .id = V4L2_CID_EXPOSURE,
4889 .type = V4L2_CTRL_TYPE_INTEGER,
4890 .name = "Exposure time [us]",
4892 - .maximum = DEFAULT_EXPOSURE,
4894 - .default_value = DEFAULT_EXPOSURE,
4895 .flags = V4L2_CTRL_FLAG_SLIDER,
4898 @@ -336,7 +550,7 @@ static int smia_ioctl_queryctrl(struct v
4899 struct v4l2_queryctrl *a)
4901 struct smia_sensor *sensor = s->priv;
4905 rval = smia_ctrl_query(smia_ctrls, ARRAY_SIZE(smia_ctrls), a);
4907 @@ -344,16 +558,16 @@ static int smia_ioctl_queryctrl(struct v
4908 ARRAY_SIZE(smia_mode_ctrls), a);
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;
4921 + ctrl = CID_TO_CTRL(a->id);
4924 + if (!sensor->controls[ctrl].set)
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;
4934 @@ -362,6 +576,7 @@ static int smia_ioctl_g_ctrl(struct v4l2
4935 struct v4l2_control *vc)
4937 struct smia_sensor *sensor = s->priv;
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
4947 - case V4L2_CID_GAIN:
4948 - vc->value = sensor->ctrl_gain;
4950 - case V4L2_CID_EXPOSURE:
4951 - vc->value = sensor->ctrl_exposure;
4954 + ctrl = CID_TO_CTRL(vc->id);
4957 + if (!sensor->controls[ctrl].set)
4960 + vc->value = sensor->controls[ctrl].value;
4965 @@ -386,30 +598,13 @@ static int smia_ioctl_s_ctrl(struct v4l2
4966 struct v4l2_control *vc)
4968 struct smia_sensor *sensor = s->priv;
4969 - int exposure_rows;
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);
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,
4990 + int ctrl = CID_TO_CTRL(vc->id);
4993 + if (!sensor->controls[ctrl].set)
4997 + return sensor->controls[ctrl].set(sensor, vc->value);
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
5003 reglist = smia_reglist_find_mode_fmt(sensor->meta_reglist,
5004 sensor->current_reglist, f);
5007 - sensor->current_reglist = reglist;
5014 + sensor->current_reglist = reglist;
5015 + return smia_update_controls(s);
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);
5024 - sensor->current_reglist = reglist;
5031 + sensor->current_reglist = reglist;
5032 + return smia_update_controls(s);
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
5040 - sensor->model_id = model_id;
5041 sensor->revision_number = revision_number;
5042 - sensor->manufacturer_id = manufacturer_id;
5043 sensor->smia_version = smia_version;
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",
5051 - sensor->smia_version / 10, sensor->smia_version % 10);
5052 + model_id, smia_version / 10, smia_version % 10);
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)
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];
5073 + /* Initialize V4L2 controls */
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;
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;
5093 + /* Update identification string */
5094 + strncpy(s->name, sensor->type->name, V4L2NAMESIZE);
5095 s->name[V4L2NAMESIZE-1] = 0; /* Ensure NULL terminated string */
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);
5104 if (request_firmware(&sensor->fw, name,
5105 &sensor->i2c_client->dev)) {
5106 @@ -585,10 +796,74 @@ out_poweroff:
5110 +#if VS6555_RESET_SHIFT_HACK
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.
5116 +static int smia_vs6555_reset_shift_hack(struct v4l2_int_device *s)
5118 + struct smia_sensor *sensor = s->priv;
5127 + rval = smia_i2c_read_reg(sensor->i2c_client,
5128 + SMIA_REG_8BIT, 0x381c, &r381c);
5131 + rval = smia_i2c_read_reg(sensor->i2c_client,
5132 + SMIA_REG_8BIT, 0x381d, &r381d);
5135 + rval = smia_i2c_read_reg(sensor->i2c_client,
5136 + SMIA_REG_8BIT, 0x381e, &r381e);
5139 + rval = smia_i2c_read_reg(sensor->i2c_client,
5140 + SMIA_REG_8BIT, 0x381f, &r381f);
5144 + if (r381d != 0 && r381f != 0 &&
5145 + r381c == 0 && r381e == 0)
5148 + dev_dbg(&sensor->i2c_client->dev, "VS6555 HW misconfigured--"
5149 + "trying to reset (%02X%02X%02X%02X)\n",
5150 + r381c, r381d, r381e, r381f);
5152 + smia_stream_off(s);
5153 + smia_power_off(s);
5155 + rval = smia_power_on(s);
5158 + rval = smia_configure(s);
5161 + rval = smia_stream_on(s);
5164 + } while (--count > 0);
5166 + dev_warn(&sensor->i2c_client->dev,
5167 + "VS6555 reset failed--expect bad image\n");
5169 + return 0; /* Return zero nevertheless -- at least we tried */
5173 static int smia_ioctl_s_power(struct v4l2_int_device *s,
5174 enum v4l2_power new_state)
5176 struct smia_sensor *sensor = s->priv;
5177 + enum v4l2_power old_state = sensor->power;
5181 @@ -599,7 +874,7 @@ static int smia_ioctl_s_power(struct v4l
5182 new_state = V4L2_POWER_OFF;
5184 /* If we are already in this mode, do nothing */
5185 - if (sensor->power == new_state)
5186 + if (old_state == new_state)
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 */
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);
5199 @@ -625,23 +900,26 @@ static int smia_ioctl_s_power(struct v4l
5201 if (new_state == V4L2_POWER_ON) {
5202 /* Standby -> streaming */
5203 + sensor->power = V4L2_POWER_ON;
5204 rval = smia_configure(s);
5207 - if (sensor->power == V4L2_POWER_OFF)
5208 + if (old_state == V4L2_POWER_OFF)
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);
5218 /* Streaming -> standby */
5219 rval = smia_stream_off(s);
5224 - sensor->power = new_state;
5226 + sensor->power = (rval == 0) ? new_state : old_state;
5230 @@ -717,9 +995,6 @@ static int smia_probe(struct i2c_client
5231 sensor->i2c_client = client;
5232 i2c_set_clientdata(client, sensor);
5234 - sensor->ctrl_gain = 0;
5235 - sensor->ctrl_exposure = DEFAULT_EXPOSURE;
5237 rval = v4l2_int_device_register(sensor->v4l2_int_device);
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
5244 #ifndef SMIA_SENSOR_H
5245 #define SMIA_SENSOR_H
5247 -#include <linux/i2c.h>
5248 #include <media/v4l2-int-device.h>
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);
5255 -struct smia_sensor {
5256 - struct i2c_client *i2c_client;
5257 - struct i2c_driver driver;
5259 - /* Sensor information */
5261 - u8 revision_number;
5262 - u8 manufacturer_id;
5265 - /* V4L2 current control values */
5266 - s32 ctrl_exposure;
5269 - struct smia_reglist *current_reglist;
5270 - struct v4l2_int_device *v4l2_int_device;
5271 - struct v4l2_fract timeperframe;
5273 - struct smia_sensor_platform_data *platform_data;
5275 - const struct firmware *fw;
5276 - struct smia_meta_reglist *meta_reglist;
5278 - enum v4l2_power power;
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
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)
5294 /* resource configuration registers */
5296 #define DEVGROUP_OFFSET 0
5297 @@ -467,6 +472,31 @@ int twl4030_disable_regulator(int res)
5299 EXPORT_SYMBOL(twl4030_disable_regulator);
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
5311 +static void __init twl_workaround(void)
5314 + u8 reg[]={R_VDD1_OSC, R_VDD2_OSC, R_VIO_OSC};
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]);
5323 + pr_warning("TWL4030: workaround setup failed!\n");
5326 void __init twl4030_power_init(struct twl4030_power_data *triton2_scripts)
5329 @@ -502,6 +532,8 @@ void __init twl4030_power_init(struct tw
5333 + /* TODO: introduce workaround based on TWL4030 revision */
5335 if (twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY))
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"
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
5362 + * Copyright (C) Nokia Corporation
5364 + * Contact: Atal Shargorodsky <ext-atal.shargorodsky@nokia.com>
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.
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.
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
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>
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;
5391 +static int panic_info_buff_open(struct inode *inode, struct file *file)
5396 +static ssize_t panic_info_buff_write(struct file *file,
5397 + const char __user *buf, size_t len, loff_t *off)
5399 + if (len >= PANIC_BUFFER_MAX_LEN)
5401 + if (copy_from_user(panic_info_buff, buf, len))
5403 + panic_info_buff[len] = '\0';
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,
5414 +static int panic_info_buff_event(struct notifier_block *this,
5415 + unsigned long event, void *ptr)
5417 + if (panic_info_buff[0] == '\0') {
5418 + printk(KERN_EMERG "Panic info buffer is empty.\n");
5420 + printk(KERN_EMERG "Panic info buffer:\n");
5421 + printk(KERN_EMERG "%s\n", panic_info_buff);
5426 +static struct notifier_block panic_info_buff_block = {
5427 + .notifier_call = panic_info_buff_event,
5431 +static int __devinit panic_info_buff_init(void)
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);
5440 +module_init(panic_info_buff_init);
5442 +static void __devexit panic_info_buff_exit(void)
5444 + debugfs_remove(panic_info_buff_debugfs);
5445 + atomic_notifier_chain_unregister(&panic_notifier_list,
5446 + &panic_info_buff_block);
5449 +module_exit(panic_info_buff_exit);
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
5459 /* Channel states */
5460 #define SSI_CH_OPEN 0x01
5461 +#define SSI_CH_RX_POLL 0x10
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 {
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,
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
5482 #include "ssi_driver.h"
5484 +#define NOT_SET (-1)
5486 +int ssi_set_rx(struct ssi_port *sport, struct ssr_ctx *cfg)
5488 + struct ssi_dev *ssi_ctrl = sport->ssi_controller;
5489 + void __iomem *base = ssi_ctrl->base;
5490 + int port = sport->port_number;
5492 + if ((cfg->mode != SSI_MODE_STREAM) &&
5493 + (cfg->mode != SSI_MODE_FRAME) &&
5494 + (cfg->mode != SSI_MODE_SLEEP) &&
5495 + (cfg->mode != NOT_SET))
5498 + if ((cfg->frame_size > SSI_MAX_FRAME_SIZE) &&
5499 + (cfg->frame_size != NOT_SET))
5502 + if ((cfg->channels == 0) ||
5503 + ((cfg->channels > SSI_CHANNELS_DEFAULT) &&
5504 + (cfg->channels != NOT_SET)))
5507 + if ((cfg->timeout > SSI_MAX_RX_TIMEOUT) && (cfg->timeout != NOT_SET))
5510 + if (cfg->mode != NOT_SET)
5511 + ssi_outl(cfg->mode, base, SSI_SSR_MODE_REG(port));
5513 + if (cfg->frame_size != NOT_SET)
5514 + ssi_outl(cfg->frame_size, base, SSI_SSR_FRAMESIZE_REG(port));
5516 + if (cfg->channels != NOT_SET) {
5517 + if ((cfg->channels & (-cfg->channels)) ^ cfg->channels)
5520 + ssi_outl(cfg->channels, base,
5521 + SSI_SSR_CHANNELS_REG(port));
5524 + if (cfg->timeout != NOT_SET)
5525 + ssi_outl(cfg->timeout, base, SSI_SSR_TIMEOUT_REG(port));
5530 +void ssi_get_rx(struct ssi_port *sport, struct ssr_ctx *cfg)
5532 + struct ssi_dev *ssi_ctrl = sport->ssi_controller;
5533 + void __iomem *base = ssi_ctrl->base;
5534 + int port = sport->port_number;
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));
5542 +int ssi_set_tx(struct ssi_port *sport, struct sst_ctx *cfg)
5544 + struct ssi_dev *ssi_ctrl = sport->ssi_controller;
5545 + void __iomem *base = ssi_ctrl->base;
5546 + int port = sport->port_number;
5548 + if ((cfg->mode != SSI_MODE_STREAM) &&
5549 + (cfg->mode != SSI_MODE_FRAME) &&
5550 + (cfg->mode != NOT_SET))
5553 + if ((cfg->frame_size > SSI_MAX_FRAME_SIZE) &&
5554 + (cfg->frame_size != NOT_SET))
5557 + if ((cfg->channels == 0) ||
5558 + ((cfg->channels > SSI_CHANNELS_DEFAULT) &&
5559 + (cfg->channels != NOT_SET)))
5562 + if ((cfg->divisor > SSI_MAX_TX_DIVISOR) && (cfg->divisor != NOT_SET))
5565 + if ((cfg->arb_mode != SSI_ARBMODE_ROUNDROBIN) &&
5566 + (cfg->arb_mode != SSI_ARBMODE_PRIORITY) &&
5567 + (cfg->mode != NOT_SET))
5570 + if (cfg->mode != NOT_SET)
5571 + ssi_outl(cfg->channels, base, SSI_SST_CHANNELS_REG(port));
5573 + if (cfg->frame_size != NOT_SET)
5574 + ssi_outl(cfg->frame_size, base, SSI_SST_FRAMESIZE_REG(port));
5576 + if (cfg->channels != NOT_SET) {
5577 + if ((cfg->channels & (-cfg->channels)) ^ cfg->channels)
5580 + ssi_outl(cfg->mode, base, SSI_SST_MODE_REG(port));
5583 + if (cfg->divisor != NOT_SET)
5584 + ssi_outl(cfg->divisor, base, SSI_SST_DIVISOR_REG(port));
5586 + if (cfg->arb_mode != NOT_SET)
5587 + ssi_outl(cfg->arb_mode, base, SSI_SST_ARBMODE_REG(port));
5592 +void ssi_get_tx(struct ssi_port *sport, struct sst_ctx *cfg)
5594 + struct ssi_dev *ssi_ctrl = sport->ssi_controller;
5595 + void __iomem *base = ssi_ctrl->base;
5596 + int port = sport->port_number;
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));
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);
5612 + * ssi_poll - SSI poll
5613 + * @dev - ssi device channel reference to apply the I/O control
5614 + * (or port associated to it)
5616 + * Return 0 on sucess, a negative value on failure.
5619 +int ssi_poll(struct ssi_device *dev)
5621 + struct ssi_channel *ch;
5624 + if (unlikely(!dev || !dev->ch))
5627 + if (unlikely(!(dev->ch->flags & SSI_CH_OPEN))) {
5628 + dev_err(&dev->device, "SSI device NOT open\n");
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);
5640 +EXPORT_SYMBOL(ssi_poll);
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
5649 *(unsigned int *)arg = ssi_cawake(dev->ch->ssi_port);
5651 + case SSI_IOCTL_SET_RX:
5656 + err = ssi_set_rx(dev->ch->ssi_port, (struct ssr_ctx *)arg);
5658 + case SSI_IOCTL_GET_RX:
5663 + ssi_get_rx(dev->ch->ssi_port, (struct ssr_ctx *)arg);
5665 + case SSI_IOCTL_SET_TX:
5670 + err = ssi_set_tx(dev->ch->ssi_port, (struct sst_ctx *)arg);
5672 + case SSI_IOCTL_GET_TX:
5677 + ssi_get_tx(dev->ch->ssi_port, (struct sst_ctx *)arg);
5678 case SSI_IOCTL_TX_CH_FULL:
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
5686 void ssi_reset_ch_read(struct ssi_channel *ch)
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;
5695 ch->read_data.addr = NULL;
5696 ch->read_data.size = 0;
5697 ch->read_data.lch = -1;
5699 + ssi_outl(SSI_SSR_DATAAVAILABLE(channel), base,
5700 + SSI_SYS_MPU_STATUS_REG(port, irq));
5703 void ssi_reset_ch_write(struct ssi_channel *ch)
5704 @@ -145,6 +155,8 @@ static void do_channel_rx(struct ssi_cha
5709 + int data_read = 0;
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
5715 spin_lock(&ssi_ctrl->lock);
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)
5721 + if (ch->read_data.addr) {
5723 + *(ch->read_data.addr) = ssi_inl(base,
5724 + SSI_SSR_BUFFER_CH_REG(n_p, n_ch));
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
5731 spin_unlock(&ssi_ctrl->lock);
5733 - (*ch->read_done)(ch->dev);
5735 + ssi_port_event_handler(ch->ssi_port,
5736 + SSI_EVENT_SSR_DATAAVAILABLE,
5740 + (*ch->read_done)(ch->dev);
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
5749 +# OMAP SSI kernel configuration
5753 + tristate "SSI character driver"
5754 + depends on OMAP_SSI
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.
5760 +config SSI_CHAR_DEBUG
5761 + bool "Debug CMT character driver"
5762 + depends on SSI_CHAR && DEBUG_KERNEL
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
5771 +# Makefile for SSI CHAR driver
5773 +#EXTRA_CFLAGS := -I$(src)/../../../include
5775 +obj-$(CONFIG_SSI_CHAR) += ssi_char.o
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
5785 + * SSI character device driver, implements the character device
5788 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
5790 + * Contact: Andras Domokos <andras.domokos@nokia.com>
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.
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.
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
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>
5823 +#include <mach/ssi.h>
5824 +#include <linux/ssi_driver_if.h>
5825 +#include <linux/ssi_char.h>
5827 +#include "ssi-char-debug.h"
5828 +#include "ssi-char.h"
5830 +#define DRIVER_VERSION "0.1.0"
5832 +static unsigned int port = 1;
5833 +module_param(port, uint, 1);
5834 +MODULE_PARM_DESC(port, "SSI port to be probed");
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");
5840 +dev_t ssi_char_dev;
5842 +struct char_queue {
5843 + struct list_head list;
5845 + unsigned int count;
5849 + unsigned int opened;
5851 + struct list_head rx_queue;
5852 + struct list_head tx_queue;
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;
5860 +static struct ssi_char ssi_char_data[SSI_MAX_CHAR_DEVS];
5862 +void if_notify(int ch, struct ssi_event *ev)
5864 + struct char_queue *entry;
5866 + spin_lock(&ssi_char_data[ch].lock);
5868 + if (!ssi_char_data[ch].opened) {
5869 + printk(KERN_DEBUG "device not opened\n!");
5870 + spin_unlock(&ssi_char_data[ch].lock);
5874 + switch (SSI_EV_TYPE(ev->event)) {
5876 + entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
5878 + pr_err("SSI-CHAR: entry allocation failed.\n");
5879 + spin_unlock(&ssi_char_data[ch].lock);
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);
5889 + entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
5891 + pr_err("SSI-CHAR: entry allocation failed.\n");
5892 + spin_unlock(&ssi_char_data[ch].lock);
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);
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);
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);
5913 + spin_unlock(&ssi_char_data[ch].lock);
5919 +static int ssi_char_fasync(int fd, struct file *file, int on)
5921 + int ch = (int)file->private_data;
5922 + if (fasync_helper(fd, file, on, &ssi_char_data[ch].async_queue) >= 0)
5929 +static unsigned int ssi_char_poll(struct file *file, poll_table *wait)
5931 + int ch = (int)file->private_data;
5932 + unsigned int ret = 0;
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);
5944 +static ssize_t ssi_char_read(struct file *file, char __user *buf,
5945 + size_t count, loff_t *ppos)
5947 + int ch = (int)file->private_data;
5948 + DECLARE_WAITQUEUE(wait, current);
5950 + unsigned int data_len;
5951 + struct char_queue *entry;
5954 + /* only 32bit data is supported for now */
5955 + if ((count < 4) || (count & 3))
5958 + data = kmalloc(count, GFP_ATOMIC);
5960 + ret = if_ssi_read(ch, data, count);
5966 + add_wait_queue(&ssi_char_data[ch].rx_wait, &wait);
5972 + set_current_state(TASK_INTERRUPTIBLE);
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);
5983 + spin_unlock_bh(&ssi_char_data[ch].lock);
5986 + spin_lock_bh(&ssi_char_data[ch].lock);
5987 + ssi_char_data[ch].poll_event &= ~(POLLIN | POLLRDNORM |
5990 + spin_unlock_bh(&ssi_char_data[ch].lock);
5992 + } else if (file->f_flags & O_NONBLOCK) {
5995 + } else if (signal_pending(current)) {
5997 + if_ssi_cancel_read(ch);
6005 + ret = copy_to_user((void __user *)buf, data, data_len);
6013 + __set_current_state(TASK_RUNNING);
6014 + remove_wait_queue(&ssi_char_data[ch].rx_wait, &wait);
6020 +static ssize_t ssi_char_write(struct file *file, const char __user *buf,
6021 + size_t count, loff_t *ppos)
6023 + int ch = (int)file->private_data;
6024 + DECLARE_WAITQUEUE(wait, current);
6026 + unsigned int data_len = 0;
6027 + struct char_queue *entry;
6030 + /* only 32bit data is supported for now */
6031 + if ((count < 4) || (count & 3))
6034 + data = kmalloc(count, GFP_ATOMIC);
6036 + if (copy_from_user(data, (void __user *)buf, count)) {
6043 + spin_lock_bh(&ssi_char_data[ch].lock);
6044 + ret = if_ssi_write(ch, data, count);
6046 + spin_unlock_bh(&ssi_char_data[ch].lock);
6050 + ssi_char_data[ch].poll_event &= ~(POLLOUT | POLLWRNORM);
6051 + spin_unlock_bh(&ssi_char_data[ch].lock);
6053 + add_wait_queue(&ssi_char_data[ch].tx_wait, &wait);
6059 + set_current_state(TASK_INTERRUPTIBLE);
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);
6070 + spin_unlock_bh(&ssi_char_data[ch].lock);
6075 + } else if (file->f_flags & O_NONBLOCK) {
6078 + } else if (signal_pending(current)) {
6079 + ret = -ERESTARTSYS;
6089 + __set_current_state(TASK_RUNNING);
6090 + remove_wait_queue(&ssi_char_data[ch].tx_wait, &wait);
6096 +static int ssi_char_ioctl(struct inode *inode, struct file *file,
6097 + unsigned int cmd, unsigned long arg)
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;
6106 + case CS_SEND_BREAK:
6107 + if_ssi_send_break(ch);
6110 + if_ssi_flush_rx(ch);
6113 + if_ssi_flush_tx(ch);
6115 + case CS_SET_WAKELINE:
6116 + if (copy_from_user(&state, (void __user *)arg,
6120 + if_ssi_set_wakeline(ch, state);
6122 + case CS_GET_WAKELINE:
6123 + if_ssi_get_wakeline(ch, &state);
6124 + if (copy_to_user((void __user *)arg, &state, sizeof(state)))
6128 + if (copy_from_user(&rx_cfg, (void __user *)arg,
6132 + ret = if_ssi_set_rx(ch, &rx_cfg);
6136 + if_ssi_get_rx(ch, &rx_cfg);
6137 + if (copy_to_user((void __user *)arg, &rx_cfg, sizeof(rx_cfg)))
6141 + if (copy_from_user(&tx_cfg, (void __user *)arg,
6145 + ret = if_ssi_set_tx(ch, &tx_cfg);
6148 + if_ssi_get_tx(ch, &tx_cfg);
6149 + if (copy_to_user((void __user *)arg, &tx_cfg, sizeof(tx_cfg)))
6153 + return -ENOIOCTLCMD;
6160 +static int ssi_char_open(struct inode *inode, struct file *file)
6162 + int ret = 0, ch = iminor(inode);
6164 + if (!channels_map[ch])
6167 + spin_lock_bh(&ssi_char_data[ch].lock);
6169 + if (ssi_char_data[ch].opened) {
6170 + spin_unlock_bh(&ssi_char_data[ch].lock);
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);
6179 + ret = if_ssi_start(ch);
6184 +static int ssi_char_release(struct inode *inode, struct file *file)
6186 + int ch = (int)file->private_data;
6187 + struct char_queue *entry;
6188 + struct list_head *cursor, *next;
6191 + spin_lock_bh(&ssi_char_data[ch].lock);
6192 + ssi_char_data[ch].opened--;
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);
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);
6210 + spin_unlock_bh(&ssi_char_data[ch].lock);
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,
6226 +static struct cdev ssi_char_cdev;
6228 +static int __init ssi_char_init(void)
6230 + char devname[] = "ssi_char";
6233 + pr_info("SSI character device version " DRIVER_VERSION "\n");
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);
6245 + ret = if_ssi_init(port, channels_map);
6249 + ret = alloc_chrdev_region(&ssi_char_dev, 0, SSI_MAX_CHAR_DEVS, devname);
6251 + pr_err("SSI character driver: Failed to register\n");
6255 + cdev_init(&ssi_char_cdev, &ssi_char_fops);
6256 + cdev_add(&ssi_char_cdev, ssi_char_dev, SSI_MAX_CHAR_DEVS);
6261 +static void __exit ssi_char_exit(void)
6263 + cdev_del(&ssi_char_cdev);
6264 + unregister_chrdev_region(ssi_char_dev, SSI_MAX_CHAR_DEVS);
6268 +MODULE_AUTHOR("Andras Domokos <andras.domokos@nokia.com>");
6269 +MODULE_DESCRIPTION("SSI character device");
6270 +MODULE_LICENSE("GPL");
6271 +MODULE_VERSION(DRIVER_VERSION);
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
6280 + * ssi-char-debug.h
6282 + * Part of the SSI character driver. Debugging related definitions.
6284 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
6286 + * Contact: Andras Domokos <andras.domokos@nokia.com>
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.
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.
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
6304 +#ifndef _SSI_CHAR_DEBUG_H
6305 +#define _SSI_CHAR_DEBUG_H
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)
6312 +#define DPRINTK(fmt, arg...) while (0)
6313 +#define DENTER() while (0)
6314 +#define DLEAVE(a) while (0)
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
6325 + * Part of the SSI character device driver.
6327 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
6329 + * Contact: Andras Domokos <andras.domokos@nokia.com>
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.
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.
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
6347 +#ifndef _SSI_CHAR_H
6348 +#define _SSI_CHAR_H
6350 +#include "ssi-if.h"
6352 +/* how many char devices would be created at most */
6353 +#define SSI_MAX_CHAR_DEVS 8
6355 +void if_notify(int ch, struct ssi_event *ev);
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
6365 + * Part of the SSI character driver, implements the SSI interface.
6367 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
6369 + * Contact: Andras Domokos <andras.domokos@nokia.com>
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.
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.
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
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>
6398 +#include <linux/ssi_driver_if.h>
6399 +#include <linux/ssi_char.h>
6401 +#include "ssi-char-debug.h"
6402 +#include "ssi-char.h"
6403 +#include "ssi-if.h"
6405 +#define SSI_CHANNEL_STATE_UNAVAIL (1 << 0)
6406 +#define SSI_CHANNEL_STATE_READING (1 << 1)
6407 +#define SSI_CHANNEL_STATE_WRITING (1 << 2)
6412 +#define SSI_RX_PARAM(cfg, mod, fsize, n, tmo) \
6414 + (cfg)->mode = mod; \
6415 + (cfg)->frame_size = fsize; \
6416 + (cfg)->channels = n; \
6417 + (cfg)->timeout = tmo; \
6420 +#define SSI_TX_PARAM(cfg, mod, fsize, n, div, arb) \
6422 + (cfg)->mode = mod; \
6423 + (cfg)->frame_size = fsize; \
6424 + (cfg)->channels = n; \
6425 + (cfg)->divisor = div; \
6426 + (cfg)->arb_mode = arb; \
6429 +#define RXCONV(dst, src) \
6431 + (dst)->mode = (src)->mode; \
6432 + (dst)->frame_size = (src)->frame_size; \
6433 + (dst)->channels = (src)->channels; \
6434 + (dst)->timeout = (src)->timeout; \
6437 +#define TXCONV(dst, src) \
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; \
6446 +struct if_ssi_channel {
6447 + struct ssi_device *dev;
6448 + unsigned int channel_id;
6450 + unsigned int tx_count;
6452 + unsigned int rx_count;
6453 + unsigned int opened;
6454 + unsigned int state;
6458 +struct if_ssi_iface {
6459 + struct if_ssi_channel channels[SSI_MAX_CHAR_DEVS];
6464 +static void if_ssi_port_event(struct ssi_device *dev, unsigned int event,
6466 +static int __devinit if_ssi_probe(struct ssi_device *dev);
6467 +static int __devexit if_ssi_remove(struct ssi_device *dev);
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),
6474 + .name = "ssi_char"
6478 +static struct if_ssi_iface ssi_iface;
6480 +static int if_ssi_read_on(int ch, u32 *data, unsigned int count)
6482 + struct if_ssi_channel *channel;
6485 + channel = &ssi_iface.channels[ch];
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);
6493 + channel->state |= SSI_CHANNEL_STATE_READING;
6494 + channel->rx_data = data;
6495 + channel->rx_count = count;
6496 + spin_unlock(&channel->lock);
6498 + ret = ssi_read(channel->dev, data, count/4);
6503 +static void if_ssi_read_done(struct ssi_device *dev)
6505 + struct if_ssi_channel *channel;
6506 + struct ssi_event ev;
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);
6518 +int if_ssi_read(int ch, u32 *data, unsigned int count)
6521 + spin_lock_bh(&ssi_iface.lock);
6522 + ret = if_ssi_read_on(ch, data, count);
6523 + spin_unlock_bh(&ssi_iface.lock);
6527 +int if_ssi_poll(int ch)
6529 + struct if_ssi_channel *channel;
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);
6538 +static int if_ssi_write_on(int ch, u32 *address, unsigned int count)
6540 + struct if_ssi_channel *channel;
6543 + channel = &ssi_iface.channels[ch];
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);
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);
6560 +static void if_ssi_write_done(struct ssi_device *dev)
6562 + struct if_ssi_channel *channel;
6563 + struct ssi_event ev;
6565 + channel = &ssi_iface.channels[dev->n_ch];
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);
6576 +int if_ssi_write(int ch, u32 *data, unsigned int count)
6580 + spin_lock_bh(&ssi_iface.lock);
6581 + ret = if_ssi_write_on(ch, data, count);
6582 + spin_unlock_bh(&ssi_iface.lock);
6586 +void if_ssi_send_break(int ch)
6588 + struct if_ssi_channel *channel;
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);
6596 +void if_ssi_flush_rx(int ch)
6598 + struct if_ssi_channel *channel;
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);
6606 +void if_ssi_flush_ch(int ch)
6608 + struct if_ssi_channel *channel;
6610 + channel = &ssi_iface.channels[ch];
6611 + spin_lock(&channel->lock);
6612 + spin_unlock(&channel->lock);
6615 +void if_ssi_flush_tx(int ch)
6617 + struct if_ssi_channel *channel;
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);
6625 +void if_ssi_get_wakeline(int ch, unsigned int *state)
6627 + struct if_ssi_channel *channel;
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);
6635 +void if_ssi_set_wakeline(int ch, unsigned int state)
6637 + struct if_ssi_channel *channel;
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);
6645 +int if_ssi_set_rx(int ch, struct ssi_rx_config *cfg)
6648 + struct if_ssi_channel *channel;
6649 + struct ssr_ctx ctx;
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);
6659 +void if_ssi_get_rx(int ch, struct ssi_rx_config *cfg)
6661 + struct if_ssi_channel *channel;
6662 + struct ssr_ctx ctx;
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);
6671 +int if_ssi_set_tx(int ch, struct ssi_tx_config *cfg)
6674 + struct if_ssi_channel *channel;
6675 + struct sst_ctx ctx;
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);
6685 +void if_ssi_get_tx(int ch, struct ssi_tx_config *cfg)
6687 + struct if_ssi_channel *channel;
6688 + struct sst_ctx ctx;
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);
6697 +void if_ssi_cancel_read(int ch)
6699 + struct if_ssi_channel *channel;
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);
6709 +void if_ssi_cancel_write(int ch)
6711 + struct if_ssi_channel *channel;
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);
6721 +static int if_ssi_openchannel(struct if_ssi_channel *channel)
6725 + spin_lock(&channel->lock);
6727 + if (channel->state == SSI_CHANNEL_STATE_UNAVAIL)
6730 + if (channel->opened) {
6735 + if (!channel->dev) {
6736 + pr_err("Channel %d is not ready??\n",
6737 + channel->channel_id);
6742 + ret = ssi_open(channel->dev);
6744 + pr_err("Could not open channel %d\n",
6745 + channel->channel_id);
6749 + channel->opened = 1;
6752 + spin_unlock(&channel->lock);
6757 +static int if_ssi_closechannel(struct if_ssi_channel *channel)
6761 + spin_lock(&channel->lock);
6763 + if (!channel->opened)
6766 + if (!channel->dev) {
6767 + pr_err("Channel %d is not ready??\n",
6768 + channel->channel_id);
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;
6778 + if (channel->state & SSI_CHANNEL_STATE_WRITING) {
6779 + ssi_write_cancel(channel->dev);
6780 + channel->state &= ~SSI_CHANNEL_STATE_WRITING;
6783 + ssi_close(channel->dev);
6785 + channel->opened = 0;
6787 + spin_unlock(&channel->lock);
6792 +int if_ssi_start(int ch)
6794 + struct if_ssi_channel *channel;
6797 + channel = &ssi_iface.channels[ch];
6798 + spin_lock_bh(&ssi_iface.lock);
6799 + channel->state = 0;
6800 + ret = if_ssi_openchannel(channel);
6802 + pr_err("Could not open channel %d\n", ch);
6803 + spin_unlock_bh(&ssi_iface.lock);
6807 + spin_unlock_bh(&ssi_iface.lock);
6813 +void if_ssi_stop(int ch)
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);
6823 +static int __devinit if_ssi_probe(struct ssi_device *dev)
6825 + struct if_ssi_channel *channel;
6826 + unsigned long *address;
6827 + int ret = -ENXIO, port;
6829 + for (port = 0; port < SSI_MAX_PORTS; port++) {
6830 + if (if_ssi_char_driver.ch_mask[port])
6834 + if (port == SSI_MAX_PORTS)
6837 + address = &if_ssi_char_driver.ch_mask[port];
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;
6849 + spin_unlock_bh(&ssi_iface.lock);
6854 +static int __devexit if_ssi_remove(struct ssi_device *dev)
6856 + struct if_ssi_channel *channel;
6857 + unsigned long *address;
6858 + int ret = -ENXIO, port;
6860 + for (port = 0; port < SSI_MAX_PORTS; port++) {
6861 + if (if_ssi_char_driver.ch_mask[port])
6865 + if (port == SSI_MAX_PORTS)
6868 + address = &if_ssi_char_driver.ch_mask[port];
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;
6879 + spin_unlock_bh(&ssi_iface.lock);
6884 +static void if_ssi_port_event(struct ssi_device *dev, unsigned int event,
6887 + struct ssi_event ev;
6890 + ev.event = SSI_EV_EXCEP;
6891 + ev.data = (u32 *)0;
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);
6902 + spin_unlock_bh(&ssi_iface.lock);
6904 + case SSI_EVENT_SSR_DATAAVAILABLE:
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);
6912 + case SSI_EVENT_CAWAKE_UP:
6914 + case SSI_EVENT_CAWAKE_DOWN:
6916 + case SSI_EVENT_ERROR:
6919 + printk(KERN_DEBUG "%s, Unknown event(%d)\n", __func__, event);
6924 +int __init if_ssi_init(unsigned int port, unsigned int *channels_map)
6926 + struct if_ssi_channel *channel;
6930 + if (port >= SSI_MAX_PORTS)
6933 + ssi_iface.bootstrap = 1;
6934 + spin_lock_init(&ssi_iface.lock);
6936 + for (i = 0; i < SSI_MAX_PORTS; i++)
6937 + if_ssi_char_driver.ch_mask[i] = 0;
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;
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)));
6954 + ret = register_ssi_driver(&if_ssi_char_driver);
6956 + pr_err("Error while registering SSI driver %d", ret);
6961 +int __exit if_ssi_exit(void)
6963 + struct if_ssi_channel *channel;
6964 + unsigned long *address;
6967 + for (port = 0; port < SSI_MAX_PORTS; port++) {
6968 + if (if_ssi_char_driver.ch_mask[port])
6972 + if (port == SSI_MAX_PORTS)
6975 + address = &if_ssi_char_driver.ch_mask[port];
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);
6984 + unregister_ssi_driver(&if_ssi_char_driver);
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
6994 + * Part of the SSI character driver.
6996 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
6998 + * Contact: Andras Domokos <andras.domokos@nokia.com>
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.
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.
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
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)
7027 +#define SSI_HWBREAK 1
7028 +#define SSI_ERROR 2
7031 + unsigned int event;
7033 + unsigned int count;
7036 +int if_ssi_init(unsigned int port, unsigned int *channels_map);
7037 +int if_ssi_exit(void);
7039 +int if_ssi_start(int ch);
7040 +void if_ssi_stop(int ch);
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);
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);
7057 +void if_ssi_cancel_read(int ch);
7058 +void if_ssi_cancel_write(int ch);
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);
7067 if (md->usage == 0) {
7068 + int devmaj = MAJOR(disk_devt(md->disk));
7069 int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT;
7072 + devidx = md->disk->first_minor >> MMC_SHIFT;
7074 + blk_cleanup_queue(md->queue.queue);
7076 __clear_bit(devidx, dev_use);
7079 @@ -312,6 +319,15 @@ static int mmc_blk_issue_rq(struct mmc_q
7081 mmc_wait_for_req(card->host, &brq.mrq);
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);
7092 mmc_queue_bounce_post(mq);
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;
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
7110 err = mmc_blk_set_blksize(md, card);
7114 + mmc_cleanup_queue(&md->queue);
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);
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
7140 - printk(KERN_ERR "MMC: killing requests for dead queue\n");
7141 while ((req = elv_next_request(q)) != NULL) {
7143 + req->cmd_flags |= REQ_QUIET;
7144 ret = __blk_end_request(req, -EIO,
7145 blk_rq_cur_bytes(req));
7147 @@ -228,17 +228,18 @@ void mmc_cleanup_queue(struct mmc_queue
7148 struct request_queue *q = mq->queue;
7149 unsigned long flags;
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);
7156 /* Make sure the queue isn't suspended, as that will deadlock */
7157 mmc_queue_resume(mq);
7159 /* Then terminate our worker thread */
7160 kthread_stop(mq->thread);
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);
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;
7175 - blk_cleanup_queue(mq->queue);
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
7185 host->reqs_blocked += 1;
7187 - req->cmd->error = -EBADF;
7188 + req->cmd->error = -ENODEV;
7190 - req->data->error = -EBADF;
7191 + req->data->error = -ENODEV;
7192 enable_irq(host->irq);
7193 mmc_request_done(mmc, req);
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:
7202 +int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
7203 + u8 max_consecutive)
7205 + struct wl1251_acx_bet_enable *acx;
7208 + wl1251_debug(DEBUG_ACX, "acx bet enable");
7210 + acx = kzalloc(sizeof(*acx), GFP_KERNEL);
7216 + acx->enable = mode;
7217 + acx->max_consecutive = max_consecutive;
7219 + ret = wl1251_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
7221 + wl1251_warning("wl1251 acx bet enable failed: %d", ret);
7230 int wl1251_acx_ip_config(struct wl1251 *wl, bool enable, u8 *address,
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));
7241 struct wl1251_acx_wr_tbtt_and_dtim {
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));
7248 +enum wl1251_acx_bet_mode {
7249 + WL1251_ACX_BET_DISABLE = 0,
7250 + WL1251_ACX_BET_ENABLE = 1,
7253 +struct wl1251_acx_bet_enable {
7254 + struct acx_header header;
7257 + * Specifies if beacon early termination procedure is enabled or
7258 + * disabled, see enum wl1251_acx_bet_mode.
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.
7268 + u8 max_consecutive;
7271 +} __attribute__ ((packed));
7273 /*************************************************************************
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,
7280 +int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
7281 + u8 max_consecutive);
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;
7294 ret = wl1251_event_unmask(wl);
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
7300 static int wl1251_event_scan_complete(struct wl1251 *wl,
7301 struct event_mailbox *mbox)
7303 - wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d",
7304 - mbox->scheduled_scan_status,
7305 - mbox->scheduled_scan_channels);
7308 mutex_unlock(&wl->mutex);
7309 ieee80211_scan_completed(wl->hw);
7310 @@ -46,11 +42,36 @@ static int wl1251_event_scan_complete(st
7314 -static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
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)
7325 + wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status);
7327 + switch (mbox->ps_status) {
7328 + case ENTER_POWER_SAVE_FAIL:
7330 + wl->ps_entry_retry = 0;
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++;
7338 + wl1251_error("Power save entry failed, giving up");
7339 + wl->ps_entry_retry = 0;
7342 + case ENTER_POWER_SAVE_SUCCESS:
7344 + wl->ps_entry_retry = 0;
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
7356 - wl1251_event_mbox_dump(mbox);
7358 vector = mbox->events_vector & ~(mbox->events_mask);
7359 - wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector);
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
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);
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
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);
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);
7398 @@ -121,9 +151,6 @@ void wl1251_event_mbox_config(struct wl1
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);
7403 - wl1251_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
7404 - wl->mbox_ptr[0], wl->mbox_ptr[1]);
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;
7412 - wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
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,
7425 + ENTER_POWER_SAVE_FAIL = 0,
7426 + ENTER_POWER_SAVE_SUCCESS,
7427 + EXIT_POWER_SAVE_FAIL,
7428 + EXIT_POWER_SAVE_SUCCESS
7431 struct event_debug_report {
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 */
7442 + unsigned long last_event;
7444 /* Our association ID */
7446 @@ -381,6 +381,8 @@ struct wl1251 {
7447 /* PSM mode requested */
7450 + u8 ps_entry_retry;
7455 @@ -423,6 +425,8 @@ int wl1251_plt_stop(struct wl1251 *wl);
7457 #define WL1251_DEFAULT_CHANNEL 0
7459 +#define WL1251_DEFAULT_BET_CONSECUTIVE 10
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;
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;
7482 wl1251_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %s",
7483 @@ -1105,23 +1107,21 @@ static int wl1251_op_config_interface(st
7487 + if (!is_zero_ether_addr(conf->bssid))
7490 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
7492 - ret = wl1251_build_null_data(wl);
7496 + ret = wl1251_build_null_data(wl);
7501 wl->ssid_len = conf->ssid_len;
7503 memcpy(wl->ssid, conf->ssid, wl->ssid_len);
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);
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
7522 ret = wl1251_join(wl, wl->bss_type, wl->channel,
7523 wl->beacon_int, wl->dtim_period);
7525 @@ -1177,18 +1179,7 @@ static int wl1251_op_config(struct ieee8
7529 - if (channel != wl->channel) {
7530 - wl->channel = channel;
7532 - ret = wl1251_join(wl, wl->bss_type, wl->channel,
7533 - wl->beacon_int, wl->dtim_period);
7538 - ret = wl1251_build_null_data(wl);
7541 + wl->channel = channel;
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);
7552 wl->power_level = conf->power_level;
7554 @@ -1939,6 +1930,7 @@ static int __devinit wl1251_probe(struct
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
7569 + ret = wl1251_acx_bet_enable(wl, WL1251_ACX_BET_ENABLE,
7570 + WL1251_DEFAULT_BET_CONSECUTIVE);
7574 ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
7577 @@ -168,6 +173,12 @@ int wl1251_ps_set_mode(struct wl1251 *wl
7582 + ret = wl1251_acx_bet_enable(wl, WL1251_ACX_BET_DISABLE,
7583 + WL1251_DEFAULT_BET_CONSECUTIVE);
7587 /* disable beacon filtering */
7588 ret = wl1251_acx_beacon_filter_opt(wl, false);
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 {
7597 + struct rb_node rb_node;
7603 enum fsg_buffer_state state;
7604 @@ -694,6 +698,9 @@ struct fsg_dev {
7605 struct fsg_buffhd buffhds[NUM_BUFFERS];
7608 + /* Tree to find direct I/O's with overlapping sectors */
7609 + struct rb_root bio_tree;
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
7619 + * Find overlapped bio in fsg->bio_tree rb tree.
7621 +static int fsg_rbtree_find(struct fsg_dev *fsg, sector_t s,
7622 + unsigned int sectors)
7624 + struct rb_node *n;
7625 + struct fsg_buffhd *tmp;
7628 + spin_lock_irq(&fsg->lock);
7629 + n = fsg->bio_tree.rb_node;
7631 + tmp = rb_entry(n, struct fsg_buffhd, rb_node);
7632 + if (s + sectors <= tmp->sector)
7634 + else if (s >= tmp->sector + tmp->sectors)
7641 + spin_unlock_irq(&fsg->lock);
7646 + * Insert a node into the fsg->bio_tree rb tree.
7648 +static void fsg_rbtree_insert(struct fsg_dev *fsg, struct fsg_buffhd *node)
7650 + struct rb_node **p;
7651 + struct rb_node *parent = NULL;
7652 + struct fsg_buffhd *tmp;
7654 + spin_lock_irq(&fsg->lock);
7655 + p = &fsg->bio_tree.rb_node;
7659 + tmp = rb_entry(parent, struct fsg_buffhd, rb_node);
7660 + if (node->sector < tmp->sector)
7661 + p = &(*p)->rb_left;
7663 + p = &(*p)->rb_right;
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);
7670 /** UGLY UGLY HACK: Windows problems with multiple
7673 @@ -1721,7 +1780,8 @@ static void direct_read_end_io(struct bi
7674 * or b) more than one bio must be submitted
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)
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 *
7688 + char *p = bh->buf;
7693 @@ -1767,6 +1828,15 @@ static ssize_t direct_read(struct file *
7697 + while (fsg_rbtree_find(bh->fsg, bio->bi_sector,
7698 + bio_sectors(bio))) {
7699 + rc = sleep_thread(bh->fsg);
7706 submit_bio(READ, bio);
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;
7713 - nread = direct_read(curlun->filp, bh->buf,
7714 + nread = direct_read(curlun->filp, bh,
7715 amount, &file_offset_tmp);
7717 nread = vfs_read(curlun->filp,
7718 @@ -1920,6 +1990,7 @@ static void direct_write_end_io(struct b
7720 struct fsg_buffhd *bh = bio->bi_private;
7721 struct fsg_dev *fsg = bh->fsg;
7722 + unsigned long flags;
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);
7730 + /* FIXME: smp barriers are not necessary for this this driver */
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;
7737 - spin_unlock(&fsg->lock);
7738 + spin_unlock_irqrestore(&fsg->lock, flags);
7742 @@ -1949,6 +2022,7 @@ static ssize_t direct_write(struct file
7750 @@ -1987,6 +2061,16 @@ static ssize_t direct_write(struct file
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);
7763 + fsg_rbtree_insert(bh->fsg, bh);
7765 submit_bio(WRITE, bio);
7767 @@ -4456,6 +4540,7 @@ static int __init fsg_bind(struct usb_ga
7770 fsg->buffhds[fsg->num_buffers - 1].next = &fsg->buffhds[0];
7771 + fsg->bio_tree = RB_ROOT;
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 */
7782 + /* HACK: ULPI tends to get stuck when booting with
7783 + * the cable connected
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);
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
7800 struct musb *musb = container_of(data, struct musb, irq_work);
7801 static int old_state, old_ma, old_suspend;
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))
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));
7815 old_state = musb->xceiv->state;
7816 sysfs_notify(&musb->controller->kobj, NULL, "mode");
7818 @@ -2457,6 +2459,12 @@ bad_config:
7822 + /* Resets the controller. Has to be done. Without this, most likely
7823 + * the state machine inside the transceiver doesn't get fixed properly
7825 + musb_save_ctx_and_suspend(&musb->g, 0);
7826 + musb_restore_ctx_and_resume(&musb->g);
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 {
7836 irqreturn_t (*isr)(int, void *);
7837 struct work_struct irq_work;
7838 + struct work_struct vbus_work;
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
7847 static struct timer_list musb_idle_timer;
7849 +static void musb_vbus_work(struct work_struct *data)
7851 + struct musb *musb = container_of(data, struct musb, vbus_work);
7852 + u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
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));
7860 static void musb_do_idle(unsigned long _musb)
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;
7866 setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
7867 + INIT_WORK(&musb->vbus_work, musb_vbus_work);
7871 @@ -448,6 +460,9 @@ void musb_restore_ctx_and_resume(struct
7873 /* Restore register context */
7874 musb_restore_ctx(musb);
7876 + /* set constraints */
7877 + schedule_work(&musb->vbus_work);
7878 spin_unlock_irqrestore(&musb->lock, flags);
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
7885 /* The number of ports handled by the driver. (MAX:2) */
7886 #define SSI_MAX_PORTS 1
7888 +#define SSI_MAX_FRAME_SIZE 0x1f
7889 +#define SSI_MAX_RX_TIMEOUT 0x1ff
7890 +#define SSI_MAX_TX_DIVISOR 0x7f
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,
7903 @@ -52,6 +57,10 @@ enum {
7911 SSI_IOCTL_TX_CH_FULL,
7912 SSI_IOCTL_CH_DATAACCEPT,
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
7929 + * Part of the SSI character device driver.
7931 + * Copyright (C) 2009 Nokia Corporation. All rights reserved.
7933 + * Contact: Andras Domokos <andras.domokos@nokia.com>
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.
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.
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
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)
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)
7971 +#define SSI_MODE_SLEEP 0
7972 +#define SSI_MODE_STREAM 1
7973 +#define SSI_MODE_FRAME 2
7975 +#define SSI_ARBMODE_RR 0
7976 +#define SSI_ARBMODE_PRIO 1
7979 +#define WAKE_DOWN 1
7981 +struct ssi_tx_config {
7989 +struct ssi_rx_config {
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
8002 Enable configuration of fault-injection capabilities via debugfs.
8004 +config PANIC_INFO_BUFF
8005 + tristate "Buffer to be printed at panic"
8006 + depends on DEBUG_FS
8008 + Provide a small buffer which will be printed at panic.
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:
8020 +EXPORT_SYMBOL_GPL(follow_page);
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 */
8031 - /* Always read from the existing re-mapping */
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()'.
8043 spin_unlock(&sis->remap_lock);
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
8050 conn->mode = HCI_CM_ACTIVE;
8051 conn->state = BT_OPEN;
8052 + conn->auth_type = HCI_AT_GENERAL_BONDING;
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
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);
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)
8079 + struct ieee80211_local *local = sdata->local;
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
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);
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;
8098 + if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATED) {
8099 + printk(KERN_DEBUG "%s reports beacon loss when not "
8100 + "associated\n", sdata->dev->name);
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.
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) &&
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
8121 - if (time_after(jiffies, sta->last_rx + IEEE80211_PROBE_IDLE_TIME)) {
8122 - ifsta->flags |= IEEE80211_STA_PROBEREQ_POLL;
8123 - send_probe = true;
8129 @@ -1148,7 +1151,7 @@ static void ieee80211_associated(struct
8131 ieee80211_set_disassoc(sdata, ifsta, true, true,
8132 WLAN_REASON_PREV_AUTH_NOT_VALID);
8134 + else if (!(local->hw.flags & IEEE80211_HW_BEACON_FILTER))
8135 mod_timer(&ifsta->timer, jiffies +
8136 IEEE80211_MONITORING_INTERVAL);
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;
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");
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);
8163 - printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), "
8164 + printk(KERN_DEBUG "\t(%d KHz - %d KHz @ %d KHz), "
8166 freq_range->start_freq_khz,
8167 freq_range->end_freq_khz,
8168 @@ -669,15 +669,15 @@ static void print_regdomain(const struct
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");
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");
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]);
8187 @@ -686,7 +686,7 @@ static void print_regdomain(const struct
8189 void print_regdomain_info(const struct ieee80211_regdomain *rd)
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]);
8196 @@ -805,7 +805,7 @@ int regulatory_init(void)
8197 #ifdef CONFIG_WIRELESS_OLD_REGULATORY
8198 cfg80211_regdomain = static_regdom(ieee80211_regdom);
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
8210 #define AIC3X_VERSION "0.2"
8212 +static int hp_dac_lim = 9;
8213 +module_param(hp_dac_lim, int, 0);
8215 /* codec private data */
8217 unsigned int sysclk;
8218 @@ -294,6 +297,40 @@ static DECLARE_TLV_DB_SCALE(hpout_tlv, 0
8220 static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1);
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} }
8235 +static int tlv320alc3x_info_volsw(struct snd_kcontrol *kcontrol,
8236 + struct snd_ctl_elem_info *uinfo)
8238 + struct soc_mixer_control *mc =
8239 + (struct soc_mixer_control *)kcontrol->private_value;
8240 + int max = mc->max;
8242 + if (hp_dac_lim != max && hp_dac_lim >= 2 && hp_dac_lim <= 9)
8246 + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
8248 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
8251 + uinfo->value.integer.min = 0;
8252 + uinfo->value.integer.max = max;
8256 static const struct snd_kcontrol_new aic3x_snd_controls[] = {
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,
8263 - SOC_DOUBLE_R_TLV("HP DAC Output Volume", HPLOUT_CTRL, HPROUT_CTRL, 4,
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,
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 */
8288 +static int hp_lim = 63;
8289 +module_param(hp_lim, int, 0);
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)
8298 + int ext_api = (kcontrol->private_value >> 26) & 0x0f;
8299 int max = (kcontrol->private_value >> 16) & 0xff;
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);
8309 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;