Lines Matching full:dmic
2 * omap-dmic.c -- OMAP ASoC DMIC DAI driver
44 #include "omap-dmic.h"
65 static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) in omap_dmic_write() argument
67 writel_relaxed(val, dmic->io_base + reg); in omap_dmic_write()
70 static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg) in omap_dmic_read() argument
72 return readl_relaxed(dmic->io_base + reg); in omap_dmic_read()
75 static inline void omap_dmic_start(struct omap_dmic *dmic) in omap_dmic_start() argument
77 u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG); in omap_dmic_start()
80 omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_SET_REG, in omap_dmic_start()
83 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl | dmic->ch_enabled); in omap_dmic_start()
86 static inline void omap_dmic_stop(struct omap_dmic *dmic) in omap_dmic_stop() argument
88 u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG); in omap_dmic_stop()
89 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, in omap_dmic_stop()
93 omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_CLR_REG, in omap_dmic_stop()
98 static inline int dmic_is_enabled(struct omap_dmic *dmic) in dmic_is_enabled() argument
100 return omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG) & in dmic_is_enabled()
107 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); in omap_dmic_dai_startup() local
110 mutex_lock(&dmic->mutex); in omap_dmic_dai_startup()
113 dmic->active = 1; in omap_dmic_dai_startup()
117 mutex_unlock(&dmic->mutex); in omap_dmic_dai_startup()
125 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); in omap_dmic_dai_shutdown() local
127 mutex_lock(&dmic->mutex); in omap_dmic_dai_shutdown()
129 pm_qos_remove_request(&dmic->pm_qos_req); in omap_dmic_dai_shutdown()
132 dmic->active = 0; in omap_dmic_dai_shutdown()
134 mutex_unlock(&dmic->mutex); in omap_dmic_dai_shutdown()
137 static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate) in omap_dmic_select_divider() argument
146 if (dmic->fclk_freq == 19200000 && dmic->out_freq == 3840000) in omap_dmic_select_divider()
149 dev_err(dmic->dev, in omap_dmic_select_divider()
155 switch (dmic->out_freq) { in omap_dmic_select_divider()
157 if (dmic->fclk_freq != 24576000) in omap_dmic_select_divider()
162 switch (dmic->fclk_freq) { in omap_dmic_select_divider()
177 if (dmic->fclk_freq != 24576000) in omap_dmic_select_divider()
182 if (dmic->fclk_freq != 19200000) in omap_dmic_select_divider()
187 dev_err(dmic->dev, "invalid out frequency: %dHz\n", in omap_dmic_select_divider()
188 dmic->out_freq); in omap_dmic_select_divider()
195 dev_err(dmic->dev, "invalid out frequency %dHz for %dHz input\n", in omap_dmic_select_divider()
196 dmic->out_freq, dmic->fclk_freq); in omap_dmic_select_divider()
204 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); in omap_dmic_dai_hw_params() local
208 dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); in omap_dmic_dai_hw_params()
209 if (dmic->clk_div < 0) { in omap_dmic_dai_hw_params()
210 dev_err(dmic->dev, "no valid divider for %dHz from %dHz\n", in omap_dmic_dai_hw_params()
211 dmic->out_freq, dmic->fclk_freq); in omap_dmic_dai_hw_params()
215 dmic->ch_enabled = 0; in omap_dmic_dai_hw_params()
219 dmic->ch_enabled |= OMAP_DMIC_UP3_ENABLE; in omap_dmic_dai_hw_params()
222 dmic->ch_enabled |= OMAP_DMIC_UP2_ENABLE; in omap_dmic_dai_hw_params()
225 dmic->ch_enabled |= OMAP_DMIC_UP1_ENABLE; in omap_dmic_dai_hw_params()
228 dev_err(dmic->dev, "invalid number of legacy channels\n"); in omap_dmic_dai_hw_params()
234 dma_data->maxburst = dmic->threshold * channels; in omap_dmic_dai_hw_params()
235 dmic->latency = (OMAP_DMIC_THRES_MAX - dmic->threshold) * USEC_PER_SEC / in omap_dmic_dai_hw_params()
244 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); in omap_dmic_dai_prepare() local
247 if (pm_qos_request_active(&dmic->pm_qos_req)) in omap_dmic_dai_prepare()
248 pm_qos_update_request(&dmic->pm_qos_req, dmic->latency); in omap_dmic_dai_prepare()
251 omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold); in omap_dmic_dai_prepare()
253 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG); in omap_dmic_dai_prepare()
255 /* Set dmic out format */ in omap_dmic_dai_prepare()
260 /* Configure dmic clock divider */ in omap_dmic_dai_prepare()
262 ctrl |= OMAP_DMIC_CLK_DIV(dmic->clk_div); in omap_dmic_dai_prepare()
264 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl); in omap_dmic_dai_prepare()
266 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, in omap_dmic_dai_prepare()
276 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); in omap_dmic_dai_trigger() local
280 omap_dmic_start(dmic); in omap_dmic_dai_trigger()
283 omap_dmic_stop(dmic); in omap_dmic_dai_trigger()
292 static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id, in omap_dmic_select_fclk() argument
306 dev_err(dmic->dev, "invalid input frequency: %dHz\n", freq); in omap_dmic_select_fclk()
307 dmic->fclk_freq = 0; in omap_dmic_select_fclk()
311 if (dmic->sysclk == clk_id) { in omap_dmic_select_fclk()
312 dmic->fclk_freq = freq; in omap_dmic_select_fclk()
317 if (dmic->active && dmic_is_enabled(dmic)) { in omap_dmic_select_fclk()
318 dev_err(dmic->dev, "can't re-parent when DMIC active\n"); in omap_dmic_select_fclk()
333 dev_err(dmic->dev, "fclk clk_id (%d) not supported\n", clk_id); in omap_dmic_select_fclk()
337 parent_clk = clk_get(dmic->dev, parent_clk_name); in omap_dmic_select_fclk()
339 dev_err(dmic->dev, "can't get %s\n", parent_clk_name); in omap_dmic_select_fclk()
343 mux = clk_get_parent(dmic->fclk); in omap_dmic_select_fclk()
345 dev_err(dmic->dev, "can't get fck mux parent\n"); in omap_dmic_select_fclk()
350 mutex_lock(&dmic->mutex); in omap_dmic_select_fclk()
351 if (dmic->active) { in omap_dmic_select_fclk()
353 pm_runtime_put_sync(dmic->dev); in omap_dmic_select_fclk()
355 pm_runtime_get_sync(dmic->dev); in omap_dmic_select_fclk()
359 mutex_unlock(&dmic->mutex); in omap_dmic_select_fclk()
362 dev_err(dmic->dev, "re-parent failed\n"); in omap_dmic_select_fclk()
366 dmic->sysclk = clk_id; in omap_dmic_select_fclk()
367 dmic->fclk_freq = freq; in omap_dmic_select_fclk()
376 static int omap_dmic_select_outclk(struct omap_dmic *dmic, int clk_id, in omap_dmic_select_outclk() argument
382 dev_err(dmic->dev, "output clk_id (%d) not supported\n", in omap_dmic_select_outclk()
392 dmic->out_freq = freq; in omap_dmic_select_outclk()
395 dev_err(dmic->dev, "invalid out frequency: %dHz\n", freq); in omap_dmic_select_outclk()
396 dmic->out_freq = 0; in omap_dmic_select_outclk()
406 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); in omap_dmic_set_dai_sysclk() local
409 return omap_dmic_select_fclk(dmic, clk_id, freq); in omap_dmic_set_dai_sysclk()
411 return omap_dmic_select_outclk(dmic, clk_id, freq); in omap_dmic_set_dai_sysclk()
413 dev_err(dmic->dev, "invalid clock direction (%d)\n", dir); in omap_dmic_set_dai_sysclk()
428 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); in omap_dmic_probe() local
430 pm_runtime_enable(dmic->dev); in omap_dmic_probe()
433 pm_runtime_get_sync(dmic->dev); in omap_dmic_probe()
434 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, 0x00); in omap_dmic_probe()
435 pm_runtime_put_sync(dmic->dev); in omap_dmic_probe()
437 /* Configure DMIC threshold value */ in omap_dmic_probe()
438 dmic->threshold = OMAP_DMIC_THRES_MAX - 3; in omap_dmic_probe()
440 snd_soc_dai_init_dma_data(dai, NULL, &dmic->dma_data); in omap_dmic_probe()
447 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); in omap_dmic_remove() local
449 pm_runtime_disable(dmic->dev); in omap_dmic_remove()
455 .name = "omap-dmic",
469 .name = "omap-dmic",
474 struct omap_dmic *dmic; in asoc_dmic_probe() local
478 dmic = devm_kzalloc(&pdev->dev, sizeof(struct omap_dmic), GFP_KERNEL); in asoc_dmic_probe()
479 if (!dmic) in asoc_dmic_probe()
482 platform_set_drvdata(pdev, dmic); in asoc_dmic_probe()
483 dmic->dev = &pdev->dev; in asoc_dmic_probe()
484 dmic->sysclk = OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS; in asoc_dmic_probe()
486 mutex_init(&dmic->mutex); in asoc_dmic_probe()
488 dmic->fclk = devm_clk_get(dmic->dev, "fck"); in asoc_dmic_probe()
489 if (IS_ERR(dmic->fclk)) { in asoc_dmic_probe()
490 dev_err(dmic->dev, "cant get fck\n"); in asoc_dmic_probe()
496 dev_err(dmic->dev, "invalid dma memory resource\n"); in asoc_dmic_probe()
499 dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG; in asoc_dmic_probe()
501 dmic->dma_data.filter_data = "up_link"; in asoc_dmic_probe()
504 dmic->io_base = devm_ioremap_resource(&pdev->dev, res); in asoc_dmic_probe()
505 if (IS_ERR(dmic->io_base)) in asoc_dmic_probe()
506 return PTR_ERR(dmic->io_base); in asoc_dmic_probe()
523 { .compatible = "ti,omap4-dmic", },
530 .name = "omap-dmic",
538 MODULE_ALIAS("platform:omap-dmic");
540 MODULE_DESCRIPTION("OMAP DMIC ASoC Interface");