Skip to content

Commit

Permalink
pwm: mtk-disp: Implement atomic API .apply()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jitao Shi authored and Thierry Reding committed Sep 2, 2021
1 parent d7a4e58 commit 888a623
Showing 1 changed file with 41 additions and 54 deletions.
95 changes: 41 additions & 54 deletions drivers/pwm/pwm-mtk-disp.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct mtk_disp_pwm {
struct clk *clk_main;
struct clk *clk_mm;
void __iomem *base;
bool enabled;
};

static inline struct mtk_disp_pwm *to_mtk_disp_pwm(struct pwm_chip *chip)
Expand All @@ -66,25 +67,45 @@ static void mtk_disp_pwm_update_bits(struct mtk_disp_pwm *mdp, u32 offset,
writel(value, address);
}

static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
u32 clk_div, period, high_width, value;
u64 div, rate;
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;
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;
}

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;
if (!mdp->enabled) {
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;
}
}

/*
Expand All @@ -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))
*/
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;
if (clk_div > PWM_CLKDIV_MAX) {
clk_disable_unprepare(mdp->clk_mm);
clk_disable_unprepare(mdp->clk_main);
if (!mdp->enabled) {
clk_disable_unprepare(mdp->clk_mm);
clk_disable_unprepare(mdp->clk_main);
}
return -EINVAL;
}

div = NSEC_PER_SEC * (clk_div + 1);
period = div64_u64(rate * period_ns, div);
period = div64_u64(rate * state->period, div);
if (period > 0)
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);

mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
Expand Down Expand Up @@ -141,51 +164,15 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
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,
mdp->data->enable_mask);
mdp->enabled = true;

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 = {
.config = mtk_disp_pwm_config,
.enable = mtk_disp_pwm_enable,
.disable = mtk_disp_pwm_disable,
.apply = mtk_disp_pwm_apply,
.owner = THIS_MODULE,
};

Expand Down

0 comments on commit 888a623

Please sign in to comment.