Lines Matching +full:feedback +full:- +full:loop
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Force feedback support for memoryless devices
19 #include <linux/fixp-arith.h>
23 MODULE_DESCRIPTION("Force feedback support for memoryless devices");
38 int count; /* loop count of the effect */
59 switch (effect->type) { in get_envelope()
61 return &effect->u.periodic.envelope; in get_envelope()
64 return &effect->u.constant.envelope; in get_envelope()
76 const struct ff_envelope *envelope = get_envelope(state->effect); in calculate_next_time()
79 if (envelope->attack_length) { in calculate_next_time()
80 attack_stop = state->play_at + in calculate_next_time()
81 msecs_to_jiffies(envelope->attack_length); in calculate_next_time()
82 if (time_before(state->adj_at, attack_stop)) in calculate_next_time()
83 return state->adj_at + in calculate_next_time()
87 if (state->effect->replay.length) { in calculate_next_time()
88 if (envelope->fade_length) { in calculate_next_time()
90 fade_start = state->stop_at - in calculate_next_time()
91 msecs_to_jiffies(envelope->fade_length); in calculate_next_time()
93 if (time_before(state->adj_at, fade_start)) in calculate_next_time()
97 next_fade = state->adj_at + in calculate_next_time()
99 if (time_before(next_fade, state->stop_at)) in calculate_next_time()
103 return state->stop_at; in calculate_next_time()
106 return state->play_at; in calculate_next_time()
122 state = &ml->states[i]; in ml_schedule_timer()
124 if (!test_bit(FF_EFFECT_STARTED, &state->flags)) in ml_schedule_timer()
127 if (test_bit(FF_EFFECT_PLAYING, &state->flags)) in ml_schedule_timer()
130 next_at = state->play_at; in ml_schedule_timer()
139 timer_delete(&ml->timer); in ml_schedule_timer()
142 mod_timer(&ml->timer, earliest); in ml_schedule_timer()
152 struct ff_effect *effect = state->effect; in apply_envelope()
159 if (envelope->attack_length && in apply_envelope()
161 state->play_at + msecs_to_jiffies(envelope->attack_length))) { in apply_envelope()
163 value, envelope->attack_level); in apply_envelope()
164 time_from_level = jiffies_to_msecs(now - state->play_at); in apply_envelope()
165 time_of_envelope = envelope->attack_length; in apply_envelope()
166 envelope_level = min_t(u16, envelope->attack_level, 0x7fff); in apply_envelope()
168 } else if (envelope->fade_length && effect->replay.length && in apply_envelope()
170 state->stop_at - msecs_to_jiffies(envelope->fade_length)) && in apply_envelope()
171 time_before(now, state->stop_at)) { in apply_envelope()
172 time_from_level = jiffies_to_msecs(state->stop_at - now); in apply_envelope()
173 time_of_envelope = envelope->fade_length; in apply_envelope()
174 envelope_level = min_t(u16, envelope->fade_level, 0x7fff); in apply_envelope()
178 difference = abs(value) - envelope_level; in apply_envelope()
189 -(difference + envelope_level) : (difference + envelope_level); in apply_envelope()
198 if (test_bit(effect_type, ff->ffbit)) in get_compatible_type()
201 if (effect_type == FF_PERIODIC && test_bit(FF_RUMBLE, ff->ffbit)) in get_compatible_type()
228 return ((s32)a) >> (16 - FRAC_N); in fixp_new16()
244 struct ff_effect *new = state->effect; in ml_combine_effects()
249 switch (new->type) { in ml_combine_effects()
251 i = new->direction * 360 / 0xffff; in ml_combine_effects()
253 new->u.constant.level, in ml_combine_effects()
254 &new->u.constant.envelope)); in ml_combine_effects()
256 y = fixp_mult(-fixp_cos16(i), level) * gain / 0xffff; in ml_combine_effects()
262 effect->u.ramp.start_level = in ml_combine_effects()
263 clamp_val(effect->u.ramp.start_level + x, -0x80, 0x7f); in ml_combine_effects()
264 effect->u.ramp.end_level = in ml_combine_effects()
265 clamp_val(effect->u.ramp.end_level + y, -0x80, 0x7f); in ml_combine_effects()
269 strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff; in ml_combine_effects()
270 weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff; in ml_combine_effects()
272 if (effect->u.rumble.strong_magnitude + strong) in ml_combine_effects()
273 effect->direction = ml_calculate_direction( in ml_combine_effects()
274 effect->direction, in ml_combine_effects()
275 effect->u.rumble.strong_magnitude, in ml_combine_effects()
276 new->direction, strong); in ml_combine_effects()
277 else if (effect->u.rumble.weak_magnitude + weak) in ml_combine_effects()
278 effect->direction = ml_calculate_direction( in ml_combine_effects()
279 effect->direction, in ml_combine_effects()
280 effect->u.rumble.weak_magnitude, in ml_combine_effects()
281 new->direction, weak); in ml_combine_effects()
283 effect->direction = 0; in ml_combine_effects()
284 effect->u.rumble.strong_magnitude = in ml_combine_effects()
285 min(strong + effect->u.rumble.strong_magnitude, in ml_combine_effects()
287 effect->u.rumble.weak_magnitude = in ml_combine_effects()
288 min(weak + effect->u.rumble.weak_magnitude, 0xffffU); in ml_combine_effects()
292 i = apply_envelope(state, abs(new->u.periodic.magnitude), in ml_combine_effects()
293 &new->u.periodic.envelope); in ml_combine_effects()
298 if (effect->u.rumble.strong_magnitude + i) in ml_combine_effects()
299 effect->direction = ml_calculate_direction( in ml_combine_effects()
300 effect->direction, in ml_combine_effects()
301 effect->u.rumble.strong_magnitude, in ml_combine_effects()
302 new->direction, i); in ml_combine_effects()
304 effect->direction = 0; in ml_combine_effects()
305 effect->u.rumble.strong_magnitude = in ml_combine_effects()
306 min(i + effect->u.rumble.strong_magnitude, 0xffffU); in ml_combine_effects()
307 effect->u.rumble.weak_magnitude = in ml_combine_effects()
308 min(i + effect->u.rumble.weak_magnitude, 0xffffU); in ml_combine_effects()
338 state = &ml->states[i]; in ml_get_combo_effect()
339 effect = state->effect; in ml_get_combo_effect()
341 if (!test_bit(FF_EFFECT_STARTED, &state->flags)) in ml_get_combo_effect()
344 if (time_before(jiffies, state->play_at)) in ml_get_combo_effect()
352 effect_type = get_compatible_type(ml->dev->ff, effect->type); in ml_get_combo_effect()
353 if (combo_effect->type != effect_type) { in ml_get_combo_effect()
354 if (combo_effect->type != 0) { in ml_get_combo_effect()
358 combo_effect->type = effect_type; in ml_get_combo_effect()
361 if (__test_and_clear_bit(FF_EFFECT_ABORTING, &state->flags)) { in ml_get_combo_effect()
362 __clear_bit(FF_EFFECT_PLAYING, &state->flags); in ml_get_combo_effect()
363 __clear_bit(FF_EFFECT_STARTED, &state->flags); in ml_get_combo_effect()
364 } else if (effect->replay.length && in ml_get_combo_effect()
365 time_after_eq(jiffies, state->stop_at)) { in ml_get_combo_effect()
367 __clear_bit(FF_EFFECT_PLAYING, &state->flags); in ml_get_combo_effect()
369 if (--state->count <= 0) { in ml_get_combo_effect()
370 __clear_bit(FF_EFFECT_STARTED, &state->flags); in ml_get_combo_effect()
372 state->play_at = jiffies + in ml_get_combo_effect()
373 msecs_to_jiffies(effect->replay.delay); in ml_get_combo_effect()
374 state->stop_at = state->play_at + in ml_get_combo_effect()
375 msecs_to_jiffies(effect->replay.length); in ml_get_combo_effect()
378 __set_bit(FF_EFFECT_PLAYING, &state->flags); in ml_get_combo_effect()
379 state->adj_at = jiffies; in ml_get_combo_effect()
380 ml_combine_effects(combo_effect, state, ml->gain); in ml_get_combo_effect()
384 return combo_effect->type != 0; in ml_get_combo_effect()
395 ml->play_effect(ml->dev, ml->private, &effect); in ml_play_effects()
403 struct input_dev *dev = ml->dev; in ml_effect_timer()
407 guard(spinlock_irqsave)(&dev->event_lock); in ml_effect_timer()
412 * Sets requested gain for FF effects. Called with dev->event_lock held.
416 struct ml_device *ml = dev->ff->private; in ml_ff_set_gain()
419 ml->gain = gain; in ml_ff_set_gain()
422 __clear_bit(FF_EFFECT_PLAYING, &ml->states[i].flags); in ml_ff_set_gain()
428 * Start/stop specified FF effect. Called with dev->event_lock held.
432 struct ml_device *ml = dev->ff->private; in ml_ff_playback()
433 struct ml_effect_state *state = &ml->states[effect_id]; in ml_ff_playback()
438 __set_bit(FF_EFFECT_STARTED, &state->flags); in ml_ff_playback()
439 state->count = value; in ml_ff_playback()
440 state->play_at = jiffies + in ml_ff_playback()
441 msecs_to_jiffies(state->effect->replay.delay); in ml_ff_playback()
442 state->stop_at = state->play_at + in ml_ff_playback()
443 msecs_to_jiffies(state->effect->replay.length); in ml_ff_playback()
444 state->adj_at = state->play_at; in ml_ff_playback()
449 if (test_bit(FF_EFFECT_PLAYING, &state->flags)) in ml_ff_playback()
450 __set_bit(FF_EFFECT_ABORTING, &state->flags); in ml_ff_playback()
452 __clear_bit(FF_EFFECT_STARTED, &state->flags); in ml_ff_playback()
463 struct ml_device *ml = dev->ff->private; in ml_ff_upload()
464 struct ml_effect_state *state = &ml->states[effect->id]; in ml_ff_upload()
466 guard(spinlock_irq)(&dev->event_lock); in ml_ff_upload()
468 if (test_bit(FF_EFFECT_STARTED, &state->flags)) { in ml_ff_upload()
469 __clear_bit(FF_EFFECT_PLAYING, &state->flags); in ml_ff_upload()
470 state->play_at = jiffies + in ml_ff_upload()
471 msecs_to_jiffies(state->effect->replay.delay); in ml_ff_upload()
472 state->stop_at = state->play_at + in ml_ff_upload()
473 msecs_to_jiffies(state->effect->replay.length); in ml_ff_upload()
474 state->adj_at = state->play_at; in ml_ff_upload()
483 struct ml_device *ml = ff->private; in ml_ff_destroy()
492 timer_delete_sync(&ml->timer); in ml_ff_destroy()
494 kfree(ml->private); in ml_ff_destroy()
498 * input_ff_create_memless() - create memoryless force-feedback device
499 * @dev: input device supporting force-feedback
500 * @data: driver-specific data to be passed into @play_effect
501 * @play_effect: driver-specific method for playing FF effect
512 return -ENOMEM; in input_ff_create_memless()
514 ml->dev = dev; in input_ff_create_memless()
515 ml->private = data; in input_ff_create_memless()
516 ml->play_effect = play_effect; in input_ff_create_memless()
517 ml->gain = 0xffff; in input_ff_create_memless()
518 timer_setup(&ml->timer, ml_effect_timer, 0); in input_ff_create_memless()
520 set_bit(FF_GAIN, dev->ffbit); in input_ff_create_memless()
526 ff = dev->ff; in input_ff_create_memless()
527 ff->upload = ml_ff_upload; in input_ff_create_memless()
528 ff->playback = ml_ff_playback; in input_ff_create_memless()
529 ff->set_gain = ml_ff_set_gain; in input_ff_create_memless()
530 ff->destroy = ml_ff_destroy; in input_ff_create_memless()
533 if (test_bit(FF_RUMBLE, ff->ffbit)) { in input_ff_create_memless()
534 set_bit(FF_PERIODIC, dev->ffbit); in input_ff_create_memless()
535 set_bit(FF_SINE, dev->ffbit); in input_ff_create_memless()
536 set_bit(FF_TRIANGLE, dev->ffbit); in input_ff_create_memless()
537 set_bit(FF_SQUARE, dev->ffbit); in input_ff_create_memless()
541 ml->states[i].effect = &ff->effects[i]; in input_ff_create_memless()
543 ff->private = no_free_ptr(ml); in input_ff_create_memless()