BACKPORT: FROMLIST: pwm: Add support for different PWM output types
Normally, PWM channels have fixed output until software requests to change their settings. There are some PWM devices whose outputs can be changed autonomously according to a predefined pattern programmed in hardware. Add support for such devices by adding a new pwm_output_type enum type to identify these two different PWM types and adding helper functions to read the PWM output type supported by a PWM. Bug: 140290585 Link: https://lore.kernel.org/lkml/1568415464-20267-1-git-send-email-gurus@codeaurora.org/ Change-Id: Ie8d61975057c51258e5bde9451ce96be4acdf98b Signed-off-by: Fenglin Wu <fenglinw@codeaurora.org> [gurus@codeaurora.org: removed output_pattern, changed output_type sysfs param to read-only, reworded commit message] Signed-off-by: Guru Das Srinagesh <gurus@codeaurora.org>
This commit is contained in:
parent
4233dfd7c0
commit
106a4b85e0
@ -282,6 +282,7 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip,
|
||||
pwm->pwm = chip->base + i;
|
||||
pwm->hwpwm = i;
|
||||
pwm->state.polarity = polarity;
|
||||
pwm->state.output_type = PWM_OUTPUT_FIXED;
|
||||
|
||||
if (chip->ops->get_state)
|
||||
chip->ops->get_state(chip, pwm, &pwm->state);
|
||||
|
@ -215,11 +215,35 @@ static ssize_t capture_show(struct device *child,
|
||||
return sprintf(buf, "%u %u\n", result.period, result.duty_cycle);
|
||||
}
|
||||
|
||||
static ssize_t output_type_show(struct device *child,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
const struct pwm_device *pwm = child_to_pwm_device(child);
|
||||
const char *output_type = "unknown";
|
||||
struct pwm_state state;
|
||||
|
||||
pwm_get_state(pwm, &state);
|
||||
switch (state.output_type) {
|
||||
case PWM_OUTPUT_FIXED:
|
||||
output_type = "fixed";
|
||||
break;
|
||||
case PWM_OUTPUT_MODULATED:
|
||||
output_type = "modulated";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", output_type);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(period);
|
||||
static DEVICE_ATTR_RW(duty_cycle);
|
||||
static DEVICE_ATTR_RW(enable);
|
||||
static DEVICE_ATTR_RW(polarity);
|
||||
static DEVICE_ATTR_RO(capture);
|
||||
static DEVICE_ATTR_RO(output_type);
|
||||
|
||||
static struct attribute *pwm_attrs[] = {
|
||||
&dev_attr_period.attr,
|
||||
@ -227,6 +251,7 @@ static struct attribute *pwm_attrs[] = {
|
||||
&dev_attr_enable.attr,
|
||||
&dev_attr_polarity.attr,
|
||||
&dev_attr_capture.attr,
|
||||
&dev_attr_output_type.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(pwm);
|
||||
|
@ -48,6 +48,17 @@ enum {
|
||||
PWMF_EXPORTED = 1 << 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum pwm_output_type - output type of the PWM signal
|
||||
* @PWM_OUTPUT_FIXED: PWM output is fixed until a change request
|
||||
* @PWM_OUTPUT_MODULATED: PWM output is modulated in hardware
|
||||
* autonomously with a predefined pattern
|
||||
*/
|
||||
enum pwm_output_type {
|
||||
PWM_OUTPUT_FIXED = 1 << 0,
|
||||
PWM_OUTPUT_MODULATED = 1 << 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct pwm_state - state of a PWM channel
|
||||
* @period: PWM period (in nanoseconds)
|
||||
@ -59,6 +70,7 @@ struct pwm_state {
|
||||
unsigned int period;
|
||||
unsigned int duty_cycle;
|
||||
enum pwm_polarity polarity;
|
||||
enum pwm_output_type output_type;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
@ -144,6 +156,16 @@ static inline enum pwm_polarity pwm_get_polarity(const struct pwm_device *pwm)
|
||||
return state.polarity;
|
||||
}
|
||||
|
||||
static inline enum pwm_output_type pwm_get_output_type(
|
||||
const struct pwm_device *pwm)
|
||||
{
|
||||
struct pwm_state state;
|
||||
|
||||
pwm_get_state(pwm, &state);
|
||||
|
||||
return state.output_type;
|
||||
}
|
||||
|
||||
static inline void pwm_get_args(const struct pwm_device *pwm,
|
||||
struct pwm_args *args)
|
||||
{
|
||||
@ -250,6 +272,7 @@ pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle,
|
||||
* @get_state: get the current PWM state. This function is only
|
||||
* called once per PWM device when the PWM chip is
|
||||
* registered.
|
||||
* @get_output_type_supported: get the supported output type of this PWM
|
||||
* @owner: helps prevent removal of modules exporting active PWMs
|
||||
* @config: configure duty cycles and period length for this PWM
|
||||
* @set_polarity: configure the polarity of this PWM
|
||||
@ -265,6 +288,8 @@ struct pwm_ops {
|
||||
const struct pwm_state *state);
|
||||
void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
struct pwm_state *state);
|
||||
int (*get_output_type_supported)(struct pwm_chip *chip,
|
||||
struct pwm_device *pwm);
|
||||
struct module *owner;
|
||||
|
||||
/* Only used by legacy drivers */
|
||||
@ -319,6 +344,24 @@ void pwm_free(struct pwm_device *pwm);
|
||||
int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state);
|
||||
int pwm_adjust_config(struct pwm_device *pwm);
|
||||
|
||||
/**
|
||||
* pwm_get_output_type_supported() - obtain output type of a PWM device.
|
||||
* @pwm: PWM device
|
||||
*
|
||||
* Returns: output type supported by the PWM device
|
||||
*/
|
||||
static inline int pwm_get_output_type_supported(struct pwm_device *pwm)
|
||||
{
|
||||
if (!pwm)
|
||||
return -EINVAL;
|
||||
|
||||
if (pwm->chip->ops->get_output_type_supported)
|
||||
return pwm->chip->ops->get_output_type_supported(pwm->chip,
|
||||
pwm);
|
||||
|
||||
return PWM_OUTPUT_FIXED;
|
||||
}
|
||||
|
||||
/**
|
||||
* pwm_config() - change a PWM device configuration
|
||||
* @pwm: PWM device
|
||||
@ -437,6 +480,11 @@ static inline int pwm_adjust_config(struct pwm_device *pwm)
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline int pwm_get_output_type_supported(struct pwm_device *pwm)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
|
||||
int period_ns)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user