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

pwm: mtk-disp: Adjust the clocks to avoid them mismatch

The clks "main" and "mm" are prepared in .probe() (and unprepared in
.remove()). This results in the clocks being on during suspend which
results in unnecessarily increased power consumption.

Remove the clock operations from .probe() and .remove(). Add the
clk_prepare_enable() in .enable() and the clk_disable_unprepare() in
.disable().

Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
[thierry.reding@gmail.com: squashed in fixup patch]
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>

authored by

Jitao Shi and committed by
Thierry Reding
d7a4e582 dd8f6b29

+43 -52
+43 -52
drivers/pwm/pwm-mtk-disp.c
··· 74 74 u64 div, rate; 75 75 int err; 76 76 77 + err = clk_prepare_enable(mdp->clk_main); 78 + if (err < 0) { 79 + dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err)); 80 + return err; 81 + } 82 + 83 + err = clk_prepare_enable(mdp->clk_mm); 84 + if (err < 0) { 85 + dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err)); 86 + clk_disable_unprepare(mdp->clk_main); 87 + return err; 88 + } 89 + 77 90 /* 78 91 * Find period, high_width and clk_div to suit duty_ns and period_ns. 79 92 * Calculate proper div value to keep period value in the bound. ··· 100 87 rate = clk_get_rate(mdp->clk_main); 101 88 clk_div = div_u64(rate * period_ns, NSEC_PER_SEC) >> 102 89 PWM_PERIOD_BIT_WIDTH; 103 - if (clk_div > PWM_CLKDIV_MAX) 90 + if (clk_div > PWM_CLKDIV_MAX) { 91 + clk_disable_unprepare(mdp->clk_mm); 92 + clk_disable_unprepare(mdp->clk_main); 104 93 return -EINVAL; 94 + } 105 95 106 96 div = NSEC_PER_SEC * (clk_div + 1); 107 97 period = div64_u64(rate * period_ns, div); ··· 113 97 114 98 high_width = div64_u64(rate * duty_ns, div); 115 99 value = period | (high_width << PWM_HIGH_WIDTH_SHIFT); 116 - 117 - err = clk_enable(mdp->clk_main); 118 - if (err < 0) 119 - return err; 120 - 121 - err = clk_enable(mdp->clk_mm); 122 - if (err < 0) { 123 - clk_disable(mdp->clk_main); 124 - return err; 125 - } 126 100 127 101 mtk_disp_pwm_update_bits(mdp, mdp->data->con0, 128 102 PWM_CLKDIV_MASK, ··· 128 122 mtk_disp_pwm_update_bits(mdp, mdp->data->commit, 129 123 mdp->data->commit_mask, 130 124 0x0); 125 + } else { 126 + /* 127 + * For MT2701, disable double buffer before writing register 128 + * and select manual mode and use PWM_PERIOD/PWM_HIGH_WIDTH. 129 + */ 130 + mtk_disp_pwm_update_bits(mdp, mdp->data->bls_debug, 131 + mdp->data->bls_debug_mask, 132 + mdp->data->bls_debug_mask); 133 + mtk_disp_pwm_update_bits(mdp, mdp->data->con0, 134 + mdp->data->con0_sel, 135 + mdp->data->con0_sel); 131 136 } 132 137 133 - clk_disable(mdp->clk_mm); 134 - clk_disable(mdp->clk_main); 138 + clk_disable_unprepare(mdp->clk_mm); 139 + clk_disable_unprepare(mdp->clk_main); 135 140 136 141 return 0; 137 142 } ··· 152 135 struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); 153 136 int err; 154 137 155 - err = clk_enable(mdp->clk_main); 156 - if (err < 0) 157 - return err; 158 - 159 - err = clk_enable(mdp->clk_mm); 138 + err = clk_prepare_enable(mdp->clk_main); 160 139 if (err < 0) { 161 - clk_disable(mdp->clk_main); 140 + dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err)); 141 + return err; 142 + } 143 + 144 + err = clk_prepare_enable(mdp->clk_mm); 145 + if (err < 0) { 146 + dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err)); 147 + clk_disable_unprepare(mdp->clk_main); 162 148 return err; 163 149 } 164 150 ··· 178 158 mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask, 179 159 0x0); 180 160 181 - clk_disable(mdp->clk_mm); 182 - clk_disable(mdp->clk_main); 161 + clk_disable_unprepare(mdp->clk_mm); 162 + clk_disable_unprepare(mdp->clk_main); 183 163 } 184 164 185 165 static const struct pwm_ops mtk_disp_pwm_ops = { ··· 212 192 if (IS_ERR(mdp->clk_mm)) 213 193 return PTR_ERR(mdp->clk_mm); 214 194 215 - ret = clk_prepare(mdp->clk_main); 216 - if (ret < 0) 217 - return ret; 218 - 219 - ret = clk_prepare(mdp->clk_mm); 220 - if (ret < 0) 221 - goto disable_clk_main; 222 - 223 195 mdp->chip.dev = &pdev->dev; 224 196 mdp->chip.ops = &mtk_disp_pwm_ops; 225 197 mdp->chip.npwm = 1; 226 198 227 199 ret = pwmchip_add(&mdp->chip); 228 200 if (ret < 0) { 229 - dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); 230 - goto disable_clk_mm; 201 + dev_err(&pdev->dev, "pwmchip_add() failed: %pe\n", ERR_PTR(ret)); 202 + return ret; 231 203 } 232 204 233 205 platform_set_drvdata(pdev, mdp); 234 206 235 - /* 236 - * For MT2701, disable double buffer before writing register 237 - * and select manual mode and use PWM_PERIOD/PWM_HIGH_WIDTH. 238 - */ 239 - if (!mdp->data->has_commit) { 240 - mtk_disp_pwm_update_bits(mdp, mdp->data->bls_debug, 241 - mdp->data->bls_debug_mask, 242 - mdp->data->bls_debug_mask); 243 - mtk_disp_pwm_update_bits(mdp, mdp->data->con0, 244 - mdp->data->con0_sel, 245 - mdp->data->con0_sel); 246 - } 247 - 248 207 return 0; 249 - 250 - disable_clk_mm: 251 - clk_unprepare(mdp->clk_mm); 252 - disable_clk_main: 253 - clk_unprepare(mdp->clk_main); 254 - return ret; 255 208 } 256 209 257 210 static int mtk_disp_pwm_remove(struct platform_device *pdev) ··· 232 239 struct mtk_disp_pwm *mdp = platform_get_drvdata(pdev); 233 240 234 241 pwmchip_remove(&mdp->chip); 235 - clk_unprepare(mdp->clk_mm); 236 - clk_unprepare(mdp->clk_main); 237 242 238 243 return 0; 239 244 }