Commit fd26f9474676bb2232ba9dded148edc41fd02ef4

Authored by Peter Ujfalusi
Committed by Mark Brown
1 parent 5032dc3429

ASoC: OMAP4: omap-dmic: Initial support for OMAP DMIC

Add support for OMAP4 Digital Microphone interface.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 4 changed files with 623 additions and 0 deletions Side-by-side Diff

sound/soc/omap/Kconfig
... ... @@ -2,6 +2,9 @@
2 2 tristate "SoC Audio for the Texas Instruments OMAP chips"
3 3 depends on ARCH_OMAP
4 4  
  5 +config SND_OMAP_SOC_DMIC
  6 + tristate
  7 +
5 8 config SND_OMAP_SOC_MCBSP
6 9 tristate
7 10 select OMAP_MCBSP
sound/soc/omap/Makefile
1 1 # OMAP Platform Support
2 2 snd-soc-omap-objs := omap-pcm.o
  3 +snd-soc-omap-dmic-objs := omap-dmic.o
3 4 snd-soc-omap-mcbsp-objs := omap-mcbsp.o
4 5 snd-soc-omap-mcpdm-objs := omap-mcpdm.o
5 6 snd-soc-omap-hdmi-objs := omap-hdmi.o
6 7  
7 8 obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
  9 +obj-$(CONFIG_SND_OMAP_SOC_DMIC) += snd-soc-omap-dmic.o
