/* Only used for Ideal Ratio mode */ static int asrc_set_clock_ratio(enum asrc_pair_index index, int inrate, int outrate) { unsigned long val = 0; int integ, i; if (outrate == 0) { dev_err(asrc->dev, "wrong output sample rate: %d\n", outrate); return -EINVAL; } /* Formula: r = (1 << ASRC_RATIO_DECIMAL_DEPTH) / outrate * inrate; */ for (integ = 0; inrate >= outrate; integ++) inrate -= outrate; val |= (integ << ASRC_RATIO_DECIMAL_DEPTH); for (i = 1; i <= ASRC_RATIO_DECIMAL_DEPTH; i++) { if ((inrate * 2) >= outrate) { val |= (1 << (ASRC_RATIO_DECIMAL_DEPTH - i)); inrate = inrate * 2 - outrate; } else inrate = inrate << 1; if (inrate == 0) break; } regmap_write(asrc->regmap, REG_ASRIDRL(index), val); regmap_write(asrc->regmap, REG_ASRIDRH(index), (val >> 24)); return 0; }
/** * Calculate and set the ratio for Ideal Ratio mode only * * The ratio is a 32-bit fixed point value with 26 fractional bits. */ static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair, int inrate, int outrate) { struct fsl_asrc *asrc_priv = pair->asrc_priv; enum asrc_pair_index index = pair->index; unsigned long ratio; int i; if (!outrate) { pair_err("output rate should not be zero\n"); return -EINVAL; } /* Calculate the intergal part of the ratio */ ratio = (inrate / outrate) << IDEAL_RATIO_DECIMAL_DEPTH; /* ... and then the 26 depth decimal part */ inrate %= outrate; for (i = 1; i <= IDEAL_RATIO_DECIMAL_DEPTH; i++) { inrate <<= 1; if (inrate < outrate) continue; ratio |= 1 << (IDEAL_RATIO_DECIMAL_DEPTH - i); inrate -= outrate; if (!inrate) break; } regmap_write(asrc_priv->regmap, REG_ASRIDRL(index), ratio); regmap_write(asrc_priv->regmap, REG_ASRIDRH(index), ratio >> 24); return 0; }