if (src4xxx->master[dai->id]) {
mclk_div = src4xxx->mclk_hz/params_rate(params); if (src4xxx->mclk_hz != mclk_div*params_rate(params)) {
dev_err(component->dev, "mclk %d / rate %d has a remainder.\n",
src4xxx->mclk_hz, params_rate(params)); return -EINVAL;
}
val = ((int)mclk_div - 128) / 128; if ((val < 0) | (val > 3)) {
dev_err(component->dev, "div register setting %d is out of range\n",
val);
dev_err(component->dev, "unsupported sample rate %d Hz for the master clock of %d Hz\n",
params_rate(params), src4xxx->mclk_hz); return -EINVAL;
}
/* set the TX DIV */
ret = regmap_update_bits(src4xxx->regmap,
SRC4XXX_TX_CTL_07, SRC4XXX_TX_MCLK_DIV_MASK,
val<<SRC4XXX_TX_MCLK_DIV_SHIFT); if (ret) {
dev_err(component->dev, "Couldn't set the TX's div register to %d << %d = 0x%x\n",
val, SRC4XXX_TX_MCLK_DIV_SHIFT,
val<<SRC4XXX_TX_MCLK_DIV_SHIFT); return ret;
}
/* set the PLL for the digital receiver */ switch (src4xxx->mclk_hz) { case 24576000:
pj = 0x22;
jd = 0x00;
d = 0x00; break; case 22579200:
pj = 0x22;
jd = 0x1b;
d = 0xa3; break; default: /* don't error out here, * other parts of the chip are still functional * Dummy initialize variables to avoid * -Wsometimes-uninitialized from clang.
*/
dev_info(component->dev, "Couldn't set the RCV PLL as this master clock rate is unknown. Chosen regmap values may not match real world values.\n");
pj = 0x0;
jd = 0xff;
d = 0xff; break;
}
ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_0F, pj); if (ret < 0)
dev_err(component->dev, "Failed to update PLL register 0x%x\n",
SRC4XXX_RCV_PLL_0F);
ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_10, jd); if (ret < 0)
dev_err(component->dev, "Failed to update PLL register 0x%x\n",
SRC4XXX_RCV_PLL_10);
ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_11, d); if (ret < 0)
dev_err(component->dev, "Failed to update PLL register 0x%x\n",
SRC4XXX_RCV_PLL_11);
ret = regmap_update_bits(src4xxx->regmap,
SRC4XXX_TX_CTL_07, SRC4XXX_TX_MCLK_DIV_MASK,
val<<SRC4XXX_TX_MCLK_DIV_SHIFT); if (ret < 0) {
dev_err(component->dev, "Couldn't set the TX's div register to %d << %d = 0x%x\n",
val, SRC4XXX_TX_MCLK_DIV_SHIFT,
val<<SRC4XXX_TX_MCLK_DIV_SHIFT); return ret;
}
return regmap_update_bits(src4xxx->regmap, reg,
SRC4XXX_MCLK_DIV_MASK, val);
} else {
dev_info(dai->dev, "not setting up MCLK as not master\n");
}
int src4xxx_probe(struct device *dev, struct regmap *regmap, void (*switch_mode)(struct device *dev))
{ struct src4xxx *src4xxx; int ret;
if (IS_ERR(regmap)) return PTR_ERR(regmap);
src4xxx = devm_kzalloc(dev, sizeof(*src4xxx), GFP_KERNEL); if (!src4xxx) return -ENOMEM;
src4xxx->regmap = regmap;
src4xxx->dev = dev;
src4xxx->mclk_hz = 0; /* mclk has not been configured yet */
dev_set_drvdata(dev, src4xxx);
ret = regmap_write(regmap, SRC4XXX_PWR_RST_01, SRC4XXX_RESET); if (ret < 0)
dev_err(dev, "Failed to issue reset: %d\n", ret);
usleep_range(1, 500); /* sleep for more then 500 ns */
ret = regmap_write(regmap, SRC4XXX_PWR_RST_01, SRC4XXX_POWER_DOWN); if (ret < 0)
dev_err(dev, "Failed to decommission reset: %d\n", ret);
usleep_range(500, 1000); /* sleep for 500 us or more */
ret = regmap_update_bits(src4xxx->regmap, SRC4XXX_PWR_RST_01,
SRC4XXX_POWER_ENABLE, SRC4XXX_POWER_ENABLE); if (ret < 0)
dev_err(dev, "Failed to port A and B : %d\n", ret);
/* set receiver to use master clock (rcv mclk is most likely jittery) */
ret = regmap_update_bits(src4xxx->regmap, SRC4XXX_RCV_CTL_0D,
SRC4XXX_RXCLK_MCLK, SRC4XXX_RXCLK_MCLK); if (ret < 0)
dev_err(dev, "Failed to enable mclk as the PLL1 DIR reference : %d\n", ret);
/* default to leaving the PLL2 running on loss of lock, divide by 8 */
ret = regmap_update_bits(src4xxx->regmap, SRC4XXX_RCV_CTL_0E,
SRC4XXX_PLL2_DIV_8 | SRC4XXX_REC_MCLK_EN | SRC4XXX_PLL2_LOL,
SRC4XXX_PLL2_DIV_8 | SRC4XXX_REC_MCLK_EN | SRC4XXX_PLL2_LOL); if (ret < 0)
dev_err(dev, "Failed to enable mclk rec and div : %d\n", ret);
ret = devm_snd_soc_register_component(dev, &src4xxx_driver,
src4xxx_dai_driver, ARRAY_SIZE(src4xxx_dai_driver)); if (ret == 0)
dev_info(dev, "src4392 probe ok %d\n", ret); return ret;
}
EXPORT_SYMBOL_GPL(src4xxx_probe);
staticbool src4xxx_volatile_register(struct device *dev, unsignedint reg)
{ switch (reg) { case SRC4XXX_RES_00: case SRC4XXX_GLOBAL_ITR_STS_02: case SRC4XXX_SRC_DIT_STS_0A: case SRC4XXX_NON_AUDIO_D_12: case SRC4XXX_RVC_STS_13: case SRC4XXX_RVC_STS_14: case SRC4XXX_RVC_STS_15: case SRC4XXX_SUB_CODE_1F: case SRC4XXX_SUB_CODE_20: case SRC4XXX_SUB_CODE_21: case SRC4XXX_SUB_CODE_22: case SRC4XXX_SUB_CODE_23: case SRC4XXX_SUB_CODE_24: case SRC4XXX_SUB_CODE_25: case SRC4XXX_SUB_CODE_26: case SRC4XXX_SUB_CODE_27: case SRC4XXX_SUB_CODE_28: case SRC4XXX_PC_PREAMBLE_HI_29: case SRC4XXX_PC_PREAMBLE_LO_2A: case SRC4XXX_PD_PREAMBLE_HI_2B: case SRC4XXX_PC_PREAMBLE_LO_2C: case SRC4XXX_IO_RATIO_32: case SRC4XXX_IO_RATIO_33: returntrue;
}
if (reg > SRC4XXX_IO_RATIO_33 && reg < SRC4XXX_PAGE_SEL_7F) returntrue;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.