summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2011-01-19 09:09:01 +0530
committerVarun Colbert <vcolbert@nvidia.com>2011-02-03 19:14:13 -0800
commit950c23d0bd1ffc19d01416fe2bb0e814233ce68e (patch)
treeb3ccae94787d2e7c06f39457a5cd6c332091c1ec
parent782c58b61982497762a852466163dd15d1bbe30e (diff)
i2s: Support DSP mode in i2s driver
Change-Id: I6e60f06a0487a03553300130ef36dbe28de0139d Reviewed-on: http://git-master/r/16196 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra2_i2s.h107
-rw-r--r--arch/arm/mach-tegra/tegra2_i2s.c78
2 files changed, 185 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/include/mach/tegra2_i2s.h b/arch/arm/mach-tegra/include/mach/tegra2_i2s.h
index 45929f20f0e2..46846c1ef834 100644
--- a/arch/arm/mach-tegra/include/mach/tegra2_i2s.h
+++ b/arch/arm/mach-tegra/include/mach/tegra2_i2s.h
@@ -157,6 +157,109 @@
#define I2S_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS (I2S_FIFO_ATN_LVL_EIGHT_SLOTS << I2S_FIFO1_ATN_LVL_SHIFT)
#define I2S_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS (I2S_FIFO_ATN_LVL_TWELVE_SLOTS << I2S_FIFO1_ATN_LVL_SHIFT)
+/*
+ * I2S_I2S_PCM_CTRL_0
+ */
+#define I2S_PCM_TRM_EDGE_POS_EDGE_NO_HIGHZ 0
+#define I2S_PCM_TRM_EDGE_POS_EDGE_HIGHZ 1
+#define I2S_PCM_TRM_EDGE_NEG_EDGE_NO_HIGHZ 2
+#define I2S_PCM_TRM_EDGE_NEG_EDGE_HIGHZ 3
+#define I2S_PCM_TRM_EDGE_CTRL_SHIFT 9
+
+#define I2S_I2S_PCM_TRM_EDGE_CTRL_MASK \
+ (3 << I2S_PCM_TRM_EDGE_CTRL_SHIFT)
+#define I2S_I2S_PCM_TRM_EDGE_POS_EDGE_NO_HIGHZ \
+ (I2S_PCM_TRM_EDGE_POS_EDGE_NO_HIGHZ \
+ << I2S_PCM_TRM_EDGE_CTRL_SHIFT)
+#define I2S_I2S_PCM_TRM_EDGE_POS_EDGE_HIGHZ \
+ (I2S_PCM_TRM_EDGE_POS_EDGE_HIGHZ \
+ << I2S_PCM_TRM_EDGE_CTRL_SHIFT)
+#define I2S_I2S_PCM_TRM_EDGE_NEG_EDGE_NO_HIGHZ \
+ (I2S_PCM_TRM_EDGE_NEG_EDGE_NO_HIGHZ \
+ << I2S_PCM_TRM_EDGE_CTRL_SHIFT)
+#define I2S_I2S_PCM_TRM_EDGE_NEG_EDGE_HIGHZ \
+ (I2S_PCM_TRM_EDGE_NEG_EDGE_HIGHZ \
+ << I2S_PCM_TRM_EDGE_CTRL_SHIFT)
+
+#define I2S_PCM_TRM_MASK_BITS_ZERO 0
+#define I2S_PCM_TRM_MASK_BITS_ONE 1
+#define I2S_PCM_TRM_MASK_BITS_TWO 2
+#define I2S_PCM_TRM_MASK_BITS_THREE 3
+#define I2S_PCM_TRM_MASK_BITS_FOUR 4
+#define I2S_PCM_TRM_MASK_BITS_FIVE 5
+#define I2S_PCM_TRM_MASK_BITS_SIX 6
+#define I2S_PCM_TRM_MASK_BITS_SEVEN 7
+#define I2S_PCM_TRM_MASK_BITS_SHIFT 6
+
+#define I2S_I2S_PCM_TRM_MASK_BITS_MASK \
+ (7 << I2S_PCM_TRM_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_TRM_MASK_BITS_ZERO \
+ (I2S_PCM_TRM_MASK_BITS_ZERO \
+ << I2S_PCM_TRM_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_TRM_MASK_BITS_ONE \
+ (I2S_PCM_TRM_MASK_BITS_ONE \
+ << I2S_PCM_TRM_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_TRM_MASK_BITS_TWO \
+ (I2S_PCM_TRM_MASK_BITS_TWO \
+ << I2S_PCM_TRM_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_TRM_MASK_BITS_THREE \
+ (I2S_PCM_TRM_MASK_BITS_THREE \
+ << I2S_PCM_TRM_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_TRM_MASK_BITS_FOUR \
+ (I2S_PCM_TRM_MASK_BITS_FOUR \
+ << I2S_PCM_TRM_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_TRM_MASK_BITS_FIVE \
+ (I2S_PCM_TRM_MASK_BITS_FIVE \
+ << I2S_PCM_TRM_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_TRM_MASK_BITS_SIX \
+ (I2S_PCM_TRM_MASK_BITS_SIX \
+ << I2S_PCM_TRM_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_TRM_MASK_BITS_SEVEN \
+ (I2S_PCM_TRM_MASK_BITS_SEVEN \
+ << I2S_PCM_TRM_MASK_BITS_SHIFT)
+
+#define I2S_I2S_PCM_CTRL_FSYNC_PCM_CTRL (1<<5)
+#define I2S_I2S_PCM_CTRL_TRM_MODE (1<<4)
+
+#define I2S_PCM_RCV_MASK_BITS_ZERO 0
+#define I2S_PCM_RCV_MASK_BITS_ONE 1
+#define I2S_PCM_RCV_MASK_BITS_TWO 2
+#define I2S_PCM_RCV_MASK_BITS_THREE 3
+#define I2S_PCM_RCV_MASK_BITS_FOUR 4
+#define I2S_PCM_RCV_MASK_BITS_FIVE 5
+#define I2S_PCM_RCV_MASK_BITS_SIX 6
+#define I2S_PCM_RCV_MASK_BITS_SEVEN 7
+#define I2S_PCM_RCV_MASK_BITS_SHIFT 1
+
+#define I2S_I2S_PCM_RCV_MASK_BITS_MASK \
+ (7 << I2S_PCM_RCV_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_RCV_MASK_BITS_ZERO \
+ (I2S_PCM_RCV_MASK_BITS_ZERO \
+ << I2S_PCM_RCV_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_RCV_MASK_BITS_ONE \
+ (I2S_PCM_RCV_MASK_BITS_ONE \
+ << I2S_PCM_RCV_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_RCV_MASK_BITS_TWO \
+ (I2S_PCM_RCV_MASK_BITS_TWO \
+ << I2S_PCM_RCV_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_RCV_MASK_BITS_THREE \
+ (I2S_PCM_RCV_MASK_BITS_THREE \
+ << I2S_PCM_RCV_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_RCV_MASK_BITS_FOUR \
+ (I2S_PCM_RCV_MASK_BITS_FOUR \
+ << I2S_PCM_RCV_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_RCV_MASK_BITS_FIVE \
+ (I2S_PCM_RCV_MASK_BITS_FIVE \
+ << I2S_PCM_RCV_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_RCV_MASK_BITS_SIX \
+ (I2S_PCM_RCV_MASK_BITS_SIX \
+ << I2S_PCM_RCV_MASK_BITS_SHIFT)
+#define I2S_I2S_PCM_RCV_MASK_BITS_SEVEN \
+ (I2S_PCM_RCV_MASK_BITS_SEVEN \
+ << I2S_PCM_RCV_MASK_BITS_SHIFT)
+
+#define I2S_I2S_PCM_CTRL_RCV_MODE (1<<0)
+
struct i2s_runtime_data {
int i2s_ctrl_0;
int i2s_status_0;
@@ -184,6 +287,10 @@ int i2s_set_bit_format(int ifc, unsigned format);
int i2s_set_bit_size(int ifc, unsigned bit_size);
int i2s_set_fifo_format(int ifc, unsigned fmt);
void i2s_set_left_right_control_polarity(int ifc, int high_low);
+int i2s_set_pcm_edge_mode(int ifc, unsigned edge_mode);
+int i2s_set_pcm_mask_bits(int ifc, unsigned mask_bits, int tx);
+void i2s_set_pcm_fsync_width(int ifc, int fsync_long);
+void i2s_enable_pcm_mode(int ifc, int enable);
void i2s_set_fifo_irq_on_err(int ifc, int fifo, int on);
void i2s_set_fifo_irq_on_qe(int ifc, int fifo, int on);
void i2s_enable_fifos(int ifc, int on);
diff --git a/arch/arm/mach-tegra/tegra2_i2s.c b/arch/arm/mach-tegra/tegra2_i2s.c
index f721f6d313a9..de50df917048 100644
--- a/arch/arm/mach-tegra/tegra2_i2s.c
+++ b/arch/arm/mach-tegra/tegra2_i2s.c
@@ -240,6 +240,13 @@ int i2s_set_bit_format(int ifc, unsigned fmt)
val |= fmt << I2S_BIT_FORMAT_SHIFT;
i2s_writel(ifc, val, I2S_I2S_CTRL_0);
+
+ if (fmt == I2S_BIT_FORMAT_DSP) {
+ i2s_enable_pcm_mode(ifc, 1);
+ }
+ else {
+ i2s_enable_pcm_mode(ifc, 0);
+ }
return 0;
}
@@ -296,6 +303,77 @@ void i2s_set_left_right_control_polarity(int ifc, int high_low)
i2s_writel(ifc, val, I2S_I2S_CTRL_0);
}
+void i2s_enable_pcm_mode(int ifc, int on)
+{
+ u32 val;
+
+ check_ifc(ifc);
+
+ val = i2s_readl(ifc, I2S_I2S_PCM_CTRL_0);
+ val &= ~(I2S_I2S_PCM_CTRL_TRM_MODE | I2S_I2S_PCM_CTRL_RCV_MODE);
+ val |= on ? (I2S_I2S_PCM_CTRL_TRM_MODE | I2S_I2S_PCM_CTRL_RCV_MODE) : 0;
+ i2s_writel(ifc, val, I2S_I2S_PCM_CTRL_0);
+}
+
+int i2s_set_pcm_edge_mode(int ifc, unsigned edge_mode)
+{
+ u32 val;
+
+ check_ifc(ifc, -EINVAL);
+
+ if (edge_mode > I2S_I2S_PCM_TRM_EDGE_NEG_EDGE_HIGHZ) {
+ pr_err("%s: invalid dsp edge mode \n", __func__);
+ return -EINVAL;
+ }
+
+ val = i2s_readl(ifc, I2S_I2S_PCM_CTRL_0);
+ val &= ~I2S_I2S_PCM_TRM_EDGE_CTRL_MASK;
+ val |= edge_mode << I2S_PCM_TRM_EDGE_CTRL_SHIFT;
+
+ i2s_writel(ifc, val, I2S_I2S_PCM_CTRL_0);
+ return 0;
+}
+
+int i2s_set_pcm_mask_bits(int ifc, unsigned mask_bits, int tx)
+{
+ u32 val;
+
+ check_ifc(ifc, -EINVAL);
+
+ val = i2s_readl(ifc, I2S_I2S_PCM_CTRL_0);
+ if (tx) {
+ if (mask_bits > I2S_I2S_PCM_TRM_MASK_BITS_SEVEN) {
+ pr_err("%s: invalid dsp mask bits \n", __func__);
+ return -EINVAL;
+ }
+ val &= ~I2S_I2S_PCM_TRM_MASK_BITS_MASK;
+ val |= mask_bits << I2S_PCM_TRM_MASK_BITS_SHIFT;
+ }
+ else {
+ if (mask_bits > I2S_I2S_PCM_RCV_MASK_BITS_SEVEN) {
+ pr_err("%s: invalid dsp mask bits \n", __func__);
+ return -EINVAL;
+ }
+ val &= ~I2S_I2S_PCM_RCV_MASK_BITS_MASK;
+ val |= mask_bits << I2S_PCM_RCV_MASK_BITS_SHIFT;
+ }
+ i2s_writel(ifc, val, I2S_I2S_PCM_CTRL_0);
+ return 0;
+}
+
+void i2s_set_pcm_fsync_width(int ifc, int fsync_long)
+{
+ u32 val;
+
+ check_ifc(ifc);
+
+ val = i2s_readl(ifc, I2S_I2S_PCM_CTRL_0);
+ val &= ~I2S_I2S_PCM_CTRL_FSYNC_PCM_CTRL;
+ val |= fsync_long ? I2S_I2S_PCM_CTRL_FSYNC_PCM_CTRL : 0;
+
+ i2s_writel(ifc, val, I2S_I2S_PCM_CTRL_0);
+}
+
void i2s_set_fifo_irq_on_err(int ifc, int fifo, int on)
{
u32 val;