[alsa-devel] [PATCH v4 4/7] ASoC: sirf: Add SiRF I2S driver
RongJun Ying
rjying at gmail.com
Wed Feb 26 07:04:52 CET 2014
From: Rongjun Ying <rongjun.ying at csr.com>
Signed-off-by: Rongjun Ying <rongjun.ying at csr.com>
---
-v4:
1. Add binding document.
2. Use MMIO regmap.
.../devicetree/bindings/sound/sirf-i2s.txt | 27 ++
sound/soc/sirf/Kconfig | 4 +
sound/soc/sirf/Makefile | 2 +
sound/soc/sirf/sirf-i2s.c | 438 ++++++++++++++++++++
sound/soc/sirf/sirf-i2s.h | 88 ++++
5 files changed, 559 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/sirf-i2s.txt
create mode 100644 sound/soc/sirf/sirf-i2s.c
create mode 100644 sound/soc/sirf/sirf-i2s.h
diff --git a/Documentation/devicetree/bindings/sound/sirf-i2s.txt b/Documentation/devicetree/bindings/sound/sirf-i2s.txt
new file mode 100644
index 0000000..cbff8a8
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/sirf-i2s.txt
@@ -0,0 +1,27 @@
+* SiRF SoC I2S module
+
+Required properties:
+- compatible: "sirf,prima2-i2s"
+- reg: Base address and size entries:
+- dmas: List of DMA controller phandle and DMA request line ordered pairs.
+- dma-names: Identifier string for each DMA request line in the dmas property.
+ These strings correspond 1:1 with the ordered pairs in dmas.
+
+ One of the DMA channels will be responsible for transmission (should be
+ named "tx") and one for reception (should be named "rx").
+
+- clocks: I2S controller clock source
+- pinctrl-names: Must contain a "default" entry.
+- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
+
+Example:
+
+i2s: i2s at b0040000 {
+ compatible = "sirf,prima2-i2s";
+ reg = <0xb0040000 0x10000>;
+ dmas = <&dmac1 6>, <&dmac1 12>;
+ dma-names = "rx", "tx";
+ clocks = <&clks 27>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s_pins_a>;
+};
diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig
index a8e083b..2fca80a 100644
--- a/sound/soc/sirf/Kconfig
+++ b/sound/soc/sirf/Kconfig
@@ -12,3 +12,7 @@ config SND_SOC_SIRF_AUDIO
depends on SND_SOC_SIRF
select SND_SOC_SIRF_AUDIO_CODEC
select SND_SOC_SIRF_AUDIO_PORT
+
+config SND_SOC_SIRF_I2S
+ select REGMAP_MMIO
+ tristate
diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile
index 4eea904..2de3cf8 100644
--- a/sound/soc/sirf/Makefile
+++ b/sound/soc/sirf/Makefile
@@ -1,5 +1,7 @@
snd-soc-sirf-audio-port-objs := sirf-audio-port.o
snd-soc-sirf-audio-objs := sirf-audio.o
+snd-soc-sirf-i2s-objs := sirf-i2s.o
obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o
obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o
+obj-$(CONFIG_SND_SOC_SIRF_I2S) += snd-soc-sirf-i2s.o
diff --git a/sound/soc/sirf/sirf-i2s.c b/sound/soc/sirf/sirf-i2s.c
new file mode 100644
index 0000000..6da4d61
--- /dev/null
+++ b/sound/soc/sirf/sirf-i2s.c
@@ -0,0 +1,438 @@
+/*
+ * SiRF I2S driver
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
+
+#include "sirf-i2s.h"
+
+struct sirf_i2s {
+ struct regmap *regmap;
+ struct clk *clk;
+ u32 i2s_ctrl;
+ u32 i2s_ctrl_tx_rx_en;
+ bool master;
+ int ext_clk;
+ int src_clk_rate;
+ struct snd_dmaengine_dai_dma_data playback_dma_data;
+ struct snd_dmaengine_dai_dma_data capture_dma_data;
+};
+
+static int sirf_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+ struct sirf_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+ snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data,
+ &i2s->capture_dma_data);
+ return 0;
+}
+
+static inline void sirf_i2s_tx_enable(struct sirf_i2s *i2s)
+{
+ /* First start the FIFO, then enable the tx/rx */
+ regmap_update_bits(i2s->regmap, AUDIO_CTRL_I2S_TXFIFO_OP,
+ AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
+ regmap_update_bits(i2s->regmap, AUDIO_CTRL_I2S_TXFIFO_OP,
+ AUDIO_FIFO_START, AUDIO_FIFO_RESET);
+ regmap_update_bits(i2s->regmap, AUDIO_CTRL_I2S_TX_RX_EN,
+ I2S_TX_ENABLE | I2S_DOUT_OE,
+ I2S_TX_ENABLE | I2S_DOUT_OE);
+}
+
+static inline void sirf_i2s_tx_disable(struct sirf_i2s *i2s)
+{
+ regmap_update_bits(i2s->regmap, AUDIO_CTRL_I2S_TX_RX_EN,
+ I2S_TX_ENABLE, ~I2S_TX_ENABLE);
+ /* First disable the tx/rx, then stop the FIFO */
+ regmap_write(i2s->regmap, AUDIO_CTRL_I2S_TXFIFO_OP, 0);
+}
+
+static inline void sirf_i2s_rx_enable(struct sirf_i2s *i2s)
+{
+ /* First start the FIFO, then enable the tx/rx */
+ regmap_update_bits(i2s->regmap, AUDIO_CTRL_I2S_RXFIFO_OP,
+ AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
+ regmap_update_bits(i2s->regmap, AUDIO_CTRL_I2S_RXFIFO_OP,
+ AUDIO_FIFO_START, AUDIO_FIFO_START);
+ regmap_update_bits(i2s->regmap, AUDIO_CTRL_I2S_TX_RX_EN,
+ I2S_RX_ENABLE, I2S_RX_ENABLE);
+}
+
+static inline void sirf_i2s_rx_disable(struct sirf_i2s *i2s)
+{
+ regmap_update_bits(i2s->regmap, AUDIO_CTRL_I2S_TX_RX_EN,
+ I2S_RX_ENABLE, ~I2S_RX_ENABLE);
+ /* First disable the tx/rx, then stop the FIFO */
+ regmap_write(i2s->regmap, AUDIO_CTRL_I2S_RXFIFO_OP, 0);
+}
+
+static int sirf_i2s_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct sirf_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+ int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (playback)
+ sirf_i2s_tx_enable(i2s);
+ else
+ sirf_i2s_rx_enable(i2s);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (playback)
+ sirf_i2s_tx_disable(i2s);
+ else
+ sirf_i2s_rx_disable(i2s);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int sirf_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct sirf_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+ u32 i2s_ctrl;
+ u32 i2s_tx_rx_ctrl;
+ u32 left_len, frame_len;
+ int channels = params_channels(params);
+ u32 bitclk;
+ u32 bclk_div;
+ u32 div;
+
+ /*
+ * SiRFSoC I2S controller only support 2 and 6 channells output.
+ * I2S_SIX_CHANNELS bit clear: select 2 channels mode.
+ * I2S_SIX_CHANNELS bit set: select 6 channels mode.
+ */
+ regmap_read(i2s->regmap, AUDIO_CTRL_I2S_CTRL, &i2s_ctrl);
+ regmap_read(i2s->regmap, AUDIO_CTRL_I2S_TX_RX_EN, &i2s_tx_rx_ctrl);
+ switch (channels) {
+ case 2:
+ i2s_ctrl &= ~I2S_SIX_CHANNELS;
+ break;
+ case 6:
+ i2s_ctrl |= I2S_SIX_CHANNELS;
+ break;
+ default:
+ dev_err(dai->dev, "%d channels unsupported\n", channels);
+ return -EINVAL;
+ }
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ left_len = 8;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ left_len = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ left_len = 24;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ left_len = 32;
+ break;
+ default:
+ dev_err(dai->dev, "Format unsupported\n");
+ return -EINVAL;
+ }
+
+ frame_len = left_len * 2;
+ i2s_ctrl &= ~(I2S_L_CHAN_LEN_MASK | I2S_FRAME_LEN_MASK);
+ /* Fill the actual len - 1 */
+ i2s_ctrl |= ((frame_len - 1) << I2S_FRAME_LEN_SHIFT)
+ | ((left_len - 1) << I2S_L_CHAN_LEN_SHIFT)
+ | (0 << I2S_MCLK_DIV_SHIFT) | (3 << I2S_BITCLK_DIV_SHIFT);
+
+ if (i2s->master) {
+ i2s_ctrl &= ~I2S_SLAVE_MODE;
+ i2s_tx_rx_ctrl |= I2S_MCLK_EN;
+ bitclk = params_rate(params) * frame_len;
+ div = i2s->src_clk_rate / bitclk;
+ /* MCLK divide-by-2 from source clk */
+ div /= 2;
+ bclk_div = div / 2 - 1;
+ i2s_ctrl |= (bclk_div << I2S_BITCLK_DIV_SHIFT);
+ /*
+ * MCLK coefficient must set to 0, means
+ * divide-by-two from reference clock.
+ */
+ i2s_ctrl &= ~I2S_MCLK_DIV_MASK;
+ } else {
+ i2s_ctrl |= I2S_SLAVE_MODE;
+ i2s_tx_rx_ctrl &= ~I2S_MCLK_EN;
+ }
+
+ if (i2s->ext_clk)
+ i2s_tx_rx_ctrl |= I2S_REF_CLK_SEL_EXT;
+ else
+ i2s_tx_rx_ctrl &= ~I2S_REF_CLK_SEL_EXT;
+
+ regmap_write(i2s->regmap, AUDIO_CTRL_I2S_CTRL, i2s_ctrl);
+ regmap_write(i2s->regmap, AUDIO_CTRL_I2S_TX_RX_EN, i2s_tx_rx_ctrl);
+ regmap_update_bits(i2s->regmap, AUDIO_CTRL_MODE_SEL,
+ I2S_MODE, I2S_MODE);
+
+ return 0;
+}
+
+static int sirf_i2s_set_dai_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ struct sirf_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ i2s->master = false;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ i2s->master = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ default:
+ dev_err(dai->dev, "Only I2S format supported\n");
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ default:
+ dev_err(dai->dev, "Only normal bit clock, normal frame clock supported\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int sirf_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id,
+ int src_rate)
+{
+ struct sirf_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+ switch (div_id) {
+ case SIRF_I2S_EXT_CLK:
+ i2s->ext_clk = 1;
+ break;
+ case SIRF_I2S_PWM_CLK:
+ i2s->ext_clk = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ i2s->src_clk_rate = src_rate;
+ return 0;
+}
+
+struct snd_soc_dai_ops sirfsoc_i2s_dai_ops = {
+ .trigger = sirf_i2s_trigger,
+ .hw_params = sirf_i2s_hw_params,
+ .set_fmt = sirf_i2s_set_dai_fmt,
+ .set_clkdiv = sirf_i2s_set_clkdiv,
+};
+
+static struct snd_soc_dai_driver sirf_i2s_dai = {
+ .probe = sirf_i2s_dai_probe,
+ .name = "sirf-i2s",
+ .id = 0,
+ .playback = {
+ .stream_name = "SiRF I2S Playback",
+ .channels_min = 2,
+ .channels_max = 6,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .capture = {
+ .stream_name = "SiRF I2S Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &sirfsoc_i2s_dai_ops,
+};
+
+#ifdef CONFIG_PM_RUNTIME
+static int sirf_i2s_runtime_suspend(struct device *dev)
+{
+ struct sirf_i2s *i2s = dev_get_drvdata(dev);
+ clk_disable_unprepare(i2s->clk);
+
+ return 0;
+}
+
+static int sirf_i2s_runtime_resume(struct device *dev)
+{
+ struct sirf_i2s *i2s = dev_get_drvdata(dev);
+ int ret;
+ ret = clk_prepare_enable(i2s->clk);
+ if (ret)
+ return ret;
+ return ret;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int sirf_i2s_suspend(struct device *dev)
+{
+ struct sirf_i2s *i2s = dev_get_drvdata(dev);
+
+ if (!pm_runtime_status_suspended(dev)) {
+ regmap_read(i2s->regmap, AUDIO_CTRL_I2S_CTRL, &i2s->i2s_ctrl);
+ regmap_read(i2s->regmap, AUDIO_CTRL_I2S_TX_RX_EN,
+ &i2s->i2s_ctrl_tx_rx_en);
+ sirf_i2s_runtime_suspend(dev);
+ }
+ return 0;
+}
+
+static int sirf_i2s_resume(struct device *dev)
+{
+ struct sirf_i2s *i2s = dev_get_drvdata(dev);
+ int ret;
+ if (!pm_runtime_status_suspended(dev)) {
+ ret = sirf_i2s_runtime_resume(dev);
+ if (ret)
+ return ret;
+ regmap_update_bits(i2s->regmap, AUDIO_CTRL_MODE_SEL,
+ I2S_MODE, I2S_MODE);
+ regmap_write(i2s->regmap, AUDIO_CTRL_I2S_CTRL, i2s->i2s_ctrl);
+ /* Restore MCLK enable and reference clock select bits. */
+ i2s->i2s_ctrl_tx_rx_en &= (I2S_MCLK_EN | I2S_REF_CLK_SEL_EXT);
+ regmap_write(i2s->regmap, AUDIO_CTRL_I2S_TX_RX_EN,
+ i2s->i2s_ctrl_tx_rx_en);
+
+ regmap_write(i2s->regmap, AUDIO_CTRL_I2S_TXFIFO_INT_MSK, 0);
+ regmap_write(i2s->regmap, AUDIO_CTRL_I2S_RXFIFO_INT_MSK, 0);
+ }
+
+ return 0;
+}
+#endif
+
+static const struct snd_soc_component_driver sirf_i2s_component = {
+ .name = "sirf-i2s",
+};
+
+static const struct regmap_config sirf_i2s_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = AUDIO_CTRL_I2S_RXFIFO_INT_MSK,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int sirf_i2s_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct sirf_i2s *i2s;
+ void __iomem *base;
+ struct resource *mem_res;
+
+ i2s = devm_kzalloc(&pdev->dev, sizeof(struct sirf_i2s),
+ GFP_KERNEL);
+ if (!i2s)
+ return -ENOMEM;
+
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem_res) {
+ dev_err(&pdev->dev, "no mem resource?\n");
+ return -ENODEV;
+ }
+
+ base = devm_ioremap(&pdev->dev, mem_res->start,
+ resource_size(mem_res));
+ if (base == NULL)
+ return -ENOMEM;
+
+ i2s->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &sirf_i2s_regmap_config);
+ if (IS_ERR(i2s->regmap))
+ return PTR_ERR(i2s->regmap);
+
+ i2s->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(i2s->clk)) {
+ dev_err(&pdev->dev, "Get clock failed.\n");
+ ret = PTR_ERR(i2s->clk);
+ return ret;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+
+ ret = devm_snd_soc_register_component(&pdev->dev, &sirf_i2s_component,
+ &sirf_i2s_dai, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "Register Audio SoC dai failed.\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, i2s);
+ return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+}
+
+static int sirf_i2s_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+ return 0;
+}
+
+static const struct of_device_id sirf_i2s_of_match[] = {
+ { .compatible = "sirf,prima2-i2s", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sirf_i2s_of_match);
+
+static const struct dev_pm_ops sirf_i2s_pm_ops = {
+ SET_RUNTIME_PM_OPS(sirf_i2s_runtime_suspend, sirf_i2s_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(sirf_i2s_suspend, sirf_i2s_resume)
+};
+
+static struct platform_driver sirf_i2s_driver = {
+ .driver = {
+ .name = "sirf-i2s",
+ .owner = THIS_MODULE,
+ .of_match_table = sirf_i2s_of_match,
+ .pm = &sirf_i2s_pm_ops,
+ },
+ .probe = sirf_i2s_probe,
+ .remove = sirf_i2s_remove,
+};
+
+module_platform_driver(sirf_i2s_driver);
+
+MODULE_DESCRIPTION("SiRF SoC I2S driver");
+MODULE_AUTHOR("RongJun Ying <Rongjun.Ying at csr.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/sirf/sirf-i2s.h b/sound/soc/sirf/sirf-i2s.h
new file mode 100644
index 0000000..3879fe5
--- /dev/null
+++ b/sound/soc/sirf/sirf-i2s.h
@@ -0,0 +1,88 @@
+/*
+ * SiRF I2S controllers define
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef _SIRF_I2S_H
+#define _SIRF_I2S_H
+
+#define AUDIO_CTRL_TX_FIFO_LEVEL_CHECK_MASK 0x3F
+#define AUDIO_CTRL_TX_FIFO_SC_OFFSET 0
+#define AUDIO_CTRL_TX_FIFO_LC_OFFSET 10
+#define AUDIO_CTRL_TX_FIFO_HC_OFFSET 20
+
+#define TX_FIFO_SC(x) (((x) & AUDIO_CTRL_TX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_CTRL_TX_FIFO_SC_OFFSET)
+#define TX_FIFO_LC(x) (((x) & AUDIO_CTRL_TX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_CTRL_TX_FIFO_LC_OFFSET)
+#define TX_FIFO_HC(x) (((x) & AUDIO_CTRL_TX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_CTRL_TX_FIFO_HC_OFFSET)
+
+#define AUDIO_CTRL_RX_FIFO_LEVEL_CHECK_MASK 0x0F
+#define AUDIO_CTRL_RX_FIFO_SC_OFFSET 0
+#define AUDIO_CTRL_RX_FIFO_LC_OFFSET 10
+#define AUDIO_CTRL_RX_FIFO_HC_OFFSET 20
+
+#define RX_FIFO_SC(x) (((x) & AUDIO_CTRL_RX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_CTRL_RX_FIFO_SC_OFFSET)
+#define RX_FIFO_LC(x) (((x) & AUDIO_CTRL_RX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_CTRL_RX_FIFO_LC_OFFSET)
+#define RX_FIFO_HC(x) (((x) & AUDIO_CTRL_RX_FIFO_LEVEL_CHECK_MASK) \
+ << AUDIO_CTRL_RX_FIFO_HC_OFFSET)
+
+#define AUDIO_CTRL_MODE_SEL (0x0000)
+#define AUDIO_CTRL_I2S_CTRL (0x0020)
+#define AUDIO_CTRL_I2S_TX_RX_EN (0x0024)
+
+#define AUDIO_CTRL_I2S_TXFIFO_OP (0x0040)
+#define AUDIO_CTRL_I2S_TXFIFO_LEV_CHK (0x0044)
+#define AUDIO_CTRL_I2S_TXFIFO_STS (0x0048)
+#define AUDIO_CTRL_I2S_TXFIFO_INT (0x004C)
+#define AUDIO_CTRL_I2S_TXFIFO_INT_MSK (0x0050)
+
+#define AUDIO_CTRL_I2S_RXFIFO_OP (0x00B8)
+#define AUDIO_CTRL_I2S_RXFIFO_LEV_CHK (0x00BC)
+#define AUDIO_CTRL_I2S_RXFIFO_STS (0x00C0)
+#define AUDIO_CTRL_I2S_RXFIFO_INT (0x00C4)
+#define AUDIO_CTRL_I2S_RXFIFO_INT_MSK (0x00C8)
+
+#define I2S_MODE (1<<0)
+
+#define I2S_LOOP_BACK (1<<3)
+#define I2S_MCLK_DIV_SHIFT 15
+#define I2S_MCLK_DIV_MASK (0x1FF<<I2S_MCLK_DIV_SHIFT)
+#define I2S_BITCLK_DIV_SHIFT 24
+#define I2S_BITCLK_DIV_MASK (0xFF<<I2S_BITCLK_DIV_SHIFT)
+
+#define I2S_MCLK_EN (1<<2)
+#define I2S_REF_CLK_SEL_EXT (1<<3)
+#define I2S_DOUT_OE (1<<4)
+#define i2s_R2X_LP_TO_TX0 (1<<30)
+#define i2s_R2X_LP_TO_TX1 (2<<30)
+#define i2s_R2X_LP_TO_TX2 (3<<30)
+
+#define AUDIO_FIFO_START (1 << 0)
+#define AUDIO_FIFO_RESET (1 << 1)
+
+#define AUDIO_FIFO_FULL (1 << 0)
+#define AUDIO_FIFO_EMPTY (1 << 1)
+#define AUDIO_FIFO_OFLOW (1 << 2)
+#define AUDIO_FIFO_UFLOW (1 << 3)
+
+#define I2S_RX_ENABLE (1 << 0)
+#define I2S_TX_ENABLE (1 << 1)
+
+/* Codec I2S Control Register defines */
+#define I2S_SLAVE_MODE (1 << 0)
+#define I2S_SIX_CHANNELS (1 << 1)
+#define I2S_L_CHAN_LEN_SHIFT (4)
+#define I2S_L_CHAN_LEN_MASK (0x1f << I2S_L_CHAN_LEN_SHIFT)
+#define I2S_FRAME_LEN_SHIFT (9)
+#define I2S_FRAME_LEN_MASK (0x3f << I2S_FRAME_LEN_SHIFT)
+
+#define SIRF_I2S_EXT_CLK 0x0
+#define SIRF_I2S_PWM_CLK 0x1
+#endif /*__SIRF_I2S_H*/
--
1.7.5.4
More information about the Alsa-devel
mailing list