Lines Matching refs:dmic
3 * omap-dmic.c -- OMAP ASoC DMIC DAI driver
30 #include "omap-dmic.h"
51 static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
53 writel_relaxed(val, dmic->io_base + reg);
56 static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg)
58 return readl_relaxed(dmic->io_base + reg);
61 static inline void omap_dmic_start(struct omap_dmic *dmic)
63 u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
66 omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_SET_REG,
69 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl | dmic->ch_enabled);
72 static inline void omap_dmic_stop(struct omap_dmic *dmic)
74 u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
75 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
79 omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_CLR_REG,
84 static inline int dmic_is_enabled(struct omap_dmic *dmic)
86 return omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG) &
93 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
96 mutex_lock(&dmic->mutex);
99 dmic->active = 1;
103 mutex_unlock(&dmic->mutex);
111 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
113 mutex_lock(&dmic->mutex);
115 cpu_latency_qos_remove_request(&dmic->pm_qos_req);
118 dmic->active = 0;
120 mutex_unlock(&dmic->mutex);
123 static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate)
132 if (dmic->fclk_freq == 19200000 && dmic->out_freq == 3840000)
135 dev_err(dmic->dev,
141 switch (dmic->out_freq) {
143 if (dmic->fclk_freq != 24576000)
148 switch (dmic->fclk_freq) {
163 if (dmic->fclk_freq != 24576000)
168 if (dmic->fclk_freq != 19200000)
173 dev_err(dmic->dev, "invalid out frequency: %dHz\n",
174 dmic->out_freq);
181 dev_err(dmic->dev, "invalid out frequency %dHz for %dHz input\n",
182 dmic->out_freq, dmic->fclk_freq);
190 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
194 dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
195 if (dmic->clk_div < 0) {
196 dev_err(dmic->dev, "no valid divider for %dHz from %dHz\n",
197 dmic->out_freq, dmic->fclk_freq);
201 dmic->ch_enabled = 0;
205 dmic->ch_enabled |= OMAP_DMIC_UP3_ENABLE;
208 dmic->ch_enabled |= OMAP_DMIC_UP2_ENABLE;
211 dmic->ch_enabled |= OMAP_DMIC_UP1_ENABLE;
214 dev_err(dmic->dev, "invalid number of legacy channels\n");
220 dma_data->maxburst = dmic->threshold * channels;
221 dmic->latency = (OMAP_DMIC_THRES_MAX - dmic->threshold) * USEC_PER_SEC /
230 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
233 if (cpu_latency_qos_request_active(&dmic->pm_qos_req))
234 cpu_latency_qos_update_request(&dmic->pm_qos_req,
235 dmic->latency);
238 omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);
240 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
242 /* Set dmic out format */
247 /* Configure dmic clock divider */
249 ctrl |= OMAP_DMIC_CLK_DIV(dmic->clk_div);
251 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl);
253 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
263 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
267 omap_dmic_start(dmic);
270 omap_dmic_stop(dmic);
279 static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
293 dev_err(dmic->dev, "invalid input frequency: %dHz\n", freq);
294 dmic->fclk_freq = 0;
298 if (dmic->sysclk == clk_id) {
299 dmic->fclk_freq = freq;
304 if (dmic->active && dmic_is_enabled(dmic)) {
305 dev_err(dmic->dev, "can't re-parent when DMIC active\n");
320 dev_err(dmic->dev, "fclk clk_id (%d) not supported\n", clk_id);
324 parent_clk = clk_get(dmic->dev, parent_clk_name);
326 dev_err(dmic->dev, "can't get %s\n", parent_clk_name);
330 mux = clk_get_parent(dmic->fclk);
332 dev_err(dmic->dev, "can't get fck mux parent\n");
337 mutex_lock(&dmic->mutex);
338 if (dmic->active) {
340 pm_runtime_put_sync(dmic->dev);
342 pm_runtime_get_sync(dmic->dev);
346 mutex_unlock(&dmic->mutex);
349 dev_err(dmic->dev, "re-parent failed\n");
353 dmic->sysclk = clk_id;
354 dmic->fclk_freq = freq;
363 static int omap_dmic_select_outclk(struct omap_dmic *dmic, int clk_id,
369 dev_err(dmic->dev, "output clk_id (%d) not supported\n",
379 dmic->out_freq = freq;
382 dev_err(dmic->dev, "invalid out frequency: %dHz\n", freq);
383 dmic->out_freq = 0;
393 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
396 return omap_dmic_select_fclk(dmic, clk_id, freq);
398 return omap_dmic_select_outclk(dmic, clk_id, freq);
400 dev_err(dmic->dev, "invalid clock direction (%d)\n", dir);
406 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
408 pm_runtime_enable(dmic->dev);
411 pm_runtime_get_sync(dmic->dev);
412 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, 0x00);
413 pm_runtime_put_sync(dmic->dev);
416 dmic->threshold = OMAP_DMIC_THRES_MAX - 3;
418 snd_soc_dai_init_dma_data(dai, NULL, &dmic->dma_data);
425 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
427 pm_runtime_disable(dmic->dev);
444 .name = "omap-dmic",
456 .name = "omap-dmic",
462 struct omap_dmic *dmic;
466 dmic = devm_kzalloc(&pdev->dev, sizeof(struct omap_dmic), GFP_KERNEL);
467 if (!dmic)
470 platform_set_drvdata(pdev, dmic);
471 dmic->dev = &pdev->dev;
472 dmic->sysclk = OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS;
474 mutex_init(&dmic->mutex);
476 dmic->fclk = devm_clk_get(dmic->dev, "fck");
477 if (IS_ERR(dmic->fclk)) {
478 dev_err(dmic->dev, "can't get fck\n");
484 dev_err(dmic->dev, "invalid dma memory resource\n");
487 dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG;
489 dmic->dma_data.filter_data = "up_link";
491 dmic->io_base = devm_platform_ioremap_resource_byname(pdev, "mpu");
492 if (IS_ERR(dmic->io_base))
493 return PTR_ERR(dmic->io_base);
509 { .compatible = "ti,omap4-dmic", },
516 .name = "omap-dmic",
524 MODULE_ALIAS("platform:omap-dmic");