Skip to content

Commit

Permalink
PWM beeper forcing PWM to inactive statr
Browse files Browse the repository at this point in the history
When disabling, some PWM hardware IP leaves the pin in the state it
happens to be in at that very moment. To make sure it is in the
inactive state, the duty cycle is now set to 0 first, before PWM is
being disabled.

Solves: EMP-628
  • Loading branch information
Robert Delien authored and raysiudak committed Apr 1, 2019
1 parent 9d3942c commit eaace6d
Showing 1 changed file with 11 additions and 0 deletions.
11 changes: 11 additions & 0 deletions drivers/input/misc/pwm-beeper.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,22 @@ static int pwm_beeper_on(struct pwm_beeper *beeper, unsigned long period)

static void pwm_beeper_off(struct pwm_beeper *beeper)
{
struct pwm_state state;

if (beeper->amplifier_on) {
regulator_disable(beeper->amplifier);
beeper->amplifier_on = false;
}

/*
* When disabling, some PWM hardware IP leaves the pin in the state it
* happens to be in. To make sure it is in the inactive state, set the
* duty cycle to 0 first.
*/
pwm_get_state(beeper->pwm, &state);
state.duty_cycle = 0;
pwm_apply_state(beeper->pwm, &state);

pwm_disable(beeper->pwm);
}

Expand Down

2 comments on commit eaace6d

@oliv3r
Copy link

@oliv3r oliv3r commented on eaace6d Apr 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is rather a nasty hack (as what you call 0 may be something else for other devices), in any case, the proper fix (whether it still works is of course unknown) was here:
f4c8526

@oliv3r
Copy link

@oliv3r oliv3r commented on eaace6d Apr 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nono, the bug is in the actual hardware and the use of the hardware. The current behavior of the driver is 'disable all clocks first', at which point the PWM periphieral which just stop at whatever it was doing. E.g. it will not finish its course. What f4c8526 does, is let the peripherial runs its course as being told; and then disable the clocks. Granted the f4c8526 may be an older version, as I recall removing the locking/unlocking bit at some point.

So while you are right that the true idle state is not defined, and this should be resolved; you are still making the peripheral stop without having finished its internal state machine! So for that, you are hacking around it.

Please sign in to comment.