Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jitao Shi and committed by
Thierry Reding
888a623d d7a4e582

+41 -54
+41 -54
drivers/pwm/pwm-mtk-disp.c
··· 47 47 struct clk *clk_main; 48 48 struct clk *clk_mm; 49 49 void __iomem *base; 50 + bool enabled; 50 51 }; 51 52 52 53 static inline struct mtk_disp_pwm *to_mtk_disp_pwm(struct pwm_chip *chip) ··· 67 66 writel(value, address); 68 67 } 69 68 70 - static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 71 - int duty_ns, int period_ns) 69 + static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 70 + const struct pwm_state *state) 72 71 { 73 72 struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); 74 73 u32 clk_div, period, high_width, value; 75 74 u64 div, rate; 76 75 int err; 77 76 78 - err = clk_prepare_enable(mdp->clk_main); 79 - if (err < 0) { 80 - dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err)); 81 - return err; 77 + if (state->polarity != PWM_POLARITY_NORMAL) 78 + return -EINVAL; 79 + 80 + if (!state->enabled) { 81 + mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask, 82 + 0x0); 83 + 84 + if (mdp->enabled) { 85 + clk_disable_unprepare(mdp->clk_mm); 86 + clk_disable_unprepare(mdp->clk_main); 87 + } 88 + 89 + mdp->enabled = false; 90 + return 0; 82 91 } 83 92 84 - err = clk_prepare_enable(mdp->clk_mm); 85 - if (err < 0) { 86 - dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err)); 87 - clk_disable_unprepare(mdp->clk_main); 88 - return err; 93 + if (!mdp->enabled) { 94 + err = clk_prepare_enable(mdp->clk_main); 95 + if (err < 0) { 96 + dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", 97 + ERR_PTR(err)); 98 + return err; 99 + } 100 + 101 + err = clk_prepare_enable(mdp->clk_mm); 102 + if (err < 0) { 103 + dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", 104 + ERR_PTR(err)); 105 + clk_disable_unprepare(mdp->clk_main); 106 + return err; 107 + } 89 108 } 90 109 91 110 /* ··· 119 98 * high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1)) 120 99 */ 121 100 rate = clk_get_rate(mdp->clk_main); 122 - clk_div = div_u64(rate * period_ns, NSEC_PER_SEC) >> 101 + clk_div = div_u64(rate * state->period, NSEC_PER_SEC) >> 123 102 PWM_PERIOD_BIT_WIDTH; 124 103 if (clk_div > PWM_CLKDIV_MAX) { 125 - clk_disable_unprepare(mdp->clk_mm); 126 - clk_disable_unprepare(mdp->clk_main); 104 + if (!mdp->enabled) { 105 + clk_disable_unprepare(mdp->clk_mm); 106 + clk_disable_unprepare(mdp->clk_main); 107 + } 127 108 return -EINVAL; 128 109 } 129 110 130 111 div = NSEC_PER_SEC * (clk_div + 1); 131 - period = div64_u64(rate * period_ns, div); 112 + period = div64_u64(rate * state->period, div); 132 113 if (period > 0) 133 114 period--; 134 115 135 - high_width = div64_u64(rate * duty_ns, div); 116 + high_width = div64_u64(rate * state->duty_cycle, div); 136 117 value = period | (high_width << PWM_HIGH_WIDTH_SHIFT); 137 118 138 119 mtk_disp_pwm_update_bits(mdp, mdp->data->con0, ··· 164 141 mdp->data->con0_sel); 165 142 } 166 143 167 - clk_disable_unprepare(mdp->clk_mm); 168 - clk_disable_unprepare(mdp->clk_main); 169 - 170 - return 0; 171 - } 172 - 173 - static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 174 - { 175 - struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); 176 - int err; 177 - 178 - err = clk_prepare_enable(mdp->clk_main); 179 - if (err < 0) { 180 - dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err)); 181 - return err; 182 - } 183 - 184 - err = clk_prepare_enable(mdp->clk_mm); 185 - if (err < 0) { 186 - dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err)); 187 - clk_disable_unprepare(mdp->clk_main); 188 - return err; 189 - } 190 - 191 144 mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask, 192 145 mdp->data->enable_mask); 146 + mdp->enabled = true; 193 147 194 148 return 0; 195 - } 196 - 197 - static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 198 - { 199 - struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); 200 - 201 - mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask, 202 - 0x0); 203 - 204 - clk_disable_unprepare(mdp->clk_mm); 205 - clk_disable_unprepare(mdp->clk_main); 206 149 } 207 150 208 151 static const struct pwm_ops mtk_disp_pwm_ops = { 209 - .config = mtk_disp_pwm_config, 210 - .enable = mtk_disp_pwm_enable, 211 - .disable = mtk_disp_pwm_disable, 152 + .apply = mtk_disp_pwm_apply, 212 153 .owner = THIS_MODULE, 213 154 }; 214 155