int pwm_apply_state()

in core.c [556:649]


int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
{
	struct pwm_chip *chip;
	int err;

	/*
	 * Some lowlevel driver's implementations of .apply() make use of
	 * mutexes, also with some drivers only returning when the new
	 * configuration is active calling pwm_apply_state() from atomic context
	 * is a bad idea. So make it explicit that calling this function might
	 * sleep.
	 */
	might_sleep();

	if (!pwm || !state || !state->period ||
	    state->duty_cycle > state->period)
		return -EINVAL;

	chip = pwm->chip;

	if (state->period == pwm->state.period &&
	    state->duty_cycle == pwm->state.duty_cycle &&
	    state->polarity == pwm->state.polarity &&
	    state->enabled == pwm->state.enabled &&
	    state->usage_power == pwm->state.usage_power)
		return 0;

	if (chip->ops->apply) {
		err = chip->ops->apply(chip, pwm, state);
		if (err)
			return err;

		trace_pwm_apply(pwm, state);

		pwm->state = *state;

		/*
		 * only do this after pwm->state was applied as some
		 * implementations of .get_state depend on this
		 */
		pwm_apply_state_debug(pwm, state);
	} else {
		/*
		 * FIXME: restore the initial state in case of error.
		 */
		if (state->polarity != pwm->state.polarity) {
			if (!chip->ops->set_polarity)
				return -EINVAL;

			/*
			 * Changing the polarity of a running PWM is
			 * only allowed when the PWM driver implements
			 * ->apply().
			 */
			if (pwm->state.enabled) {
				chip->ops->disable(chip, pwm);
				pwm->state.enabled = false;
			}

			err = chip->ops->set_polarity(chip, pwm,
						      state->polarity);
			if (err)
				return err;

			pwm->state.polarity = state->polarity;
		}

		if (state->period != pwm->state.period ||
		    state->duty_cycle != pwm->state.duty_cycle) {
			err = chip->ops->config(pwm->chip, pwm,
						state->duty_cycle,
						state->period);
			if (err)
				return err;

			pwm->state.duty_cycle = state->duty_cycle;
			pwm->state.period = state->period;
		}

		if (state->enabled != pwm->state.enabled) {
			if (state->enabled) {
				err = chip->ops->enable(chip, pwm);
				if (err)
					return err;
			} else {
				chip->ops->disable(chip, pwm);
			}

			pwm->state.enabled = state->enabled;
		}
	}

	return 0;
}