if (!np) {
dev_err(dev, "device node not found\n"); return ERR_PTR(-EINVAL);
}
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return ERR_PTR(-ENOMEM);
if (of_property_read_string(np, "atmel,model", &pdata->card_name))
pdata->card_name = "PDMIC";
if (of_property_read_u32(np, "atmel,mic-min-freq",
&pdata->mic_min_freq)) {
dev_err(dev, "failed to get mic-min-freq\n"); return ERR_PTR(-EINVAL);
}
if (of_property_read_u32(np, "atmel,mic-max-freq",
&pdata->mic_max_freq)) {
dev_err(dev, "failed to get mic-max-freq\n"); return ERR_PTR(-EINVAL);
}
if (pdata->mic_max_freq < pdata->mic_min_freq) {
dev_err(dev, "mic-max-freq should not be less than mic-min-freq\n"); return ERR_PTR(-EINVAL);
}
if (of_property_read_s32(np, "atmel,mic-offset", &pdata->mic_offset))
pdata->mic_offset = 0;
if (pdata->mic_offset > PDMIC_OFFSET_MAX_VAL) {
dev_warn(dev, "mic-offset value %d is larger than the max value %d, the max value is specified\n",
pdata->mic_offset, PDMIC_OFFSET_MAX_VAL);
pdata->mic_offset = PDMIC_OFFSET_MAX_VAL;
} elseif (pdata->mic_offset < PDMIC_OFFSET_MIN_VAL) {
dev_warn(dev, "mic-offset value %d is less than the min value %d, the min value is specified\n",
pdata->mic_offset, PDMIC_OFFSET_MIN_VAL);
pdata->mic_offset = PDMIC_OFFSET_MIN_VAL;
}
return pdata;
}
/* cpu dai component */ staticint atmel_pdmic_cpu_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai)
{ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); int ret;
ret = clk_prepare_enable(dd->gclk); if (ret) return ret;
ret = clk_prepare_enable(dd->pclk); if (ret) {
clk_disable_unprepare(dd->gclk); return ret;
}
/* Clear all bits in the Control Register(PDMIC_CR) */
regmap_write(dd->regmap, PDMIC_CR, 0);
dd->substream = substream;
/* Enable the overrun error interrupt */
regmap_write(dd->regmap, PDMIC_IER, PDMIC_IER_OVRE);
if (params_channels(params) != 1) {
dev_err(component->dev, "only supports one channel\n"); return -EINVAL;
}
if ((fs < rate_min) || (fs > rate_max)) {
dev_err(component->dev, "sample rate is %dHz, min rate is %dHz, max rate is %dHz\n",
fs, rate_min, rate_max);
switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
val = PDMIC_CR_ENPDM_EN << PDMIC_CR_ENPDM_SHIFT; break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
val = PDMIC_CR_ENPDM_DIS << PDMIC_CR_ENPDM_SHIFT; break; default: return -EINVAL;
}
pdata = atmel_pdmic_dt_init(dev); if (IS_ERR(pdata)) return PTR_ERR(pdata);
dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL); if (!dd) return -ENOMEM;
dd->pdata = pdata;
dd->dev = dev;
dd->irq = platform_get_irq(pdev, 0); if (dd->irq < 0) return dd->irq;
dd->pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(dd->pclk)) {
ret = PTR_ERR(dd->pclk);
dev_err(dev, "failed to get peripheral clock: %d\n", ret); return ret;
}
dd->gclk = devm_clk_get(dev, "gclk"); if (IS_ERR(dd->gclk)) {
ret = PTR_ERR(dd->gclk);
dev_err(dev, "failed to get GCK: %d\n", ret); return ret;
}
/* The gclk clock frequency must always be three times * lower than the pclk clock frequency
*/
ret = clk_set_rate(dd->gclk, clk_get_rate(dd->pclk)/3); if (ret) {
dev_err(dev, "failed to set GCK clock rate: %d\n", ret); return ret;
}
io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(io_base)) return PTR_ERR(io_base);
dd->phy_base = res->start;
dd->regmap = devm_regmap_init_mmio(dev, io_base,
&atmel_pdmic_regmap_config); if (IS_ERR(dd->regmap)) {
ret = PTR_ERR(dd->regmap);
dev_err(dev, "failed to init register map: %d\n", ret); return ret;
}
ret = devm_request_irq(dev, dd->irq, atmel_pdmic_interrupt, 0, "PDMIC", (void *)dd); if (ret < 0) {
dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
dd->irq, ret); return ret;
}
/* Get the minimal and maximal sample rate that the microphone supports */
atmel_pdmic_get_sample_rate(dd, &rate_min, &rate_max);
/* register cpu dai */
atmel_pdmic_cpu_dai.capture.rate_min = rate_min;
atmel_pdmic_cpu_dai.capture.rate_max = rate_max;
ret = devm_snd_soc_register_component(dev,
&atmel_pdmic_cpu_dai_component,
&atmel_pdmic_cpu_dai, 1); if (ret) {
dev_err(dev, "could not register CPU DAI: %d\n", ret); return ret;
}
/* register platform */
ret = devm_snd_dmaengine_pcm_register(dev,
&atmel_pdmic_dmaengine_pcm_config,
0); if (ret) {
dev_err(dev, "could not register platform: %d\n", ret); return ret;
}
/* register sound card */
card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) {
ret = -ENOMEM; goto unregister_codec;
}
snd_soc_card_set_drvdata(card, dd);
ret = atmel_pdmic_asoc_card_init(dev, card); if (ret) {
dev_err(dev, "failed to init sound card: %d\n", ret); goto unregister_codec;
}
ret = devm_snd_soc_register_card(dev, card); if (ret) {
dev_err(dev, "failed to register sound card: %d\n", ret); goto unregister_codec;
}
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.