8 10 obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
9 11 obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o
10 12 obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
sound/soc/omap/omap-dmic.c
  1 +/*
  2 + * omap-dmic.c -- OMAP ASoC DMIC DAI driver
  3 + *
  4 + * Copyright (C) 2010 - 2011 Texas Instruments
  5 + *
  6 + * Author: David Lambert <dlambert@ti.com>
  7 + * Misael Lopez Cruz <misael.lopez@ti.com>
  8 + * Liam Girdwood <lrg@ti.com>
  9 + * Peter Ujfalusi <peter.ujfalusi@ti.com>
  10 + *
  11 + * This program is free software; you can redistribute it and/or
  12 + * modify it under the terms of the GNU General Public License
  13 + * version 2 as published by the Free Software Foundation.
  14 + *
  15 + * This program is distributed in the hope that it will be useful, but
  16 + * WITHOUT ANY WARRANTY; without even the implied warranty of
  17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18 + * General Public License for more details.
  19 + *
  20 + * You should have received a copy of the GNU General Public License
  21 + * along with this program; if not, write to the Free Software
  22 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  23 + * 02110-1301 USA
  24 + *
  25 + */
  26 +
  27 +#include <linux/init.h>
  28 +#include <linux/module.h>
  29 +#include <linux/platform_device.h>
  30 +#include <linux/err.h>
  31 +#include <linux/clk.h>
  32 +#include <linux/io.h>
  33 +#include <linux/slab.h>
  34 +#include <linux/pm_runtime.h>
  35 +#include <plat/dma.h>
  36 +
  37 +#include <sound/core.h>
  38 +#include <sound/pcm.h>
  39 +#include <sound/pcm_params.h>
  40 +#include <sound/initval.h>
  41 +#include <sound/soc.h>
  42 +
  43 +#include "omap-pcm.h"
  44 +#include "omap-dmic.h"
  45 +
  46 +struct omap_dmic {
  47 + struct device *dev;
  48 + void __iomem *io_base;
  49 + struct clk *fclk;
  50 + int fclk_freq;
  51 + int out_freq;
  52 + int clk_div;
  53 + int sysclk;
  54 + int threshold;
  55 + u32 ch_enabled;
  56 + bool active;
  57 + struct mutex mutex;
  58 +};
  59 +
  60 +/*
  61 + * Stream DMA parameters
  62 + */
  63 +static struct omap_pcm_dma_data omap_dmic_dai_dma_params = {
  64 + .name = "DMIC capture",
  65 + .data_type = OMAP_DMA_DATA_TYPE_S32,
  66 + .sync_mode = OMAP_DMA_SYNC_PACKET,
  67 +};
  68 +
  69 +static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
  70 +{
  71 + __raw_writel(val, dmic->io_base + reg);
  72 +}
  73 +
  74 +static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg)
  75 +{
  76 + return __raw_readl(dmic->io_base + reg);
  77 +}
  78 +
  79 +static inline void omap_dmic_start(struct omap_dmic *dmic)
  80 +{
  81 + u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
  82 +
  83 + /* Configure DMA controller */
  84 + omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_SET_REG,
  85 + OMAP_DMIC_DMA_ENABLE);
  86 +
  87 + omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl | dmic->ch_enabled);
  88 +}
  89 +
  90 +static inline void omap_dmic_stop(struct omap_dmic *dmic)
  91 +{
  92 + u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
  93 + omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
  94 + ctrl & ~OMAP_DMIC_UP_ENABLE_MASK);
  95 +
  96 + /* Disable DMA request generation */
  97 + omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_CLR_REG,
  98 + OMAP_DMIC_DMA_ENABLE);
  99 +
  100 +}
  101 +
  102 +static inline int dmic_is_enabled(struct omap_dmic *dmic)
  103 +{
  104 + return omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG) &
  105 + OMAP_DMIC_UP_ENABLE_MASK;
  106 +}
  107 +
  108 +static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
  109 + struct snd_soc_dai *dai)
  110 +{
  111 + struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
  112 + int ret = 0;
  113 +
  114 + mutex_lock(&dmic->mutex);
  115 +
  116 + if (!dai->active) {
  117 + pm_runtime_get_sync(dmic->dev);
  118 + snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
  119 + dmic->active = 1;
  120 + } else {
  121 + ret = -EBUSY;
  122 + }
  123 +
  124 + mutex_unlock(&dmic->mutex);
  125 +
  126 + return ret;
  127 +}
  128 +
  129 +static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
  130 + struct snd_soc_dai *dai)
  131 +{
  132 + struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
  133 +
  134 + mutex_lock(&dmic->mutex);
  135 +
  136 + if (!dai->active) {
  137 + pm_runtime_put_sync(dmic->dev);
  138 + dmic->active = 0;
  139 + }
  140 +
  141 + mutex_unlock(&dmic->mutex);
  142 +}
  143 +
  144 +static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate)
  145 +{
  146 + int divider = -EINVAL;
  147 +
  148 + /*
  149 + * 192KHz rate is only supported with 19.2MHz/3.84MHz clock
  150 + * configuration.
  151 + */
  152 + if (sample_rate == 192000) {
  153 + if (dmic->fclk_freq == 19200000 && dmic->out_freq == 3840000)
  154 + divider = 0x6; /* Divider: 5 (192KHz sampling rate) */
  155 + else
  156 + dev_err(dmic->dev,
  157 + "invalid clock configuration for 192KHz\n");
  158 +
  159 + return divider;
  160 + }
  161 +
  162 + switch (dmic->out_freq) {
  163 + case 1536000:
  164 + if (dmic->fclk_freq != 24576000)
  165 + goto div_err;
  166 + divider = 0x4; /* Divider: 16 */
  167 + break;
  168 + case 2400000:
  169 + switch (dmic->fclk_freq) {
  170 + case 12000000:
  171 + divider = 0x5; /* Divider: 5 */
  172 + break;
  173 + case 19200000:
  174 + divider = 0x0; /* Divider: 8 */
  175 + break;
  176 + case 24000000:
  177 + divider = 0x2; /* Divider: 10 */
  178 + break;
  179 + default:
  180 + goto div_err;
  181 + }
  182 + break;
  183 + case 3072000:
  184 + if (dmic->fclk_freq != 24576000)
  185 + goto div_err;
  186 + divider = 0x3; /* Divider: 8 */
  187 + break;
  188 + case 3840000:
  189 + if (dmic->fclk_freq != 19200000)
  190 + goto div_err;
  191 + divider = 0x1; /* Divider: 5 (96KHz sampling rate) */
  192 + break;
  193 + default:
  194 + dev_err(dmic->dev, "invalid out frequency: %dHz\n",
  195 + dmic->out_freq);
  196 + break;
  197 + }
  198 +
  199 + return divider;
  200 +
  201 +div_err:
  202 + dev_err(dmic->dev, "invalid out frequency %dHz for %dHz input\n",
  203 + dmic->out_freq, dmic->fclk_freq);
  204 + return -EINVAL;
  205 +}
  206 +
  207 +static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
  208 + struct snd_pcm_hw_params *params,
  209 + struct snd_soc_dai *dai)
  210 +{
  211 + struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
  212 + int channels;
  213 +
  214 + dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
  215 + if (dmic->clk_div < 0) {
  216 + dev_err(dmic->dev, "no valid divider for %dHz from %dHz\n",
  217 + dmic->out_freq, dmic->fclk_freq);
  218 + return -EINVAL;
  219 + }
  220 +
  221 + dmic->ch_enabled = 0;
  222 + channels = params_channels(params);
  223 + switch (channels) {
  224 + case 6:
  225 + dmic->ch_enabled |= OMAP_DMIC_UP3_ENABLE;
  226 + case 4:
  227 + dmic->ch_enabled |= OMAP_DMIC_UP2_ENABLE;
  228 + case 2:
  229 + dmic->ch_enabled |= OMAP_DMIC_UP1_ENABLE;
  230 + break;
  231 + default:
  232 + dev_err(dmic->dev, "invalid number of legacy channels\n");
  233 + return -EINVAL;
  234 + }
  235 +
  236 + /* packet size is threshold * channels */
  237 + omap_dmic_dai_dma_params.packet_size = dmic->threshold * channels;
  238 + snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params);
  239 +
  240 + return 0;
  241 +}
  242 +
  243 +static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream,
  244 + struct snd_soc_dai *dai)
  245 +{
  246 + struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
  247 + u32 ctrl;
  248 +
  249 + /* Configure uplink threshold */
  250 + omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);
  251 +
  252 + ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
  253 +
  254 + /* Set dmic out format */
  255 + ctrl &= ~(OMAP_DMIC_FORMAT | OMAP_DMIC_POLAR_MASK);
  256 + ctrl |= (OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
  257 + OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
  258 +
  259 + /* Configure dmic clock divider */
  260 + ctrl &= ~OMAP_DMIC_CLK_DIV_MASK;
  261 + ctrl |= OMAP_DMIC_CLK_DIV(dmic->clk_div);
  262 +
  263 + omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl);
  264 +
  265 + omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
  266 + ctrl | OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
  267 + OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
  268 +
  269 + return 0;
  270 +}
  271 +
  272 +static int omap_dmic_dai_trigger(struct snd_pcm_substream *substream,
  273 + int cmd, struct snd_soc_dai *dai)
  274 +{
  275 + struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
  276 +
  277 + switch (cmd) {
  278 + case SNDRV_PCM_TRIGGER_START:
  279 + omap_dmic_start(dmic);
  280 + break;
  281 + case SNDRV_PCM_TRIGGER_STOP:
  282 + omap_dmic_stop(dmic);
  283 + break;
  284 + default:
  285 + break;
  286 + }
  287 +
  288 + return 0;
  289 +}
  290 +
  291 +static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
  292 + unsigned int freq)
  293 +{
  294 + struct clk *parent_clk;
  295 + char *parent_clk_name;
  296 + int ret = 0;
  297 +
  298 + switch (freq) {
  299 + case 12000000:
  300 + case 19200000:
  301 + case 24000000:
  302 + case 24576000:
  303 + break;
  304 + default:
  305 + dev_err(dmic->dev, "invalid input frequency: %dHz\n", freq);
  306 + dmic->fclk_freq = 0;
  307 + return -EINVAL;
  308 + }
  309 +
  310 + if (dmic->sysclk == clk_id) {
  311 + dmic->fclk_freq = freq;
  312 + return 0;
  313 + }
  314 +
  315 + /* re-parent not allowed if a stream is ongoing */
  316 + if (dmic->active && dmic_is_enabled(dmic)) {
  317 + dev_err(dmic->dev, "can't re-parent when DMIC active\n");
  318 + return -EBUSY;
  319 + }
  320 +
  321 + switch (clk_id) {
  322 + case OMAP_DMIC_SYSCLK_PAD_CLKS:
  323 + parent_clk_name = "pad_clks_ck";
  324 + break;
  325 + case OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS:
  326 + parent_clk_name = "slimbus_clk";
  327 + break;
  328 + case OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS:
  329 + parent_clk_name = "dmic_sync_mux_ck";
  330 + break;
  331 + default:
  332 + dev_err(dmic->dev, "fclk clk_id (%d) not supported\n", clk_id);
  333 + return -EINVAL;
  334 + }
  335 +
  336 + parent_clk = clk_get(dmic->dev, parent_clk_name);
  337 + if (IS_ERR(parent_clk)) {
  338 + dev_err(dmic->dev, "can't get %s\n", parent_clk_name);
  339 + return -ENODEV;
  340 + }
  341 +
  342 + mutex_lock(&dmic->mutex);
  343 + if (dmic->active) {
  344 + /* disable clock while reparenting */
  345 + pm_runtime_put_sync(dmic->dev);
  346 + ret = clk_set_parent(dmic->fclk, parent_clk);
  347 + pm_runtime_get_sync(dmic->dev);
  348 + } else {
  349 + ret = clk_set_parent(dmic->fclk, parent_clk);
  350 + }
  351 + mutex_unlock(&dmic->mutex);
  352 +
  353 + if (ret < 0) {
  354 + dev_err(dmic->dev, "re-parent failed\n");
  355 + goto err_busy;
  356 + }
  357 +
  358 + dmic->sysclk = clk_id;
  359 + dmic->fclk_freq = freq;
  360 +
  361 +err_busy:
  362 + clk_put(parent_clk);
  363 +
  364 + return ret;
  365 +}
  366 +
  367 +static int omap_dmic_select_outclk(struct omap_dmic *dmic, int clk_id,
  368 + unsigned int freq)
  369 +{
  370 + int ret = 0;
  371 +
  372 + if (clk_id != OMAP_DMIC_ABE_DMIC_CLK) {
  373 + dev_err(dmic->dev, "output clk_id (%d) not supported\n",
  374 + clk_id);
  375 + return -EINVAL;
  376 + }
  377 +
  378 + switch (freq) {
  379 + case 1536000:
  380 + case 2400000:
  381 + case 3072000:
  382 + case 3840000:
  383 + dmic->out_freq = freq;
  384 + break;
  385 + default:
  386 + dev_err(dmic->dev, "invalid out frequency: %dHz\n", freq);
  387 + dmic->out_freq = 0;
  388 + ret = -EINVAL;
  389 + }
  390 +
  391 + return ret;
  392 +}
  393 +
  394 +static int omap_dmic_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
  395 + unsigned int freq, int dir)
  396 +{
  397 + struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
  398 +
  399 + if (dir == SND_SOC_CLOCK_IN)
  400 + return omap_dmic_select_fclk(dmic, clk_id, freq);
  401 + else if (dir == SND_SOC_CLOCK_OUT)
  402 + return omap_dmic_select_outclk(dmic, clk_id, freq);
  403 +
  404 + dev_err(dmic->dev, "invalid clock direction (%d)\n", dir);
  405 + return -EINVAL;
  406 +}
  407 +
  408 +static const struct snd_soc_dai_ops omap_dmic_dai_ops = {
  409 + .startup = omap_dmic_dai_startup,
  410 + .shutdown = omap_dmic_dai_shutdown,
  411 + .hw_params = omap_dmic_dai_hw_params,
  412 + .prepare = omap_dmic_dai_prepare,
  413 + .trigger = omap_dmic_dai_trigger,
  414 + .set_sysclk = omap_dmic_set_dai_sysclk,
  415 +};
  416 +
  417 +static int omap_dmic_probe(struct snd_soc_dai *dai)
  418 +{
  419 + struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
  420 +
  421 + pm_runtime_enable(dmic->dev);
  422 +
  423 + /* Disable lines while request is ongoing */
  424 + pm_runtime_get_sync(dmic->dev);
  425 + omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, 0x00);
  426 + pm_runtime_put_sync(dmic->dev);
  427 +
  428 + /* Configure DMIC threshold value */
  429 + dmic->threshold = OMAP_DMIC_THRES_MAX - 3;
  430 + return 0;
  431 +}
  432 +
  433 +static int omap_dmic_remove(struct snd_soc_dai *dai)
  434 +{
  435 + struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
  436 +
  437 + pm_runtime_disable(dmic->dev);
  438 +
  439 + return 0;
  440 +}
  441 +
  442 +static struct snd_soc_dai_driver omap_dmic_dai = {
  443 + .name = "omap-dmic",
  444 + .probe = omap_dmic_probe,
  445 + .remove = omap_dmic_remove,
  446 + .capture = {
  447 + .channels_min = 2,
  448 + .channels_max = 6,
  449 + .rates = SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
  450 + .formats = SNDRV_PCM_FMTBIT_S32_LE,
  451 + },
  452 + .ops = &omap_dmic_dai_ops,
  453 +};
  454 +
  455 +static __devinit int asoc_dmic_probe(struct platform_device *pdev)
  456 +{
  457 + struct omap_dmic *dmic;
  458 + struct resource *res;
  459 + int ret;
  460 +
  461 + dmic = devm_kzalloc(&pdev->dev, sizeof(struct omap_dmic), GFP_KERNEL);
  462 + if (!dmic)
  463 + return -ENOMEM;
  464 +
  465 + platform_set_drvdata(pdev, dmic);
  466 + dmic->dev = &pdev->dev;
  467 + dmic->sysclk = OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS;
  468 +
  469 + mutex_init(&dmic->mutex);
  470 +
  471 + dmic->fclk = clk_get(dmic->dev, "dmic_fck");
  472 + if (IS_ERR(dmic->fclk)) {
  473 + dev_err(dmic->dev, "cant get dmic_fck\n");
  474 + return -ENODEV;
  475 + }
  476 +
  477 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
  478 + if (!res) {
  479 + dev_err(dmic->dev, "invalid dma memory resource\n");
  480 + ret = -ENODEV;
  481 + goto err_put_clk;
  482 + }
  483 + omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG;
  484 +
  485 + res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
  486 + if (!res) {
  487 + dev_err(dmic->dev, "invalid dma resource\n");
  488 + ret = -ENODEV;
  489 + goto err_put_clk;
  490 + }
  491 + omap_dmic_dai_dma_params.dma_req = res->start;
  492 +
  493 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
  494 + if (!res) {
  495 + dev_err(dmic->dev, "invalid memory resource\n");
  496 + ret = -ENODEV;
  497 + goto err_put_clk;
  498 + }
  499 +
  500 + if (!devm_request_mem_region(&pdev->dev, res->start,
  501 + resource_size(res), pdev->name)) {
  502 + dev_err(dmic->dev, "memory region already claimed\n");
  503 + ret = -ENODEV;
  504 + goto err_put_clk;
  505 + }
  506 +
  507 + dmic->io_base = devm_ioremap(&pdev->dev, res->start,
  508 + resource_size(res));
  509 + if (!dmic->io_base) {
  510 + ret = -ENOMEM;
  511 + goto err_put_clk;
  512 + }
  513 +
  514 + ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai);
  515 + if (ret)
  516 + goto err_put_clk;
  517 +
  518 + return 0;
  519 +
  520 +err_put_clk:
  521 + clk_put(dmic->fclk);
  522 + return ret;
  523 +}
  524 +
  525 +static int __devexit asoc_dmic_remove(struct platform_device *pdev)
  526 +{
  527 + struct omap_dmic *dmic = platform_get_drvdata(pdev);
  528 +
  529 + snd_soc_unregister_dai(&pdev->dev);
  530 + clk_put(dmic->fclk);
  531 +
  532 + return 0;
  533 +}
  534 +
  535 +static struct platform_driver asoc_dmic_driver = {
  536 + .driver = {
  537 + .name = "omap-dmic",
  538 + .owner = THIS_MODULE,
  539 + },
  540 + .probe = asoc_dmic_probe,
  541 + .remove = __devexit_p(asoc_dmic_remove),
  542 +};
  543 +
  544 +module_platform_driver(asoc_dmic_driver);
  545 +
  546 +MODULE_ALIAS("platform:omap-dmic");
  547 +MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
  548 +MODULE_DESCRIPTION("OMAP DMIC ASoC Interface");
  549 +MODULE_LICENSE("GPL");
