pwm: mtk-disp: Implement atomic API .apply()
authorJitao Shi <jitao.shi@mediatek.com>
Sun, 8 Aug 2021 13:24:31 +0000 (21:24 +0800)
committerThierry Reding <thierry.reding@gmail.com>
Thu, 2 Sep 2021 20:27:40 +0000 (22:27 +0200)
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>
drivers/pwm/pwm-mtk-disp.c

index 5817ac184fa355d6735944ad7fff6b59eacee0ac..caabcb30f90ed7b9a91d2569430390ea4ed8083f 100644 (file)
@@ -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)
@@ -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;
+               }
        }
 
        /*
@@ -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,
@@ -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,
 };