staticinlinevoid img_i2s_in_flush(struct img_i2s_in *i2s)
{ int i;
u32 reg;
for (i = 0; i < i2s->active_channels; i++) {
reg = img_i2s_in_ch_readl(i2s, i, IMG_I2S_IN_CH_CTL);
reg |= IMG_I2S_IN_CH_CTL_FIFO_FLUSH_MASK;
img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
reg &= ~IMG_I2S_IN_CH_CTL_FIFO_FLUSH_MASK;
img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
}
}
switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
img_i2s_in_enable(i2s); break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
img_i2s_in_disable(i2s); break; default: return -EINVAL;
}
ret = pm_runtime_resume_and_get(i2s->dev); if (ret < 0) return ret;
for (i = 0; i < i2s->active_channels; i++)
img_i2s_in_ch_disable(i2s, i);
/* * BLKP and LRD must be set during separate register writes
*/ for (i = 0; i < i2s->max_i2s_chan; i++) {
reg = img_i2s_in_ch_readl(i2s, i, IMG_I2S_IN_CH_CTL);
reg = (reg & ~chan_control_mask) | chan_control_set;
img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
reg = (reg & ~IMG_I2S_IN_CH_CTL_BLKP_MASK) | blkp_set;
img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
reg = (reg & ~IMG_I2S_IN_CH_CTL_LRD_MASK) | lrd_set;
img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
}
for (i = 0; i < i2s->active_channels; i++)
img_i2s_in_ch_enable(i2s, i);
i2s->channel_base = base + (max_i2s_chan_pow_2 * 0x20);
i2s->clk_sys = devm_clk_get(dev, "sys"); if (IS_ERR(i2s->clk_sys)) return dev_err_probe(dev, PTR_ERR(i2s->clk_sys), "Failed to acquire clock 'sys'\n");
pm_runtime_enable(&pdev->dev); if (!pm_runtime_enabled(&pdev->dev)) {
ret = img_i2s_in_runtime_resume(&pdev->dev); if (ret) goto err_pm_disable;
}
ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) goto err_suspend;
rst = devm_reset_control_get_exclusive(dev, "rst"); if (IS_ERR(rst)) { if (PTR_ERR(rst) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
pm_runtime_put(&pdev->dev); goto err_suspend;
}
dev_dbg(dev, "No top level reset found\n");
img_i2s_in_disable(i2s);
for (i = 0; i < i2s->max_i2s_chan; i++)
img_i2s_in_ch_disable(i2s, i);
} else {
reset_control_assert(rst);
reset_control_deassert(rst);
}
img_i2s_in_writel(i2s, 0, IMG_I2S_IN_CTL);
for (i = 0; i < i2s->max_i2s_chan; i++)
img_i2s_in_ch_writel(i2s, i,
(4 << IMG_I2S_IN_CH_CTL_CCDEL_SHIFT) |
IMG_I2S_IN_CH_CTL_JUST_MASK |
IMG_I2S_IN_CH_CTL_FW_MASK, IMG_I2S_IN_CH_CTL);
pm_runtime_put(&pdev->dev);
i2s->suspend_ch_ctl = devm_kcalloc(dev,
i2s->max_i2s_chan, sizeof(*i2s->suspend_ch_ctl), GFP_KERNEL); if (!i2s->suspend_ch_ctl) {
ret = -ENOMEM; goto err_suspend;
}
ret = devm_snd_soc_register_component(dev, &img_i2s_in_component,
&i2s->dai_driver, 1); if (ret) goto err_suspend;
ret = devm_snd_dmaengine_pcm_register(dev, &img_i2s_in_dma_config, 0); if (ret) goto err_suspend;
return 0;
err_suspend: if (!pm_runtime_enabled(&pdev->dev))
img_i2s_in_runtime_suspend(&pdev->dev);
err_pm_disable:
pm_runtime_disable(&pdev->dev);
return ret;
}
staticvoid img_i2s_in_dev_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev))
img_i2s_in_runtime_suspend(&pdev->dev);
}
staticint img_i2s_in_suspend(struct device *dev)
{ struct img_i2s_in *i2s = dev_get_drvdata(dev); int i, ret;
u32 reg;
if (pm_runtime_status_suspended(dev)) {
ret = img_i2s_in_runtime_resume(dev); if (ret) return ret;
}
for (i = 0; i < i2s->max_i2s_chan; i++) {
reg = img_i2s_in_ch_readl(i2s, i, IMG_I2S_IN_CH_CTL);
i2s->suspend_ch_ctl[i] = reg;
}
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.