sound/soc/omap/omap-dmic.h
  1 +/*
  2 + * omap-dmic.h -- OMAP Digital Microphone Controller
  3 + *
  4 + * This program is free software; you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License version 2 as
  6 + * published by the Free Software Foundation.
  7 + */
  8 +
  9 +#ifndef _OMAP_DMIC_H
  10 +#define _OMAP_DMIC_H
  11 +
  12 +#define OMAP_DMIC_REVISION_REG 0x00
  13 +#define OMAP_DMIC_SYSCONFIG_REG 0x10
  14 +#define OMAP_DMIC_IRQSTATUS_RAW_REG 0x24
  15 +#define OMAP_DMIC_IRQSTATUS_REG 0x28
  16 +#define OMAP_DMIC_IRQENABLE_SET_REG 0x2C
  17 +#define OMAP_DMIC_IRQENABLE_CLR_REG 0x30
  18 +#define OMAP_DMIC_IRQWAKE_EN_REG 0x34
  19 +#define OMAP_DMIC_DMAENABLE_SET_REG 0x38
  20 +#define OMAP_DMIC_DMAENABLE_CLR_REG 0x3C
  21 +#define OMAP_DMIC_DMAWAKEEN_REG 0x40
  22 +#define OMAP_DMIC_CTRL_REG 0x44
  23 +#define OMAP_DMIC_DATA_REG 0x48
  24 +#define OMAP_DMIC_FIFO_CTRL_REG 0x4C
  25 +#define OMAP_DMIC_FIFO_DMIC1R_DATA_REG 0x50
  26 +#define OMAP_DMIC_FIFO_DMIC1L_DATA_REG 0x54
  27 +#define OMAP_DMIC_FIFO_DMIC2R_DATA_REG 0x58
  28 +#define OMAP_DMIC_FIFO_DMIC2L_DATA_REG 0x5C
  29 +#define OMAP_DMIC_FIFO_DMIC3R_DATA_REG 0x60
  30 +#define OMAP_DMIC_FIFO_DMIC3L_DATA_REG 0x64
  31 +
  32 +/* IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR bit fields */
  33 +#define OMAP_DMIC_IRQ (1 << 0)
  34 +#define OMAP_DMIC_IRQ_FULL (1 << 1)
  35 +#define OMAP_DMIC_IRQ_ALMST_EMPTY (1 << 2)
  36 +#define OMAP_DMIC_IRQ_EMPTY (1 << 3)
  37 +#define OMAP_DMIC_IRQ_MASK 0x07
  38 +
  39 +/* DMIC_DMAENABLE bit fields */
  40 +#define OMAP_DMIC_DMA_ENABLE 0x1
  41 +
  42 +/* DMIC_CTRL bit fields */
  43 +#define OMAP_DMIC_UP1_ENABLE (1 << 0)
  44 +#define OMAP_DMIC_UP2_ENABLE (1 << 1)
  45 +#define OMAP_DMIC_UP3_ENABLE (1 << 2)
  46 +#define OMAP_DMIC_UP_ENABLE_MASK 0x7
  47 +#define OMAP_DMIC_FORMAT (1 << 3)
  48 +#define OMAP_DMIC_POLAR1 (1 << 4)
  49 +#define OMAP_DMIC_POLAR2 (1 << 5)
  50 +#define OMAP_DMIC_POLAR3 (1 << 6)
  51 +#define OMAP_DMIC_POLAR_MASK (0x7 << 4)
  52 +#define OMAP_DMIC_CLK_DIV(x) (((x) & 0x7) << 7)
  53 +#define OMAP_DMIC_CLK_DIV_MASK (0x7 << 7)
  54 +#define OMAP_DMIC_RESET (1 << 10)
  55 +
  56 +#define OMAP_DMICOUTFORMAT_LJUST (0 << 3)
  57 +#define OMAP_DMICOUTFORMAT_RJUST (1 << 3)
  58 +
  59 +/* DMIC_FIFO_CTRL bit fields */
  60 +#define OMAP_DMIC_THRES_MAX 0xF
  61 +
  62 +enum omap_dmic_clk {
  63 + OMAP_DMIC_SYSCLK_PAD_CLKS, /* PAD_CLKS */
  64 + OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS, /* SLIMBUS_CLK */
  65 + OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS, /* DMIC_SYNC_MUX_CLK */
  66 + OMAP_DMIC_ABE_DMIC_CLK, /* abe_dmic_clk */
  67 +};
  68 +
  69 +#endif