pwm: mtk-disp: Implement atomic API .apply()
Switch the driver to support the .apply() method. Signed-off-by: Jitao Shi <jitao.shi@mediatek.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
This commit is contained in:
parent
d7a4e58258
commit
888a623db5
1 changed files with 41 additions and 54 deletions
|
@ -47,6 +47,7 @@ struct mtk_disp_pwm {
|
||||||
struct clk *clk_main;
|
struct clk *clk_main;
|
||||||
struct clk *clk_mm;
|
struct clk *clk_mm;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
bool enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct mtk_disp_pwm *to_mtk_disp_pwm(struct pwm_chip *chip)
|
static inline struct mtk_disp_pwm *to_mtk_disp_pwm(struct pwm_chip *chip)
|
||||||
|
@ -66,26 +67,46 @@ static void mtk_disp_pwm_update_bits(struct mtk_disp_pwm *mdp, u32 offset,
|
||||||
writel(value, address);
|
writel(value, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||||
int duty_ns, int period_ns)
|
const struct pwm_state *state)
|
||||||
{
|
{
|
||||||
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
|
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
|
||||||
u32 clk_div, period, high_width, value;
|
u32 clk_div, period, high_width, value;
|
||||||
u64 div, rate;
|
u64 div, rate;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (state->polarity != PWM_POLARITY_NORMAL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!state->enabled) {
|
||||||
|
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
|
||||||
|
0x0);
|
||||||
|
|
||||||
|
if (mdp->enabled) {
|
||||||
|
clk_disable_unprepare(mdp->clk_mm);
|
||||||
|
clk_disable_unprepare(mdp->clk_main);
|
||||||
|
}
|
||||||
|
|
||||||
|
mdp->enabled = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mdp->enabled) {
|
||||||
err = clk_prepare_enable(mdp->clk_main);
|
err = clk_prepare_enable(mdp->clk_main);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err));
|
dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n",
|
||||||
|
ERR_PTR(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = clk_prepare_enable(mdp->clk_mm);
|
err = clk_prepare_enable(mdp->clk_mm);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err));
|
dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n",
|
||||||
|
ERR_PTR(err));
|
||||||
clk_disable_unprepare(mdp->clk_main);
|
clk_disable_unprepare(mdp->clk_main);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find period, high_width and clk_div to suit duty_ns and period_ns.
|
* Find period, high_width and clk_div to suit duty_ns and period_ns.
|
||||||
|
@ -98,20 +119,22 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||||
* high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1))
|
* high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1))
|
||||||
*/
|
*/
|
||||||
rate = clk_get_rate(mdp->clk_main);
|
rate = clk_get_rate(mdp->clk_main);
|
||||||
clk_div = div_u64(rate * period_ns, NSEC_PER_SEC) >>
|
clk_div = div_u64(rate * state->period, NSEC_PER_SEC) >>
|
||||||
PWM_PERIOD_BIT_WIDTH;
|
PWM_PERIOD_BIT_WIDTH;
|
||||||
if (clk_div > PWM_CLKDIV_MAX) {
|
if (clk_div > PWM_CLKDIV_MAX) {
|
||||||
|
if (!mdp->enabled) {
|
||||||
clk_disable_unprepare(mdp->clk_mm);
|
clk_disable_unprepare(mdp->clk_mm);
|
||||||
clk_disable_unprepare(mdp->clk_main);
|
clk_disable_unprepare(mdp->clk_main);
|
||||||
|
}
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
div = NSEC_PER_SEC * (clk_div + 1);
|
div = NSEC_PER_SEC * (clk_div + 1);
|
||||||
period = div64_u64(rate * period_ns, div);
|
period = div64_u64(rate * state->period, div);
|
||||||
if (period > 0)
|
if (period > 0)
|
||||||
period--;
|
period--;
|
||||||
|
|
||||||
high_width = div64_u64(rate * duty_ns, div);
|
high_width = div64_u64(rate * state->duty_cycle, div);
|
||||||
value = period | (high_width << PWM_HIGH_WIDTH_SHIFT);
|
value = period | (high_width << PWM_HIGH_WIDTH_SHIFT);
|
||||||
|
|
||||||
mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
|
mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
|
||||||
|
@ -141,51 +164,15 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||||
mdp->data->con0_sel);
|
mdp->data->con0_sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
clk_disable_unprepare(mdp->clk_mm);
|
|
||||||
clk_disable_unprepare(mdp->clk_main);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
|
|
||||||
{
|
|
||||||
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = clk_prepare_enable(mdp->clk_main);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = clk_prepare_enable(mdp->clk_mm);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err));
|
|
||||||
clk_disable_unprepare(mdp->clk_main);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
|
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
|
||||||
mdp->data->enable_mask);
|
mdp->data->enable_mask);
|
||||||
|
mdp->enabled = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
|
||||||
{
|
|
||||||
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
|
|
||||||
|
|
||||||
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
|
|
||||||
0x0);
|
|
||||||
|
|
||||||
clk_disable_unprepare(mdp->clk_mm);
|
|
||||||
clk_disable_unprepare(mdp->clk_main);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct pwm_ops mtk_disp_pwm_ops = {
|
static const struct pwm_ops mtk_disp_pwm_ops = {
|
||||||
.config = mtk_disp_pwm_config,
|
.apply = mtk_disp_pwm_apply,
|
||||||
.enable = mtk_disp_pwm_enable,
|
|
||||||
.disable = mtk_disp_pwm_disable,
|
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue