diff options
Diffstat (limited to 'drivers/input/ff-memless.c')
-rw-r--r-- | drivers/input/ff-memless.c | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index b483b2995fa9..1d881c96ba8f 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #define debug(format, arg...) pr_debug("ff-memless: " format "\n", ## arg) | 26 | #define debug(format, arg...) pr_debug("ff-memless: " format "\n", ## arg) |
27 | 27 | ||
28 | #include <linux/slab.h> | ||
28 | #include <linux/input.h> | 29 | #include <linux/input.h> |
29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
30 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
@@ -221,11 +222,27 @@ static int get_compatible_type(struct ff_device *ff, int effect_type) | |||
221 | } | 222 | } |
222 | 223 | ||
223 | /* | 224 | /* |
225 | * Only left/right direction should be used (under/over 0x8000) for | ||
226 | * forward/reverse motor direction (to keep calculation fast & simple). | ||
227 | */ | ||
228 | static u16 ml_calculate_direction(u16 direction, u16 force, | ||
229 | u16 new_direction, u16 new_force) | ||
230 | { | ||
231 | if (!force) | ||
232 | return new_direction; | ||
233 | if (!new_force) | ||
234 | return direction; | ||
235 | return (((u32)(direction >> 1) * force + | ||
236 | (new_direction >> 1) * new_force) / | ||
237 | (force + new_force)) << 1; | ||
238 | } | ||
239 | |||
240 | /* | ||
224 | * Combine two effects and apply gain. | 241 | * Combine two effects and apply gain. |
225 | */ | 242 | */ |
226 | static void ml_combine_effects(struct ff_effect *effect, | 243 | static void ml_combine_effects(struct ff_effect *effect, |
227 | struct ml_effect_state *state, | 244 | struct ml_effect_state *state, |
228 | unsigned int gain) | 245 | int gain) |
229 | { | 246 | { |
230 | struct ff_effect *new = state->effect; | 247 | struct ff_effect *new = state->effect; |
231 | unsigned int strong, weak, i; | 248 | unsigned int strong, weak, i; |
@@ -252,8 +269,21 @@ static void ml_combine_effects(struct ff_effect *effect, | |||
252 | break; | 269 | break; |
253 | 270 | ||
254 | case FF_RUMBLE: | 271 | case FF_RUMBLE: |
255 | strong = new->u.rumble.strong_magnitude * gain / 0xffff; | 272 | strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff; |
256 | weak = new->u.rumble.weak_magnitude * gain / 0xffff; | 273 | weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff; |
274 | |||
275 | if (effect->u.rumble.strong_magnitude + strong) | ||
276 | effect->direction = ml_calculate_direction( | ||
277 | effect->direction, | ||
278 | effect->u.rumble.strong_magnitude, | ||
279 | new->direction, strong); | ||
280 | else if (effect->u.rumble.weak_magnitude + weak) | ||
281 | effect->direction = ml_calculate_direction( | ||
282 | effect->direction, | ||
283 | effect->u.rumble.weak_magnitude, | ||
284 | new->direction, weak); | ||
285 | else | ||
286 | effect->direction = 0; | ||
257 | effect->u.rumble.strong_magnitude = | 287 | effect->u.rumble.strong_magnitude = |
258 | min(strong + effect->u.rumble.strong_magnitude, | 288 | min(strong + effect->u.rumble.strong_magnitude, |
259 | 0xffffU); | 289 | 0xffffU); |
@@ -268,6 +298,13 @@ static void ml_combine_effects(struct ff_effect *effect, | |||
268 | /* here we also scale it 0x7fff => 0xffff */ | 298 | /* here we also scale it 0x7fff => 0xffff */ |
269 | i = i * gain / 0x7fff; | 299 | i = i * gain / 0x7fff; |
270 | 300 | ||
301 | if (effect->u.rumble.strong_magnitude + i) | ||
302 | effect->direction = ml_calculate_direction( | ||
303 | effect->direction, | ||
304 | effect->u.rumble.strong_magnitude, | ||
305 | new->direction, i); | ||
306 | else | ||
307 | effect->direction = 0; | ||
271 | effect->u.rumble.strong_magnitude = | 308 | effect->u.rumble.strong_magnitude = |
272 | min(i + effect->u.rumble.strong_magnitude, 0xffffU); | 309 | min(i + effect->u.rumble.strong_magnitude, 0xffffU); |
273 | effect->u.rumble.weak_magnitude = | 310 | effect->u.rumble.weak_magnitude = |
@@ -411,8 +448,6 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) | |||
411 | msecs_to_jiffies(state->effect->replay.length); | 448 | msecs_to_jiffies(state->effect->replay.length); |
412 | state->adj_at = state->play_at; | 449 | state->adj_at = state->play_at; |
413 | 450 | ||
414 | ml_schedule_timer(ml); | ||
415 | |||
416 | } else { | 451 | } else { |
417 | debug("initiated stop"); | 452 | debug("initiated stop"); |
418 | 453 | ||
@@ -420,10 +455,10 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) | |||
420 | __set_bit(FF_EFFECT_ABORTING, &state->flags); | 455 | __set_bit(FF_EFFECT_ABORTING, &state->flags); |
421 | else | 456 | else |
422 | __clear_bit(FF_EFFECT_STARTED, &state->flags); | 457 | __clear_bit(FF_EFFECT_STARTED, &state->flags); |
423 | |||
424 | ml_play_effects(ml); | ||
425 | } | 458 | } |
426 | 459 | ||
460 | ml_play_effects(ml); | ||
461 | |||
427 | return 0; | 462 | return 0; |
428 | } | 463 | } |
429 | 464 | ||