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

ASoC: tlv320aic32x4: Fix the divide by zero

The value of register(NDAC,MDAC,NADC,MADC,BCLKN) maybe zero lead to
divide by zero in clk_aic32x4_div_recalc_rate().And the rate should be
divide by 128 if the value was zero in this function according to the
datasheet.

Add the macro AIC32X4_DIV_MAX to present the 128 and return 0 if failing
to read the value of register.

Signed-off-by: Guiting Shen <aarongt.shen@gmail.com>
Link: https://lore.kernel.org/r/20230813125520.11067-1-aarongt.shen@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Guiting Shen and committed by
Mark Brown
11e756cc b39eee27

+14 -7
+11 -5
sound/soc/codecs/tlv320aic32x4-clk.c
··· 321 321 u8 divisor; 322 322 323 323 divisor = DIV_ROUND_UP(parent_rate, rate); 324 - if (divisor > 128) 324 + if (divisor > AIC32X4_DIV_MAX) 325 325 return -EINVAL; 326 326 327 327 return regmap_update_bits(div->regmap, div->reg, ··· 334 334 unsigned long divisor; 335 335 336 336 divisor = DIV_ROUND_UP(req->best_parent_rate, req->rate); 337 - if (divisor > 128) 337 + if (divisor > AIC32X4_DIV_MAX) 338 338 return -EINVAL; 339 339 340 340 req->rate = DIV_ROUND_UP(req->best_parent_rate, divisor); ··· 345 345 unsigned long parent_rate) 346 346 { 347 347 struct clk_aic32x4 *div = to_clk_aic32x4(hw); 348 - 349 348 unsigned int val; 349 + int err; 350 350 351 - regmap_read(div->regmap, div->reg, &val); 351 + err = regmap_read(div->regmap, div->reg, &val); 352 + if (err) 353 + return 0; 352 354 353 - return DIV_ROUND_UP(parent_rate, val & AIC32X4_DIV_MASK); 355 + val &= AIC32X4_DIV_MASK; 356 + if (!val) 357 + val = AIC32X4_DIV_MAX; 358 + 359 + return DIV_ROUND_UP(parent_rate, val); 354 360 } 355 361 356 362 static const struct clk_ops aic32x4_div_ops = {
+3 -2
sound/soc/codecs/tlv320aic32x4.h
··· 223 223 #define AIC32X4_REFPOWERUP_120MS 0x07 224 224 225 225 /* Common mask and enable for all of the dividers */ 226 - #define AIC32X4_DIVEN BIT(7) 227 - #define AIC32X4_DIV_MASK GENMASK(6, 0) 226 + #define AIC32X4_DIVEN BIT(7) 227 + #define AIC32X4_DIV_MASK GENMASK(6, 0) 228 + #define AIC32X4_DIV_MAX 128 228 229 229 230 /* Clock Limits */ 230 231 #define AIC32X4_MAX_DOSR_FREQ 6200000