diff options
author | Nitin Pai <npai@nvidia.com> | 2011-07-18 14:03:00 +0530 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2011-07-21 05:10:59 -0700 |
commit | ae575be3bc7c8133e7fbbb6f9a5b022bc9d08afc (patch) | |
tree | d1314c2cc4ffb18ffe55b41a012f4f1f566b3244 | |
parent | 94a7cbce6412f8175e0d00042a860d25a6600037 (diff) |
tegra: audio_manager: Add support for I2S TDM mode
Added API's for I2S TDM mode programming for Tegra2
Added extra fields to support TDM mode programming.
Change-Id: I7cdde70ed2f9efae47ecd9efa0c0d3d701096740
Signed-off-by: Nitin Pai <npai@nvidia.com>
Reviewed-on: http://git-master/r/41525
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/audio_manager.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/audio.h | 11 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/audio_manager.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/tegra2_i2s.h | 65 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/tegra_i2s.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_i2s.c | 233 |
6 files changed, 315 insertions, 16 deletions
diff --git a/arch/arm/mach-tegra/audio_manager.c b/arch/arm/mach-tegra/audio_manager.c index 6431280f615c..eb18e691e77b 100644 --- a/arch/arm/mach-tegra/audio_manager.c +++ b/arch/arm/mach-tegra/audio_manager.c @@ -217,6 +217,7 @@ int am_set_stream_format(aud_dev_info* devinfo, am_stream_format_info *format) spdif_set_fifo_attention(dev_id, devinfo->fifo_mode, format->buffersize); } + return 0; } @@ -257,6 +258,13 @@ int am_device_init(aud_dev_info* devinfo, void *dev_fmt, void *strm_fmt) i2sprop.audio_mode = dfmt->audiomode; i2sprop.clk_rate = dfmt->clkrate; i2sprop.fifo_fmt = dfmt->fifofmt; + i2sprop.total_slots = dfmt->total_slots; + i2sprop.fsync_width = dfmt->fsync_width; + i2sprop.rx_slot_enables = dfmt->rx_slot_enables; + i2sprop.tx_slot_enables = dfmt->tx_slot_enables; + i2sprop.rx_bit_offset = dfmt->rx_bit_offset; + i2sprop.tx_bit_offset = dfmt->tx_bit_offset; + i2sprop.tdm_bitsize = dfmt->tdm_bitsize; } return i2s_init(devinfo->dev_id, &i2sprop); @@ -276,6 +284,7 @@ int am_device_init(aud_dev_info* devinfo, void *dev_fmt, void *strm_fmt) &spdifprop); } } + return 0; } diff --git a/arch/arm/mach-tegra/include/mach/audio.h b/arch/arm/mach-tegra/include/mach/audio.h index 816361fc6897..bca058766053 100644 --- a/arch/arm/mach-tegra/include/mach/audio.h +++ b/arch/arm/mach-tegra/include/mach/audio.h @@ -176,6 +176,17 @@ struct tegra_audio_platform_data { int mask; /* enable tx and rx? */ bool stereo_capture; /* True if hardware supports stereo */ void *driver_data; + + /* Below Fields are valid for TDM mode*/ + bool tdm_enable; + int total_slots; + int rx_bit_offset; + int tx_bit_offset; + int fsync_width; + int rx_slot_enables; + int tx_slot_enables; + int tdm_bitsize; + unsigned int dap_port_num; }; struct wired_jack_conf { diff --git a/arch/arm/mach-tegra/include/mach/audio_manager.h b/arch/arm/mach-tegra/include/mach/audio_manager.h index 9bdd2aa435d1..c39aafc396cc 100644 --- a/arch/arm/mach-tegra/include/mach/audio_manager.h +++ b/arch/arm/mach-tegra/include/mach/audio_manager.h @@ -46,6 +46,13 @@ typedef struct am_dev_format_info_{ int clkrate; int fifofmt; int loopmode; + int total_slots; + int fsync_width; + int tdm_bitsize; + int rx_bit_offset; + int tx_bit_offset; + int rx_slot_enables; + int tx_slot_enables; }am_dev_format_info; struct am_dev_fns { diff --git a/arch/arm/mach-tegra/include/mach/tegra2_i2s.h b/arch/arm/mach-tegra/include/mach/tegra2_i2s.h index e48ccacd1422..44a416d7acbf 100644 --- a/arch/arm/mach-tegra/include/mach/tegra2_i2s.h +++ b/arch/arm/mach-tegra/include/mach/tegra2_i2s.h @@ -35,8 +35,8 @@ #define I2S_I2S_FIFO_SCR_0 0x0c #define I2S_I2S_PCM_CTRL_0 0x10 #define I2S_I2S_NW_CTRL_0 0x14 -#define I2S_I2S_TDM_CTRL_0 0x20 -#define I2S_I2S_TDM_TX_RX_CTRL_0 0x24 +#define I2S_TDM_CTRL_0 0x20 +#define I2S_TDM_TX_RX_CTRL_0 0x24 #define I2S_I2S_FIFO1_0 0x40 #define I2S_I2S_FIFO2_0 0x80 @@ -84,21 +84,21 @@ #define I2S_FIFO_16_LSB 0 #define I2S_FIFO_20_LSB 1 #define I2S_FIFO_24_LSB 2 -#define I2S_FIFO_32 3 +#define I2S_FIFO_32 3 #define I2S_FIFO_PACKED 7 #define I2S_FIFO_SHIFT 4 #define I2S_I2S_CTRL_FIFO_FORMAT_MASK (7<<4) #define I2S_I2S_CTRL_FIFO_FORMAT_16_LSB \ - (I2S_FIFO_16_LSB << I2S_FIFO_SHIFT) + (I2S_FIFO_16_LSB << I2S_FIFO_SHIFT) #define I2S_I2S_CTRL_FIFO_FORMAT_20_LSB \ - (I2S_FIFO_20_LSB << I2S_FIFO_SHIFT) + (I2S_FIFO_20_LSB << I2S_FIFO_SHIFT) #define I2S_I2S_CTRL_FIFO_FORMAT_24_LSB \ - (I2S_FIFO_24_LSB << I2S_FIFO_SHIFT) + (I2S_FIFO_24_LSB << I2S_FIFO_SHIFT) #define I2S_I2S_CTRL_FIFO_FORMAT_32 \ - (I2S_FIFO_32 << I2S_FIFO_SHIFT) + (I2S_FIFO_32 << I2S_FIFO_SHIFT) #define I2S_I2S_CTRL_FIFO_FORMAT_PACKED \ - (I2S_FIFO_PACKED << I2S_FIFO_SHIFT) + (I2S_FIFO_PACKED << I2S_FIFO_SHIFT) // Left/Right Control Polarity. 0= Left channel when LRCK is low, // Right channel when LRCK is high, 1= vice versa @@ -289,6 +289,39 @@ #define I2S_I2S_PCM_CTRL_RCV_MODE (1<<0) +/* + * I2S_TDM_CTRL_0 + */ +#define I2S_TDM_CTRL_TDM_EN (1<<31) +#define I2S_TDM_CTRL_TX_MSB_LSB_MASK (1<<25) +#define I2S_TDM_CTRL_TX_MSB_LSB_SHIFT 25 +#define I2S_TDM_CTRL_RX_MSB_LSB_MASK (1<<24) +#define I2S_TDM_CTRL_RX_MSB_LSB_SHIFT 24 +#define I2S_TDM_CTRL_TDM_EDGE_CTRL_MASK (1<<22) +#define I2S_TDM_CTRL_TDM_EDGE_CTRL_SHIFT 22 +#define I2S_TDM_CTRL_TOTAL_SLOTS_MASK (0x7<<18) +#define I2S_TDM_CTRL_TOTAL_SLOTS_SHIFT 18 +#define I2S_TDM_CTRL_TDM_BIT_SIZE_MASK (0x1f<<12) +#define I2S_TDM_CTRL_TDM_BIT_SIZE_SHIFT 12 +#define I2S_TDM_CTRL_RX_DATA_OFFSET_MASK (0x3<<8) +#define I2S_TDM_CTRL_RX_DATA_OFFSET_SHIFT 8 +#define I2S_TDM_CTRL_TX_DATA_OFFSET_MASK (0x3<<6) +#define I2S_TDM_CTRL_TX_DATA_OFFSET_SHIFT 6 +#define I2S_TDM_CTRL_FSYNC_WIDTH_MASK 0x3f +#define I2S_TDM_CTRL_FSYNC_WIDTH_SHIFT 0 + +/* + * I2S_TDM_TX_RX_CTRL_0 + */ +#define I2S_TDM_TX_RX_CTRL_TDM_TX_EN (1<<31) +#define I2S_TDM_TX_RX_CTRL_TDM_RX_EN (1<<29) +#define I2S_TDM_TX_RX_CTRL_TDM_RX_SLOT_ENABLES_MASK (0xff<<8) +#define I2S_TDM_TX_RX_CTRL_TDM_RX_SLOT_ENABLES_SHIFT 8 +#define I2S_TDM_TX_RX_CTRL_TDM_TX_SLOT_ENABLES_MASK (0xff<<0) +#define I2S_TDM_TX_RX_CTRL_TDM_TX_SLOT_ENABLES_SHIFT 0 +#define I2S_TDM_TX_FIFO_BUSY (1<<30) +#define I2S_TDM_RX_FIFO_BUSY (1<<28) + /* * API @@ -300,4 +333,20 @@ int i2s_set_pcm_mask_bits(int ifc, unsigned mask_bits, int tx); int i2s_set_pcm_fsync_width(int ifc, int fsync_long); int i2s_enable_pcm_mode(int ifc, int enable); int i2s_enable_fifos(int ifc, int on); + +/* I2S TDM APIs */ + +int i2s_tdm_set_transfer(int ifc, int mode , int on); +int i2s_tdm_set_fifo_attention(int ifc, int fifo_mode, int buffersize); +u32 i2s_tdm_get_status(int ifc, int mode); +int i2s_tdm_enable(int ifc); +int i2s_tdm_set_msb_first(int ifc, int mode, int msb_first); +int i2s_tdm_set_tdm_edge_ctrl_highz(int ifc, int highz); +int i2s_tdm_set_total_slots(int ifc, int num_slots); +int i2s_tdm_set_bit_size(int ifc, int bit_size); +int i2s_tdm_set_data_offset(int ifc, int mode, int data_offset); +int i2s_tdm_set_fsync_width(int ifc, int fsync_width); +int i2s_tdm_set_slot_enables(int ifc, int mode, int slot_mask); +int i2s_tdm_init(int ifc, struct tegra_i2s_property *pi2sprop); + #endif /* __ARCH_ARM_MACH_TEGRA_I2S_H */ diff --git a/arch/arm/mach-tegra/include/mach/tegra_i2s.h b/arch/arm/mach-tegra/include/mach/tegra_i2s.h index ce98c081c53c..aff5e8002a6d 100644 --- a/arch/arm/mach-tegra/include/mach/tegra_i2s.h +++ b/arch/arm/mach-tegra/include/mach/tegra_i2s.h @@ -52,6 +52,11 @@ struct tegra_i2s_property { int fsync_width; /* Fsync width in terms of bit clocks */ int highz_control; /* Highz control */ int edge_control; /* sample data on edge */ + int rx_bit_offset; /* Data offset to FSync for TDM mode */ + int tx_bit_offset; /* Data offset to FSync for TDM mode */ + int tx_slot_enables; /* Number of slots enabled in the Fsync */ + int rx_slot_enables; /* Number of slots enabled in the Fsync */ + int tdm_bitsize; struct clk *i2s_clk; struct clk *i2s_sync_clk; @@ -100,4 +105,5 @@ int i2s_clock_enable(int ifc, int fifo_mode); int i2s_close(int ifc); int i2s_clock_set_parent(int ifc, int mode, int parent); int i2s_clock_set_rate(int ifc, int mode, int rate); + #endif /* __ARCH_ARM_MACH_TEGRA_I2S_H */ diff --git a/arch/arm/mach-tegra/tegra2_i2s.c b/arch/arm/mach-tegra/tegra2_i2s.c index 2c323aabf24e..a07b4ae85b3e 100644 --- a/arch/arm/mach-tegra/tegra2_i2s.c +++ b/arch/arm/mach-tegra/tegra2_i2s.c @@ -29,7 +29,6 @@ #include <mach/audio.h> #include <mach/tegra2_i2s.h> - #define NR_I2S_IFC 2 #define check_ifc(n, ...) if ((n) > NR_I2S_IFC) { \ @@ -98,12 +97,17 @@ void i2s_dump_registers(int ifc) i2s_readl(ifc, I2S_I2S_STATUS_0)); pr_info("%s: TIMING %08x\n", __func__, i2s_readl(ifc, I2S_I2S_TIMING_0)); - pr_info("%s: SCR %08x\n", __func__, + pr_info("%s: SCR %08x\n", __func__, i2s_readl(ifc, I2S_I2S_FIFO_SCR_0)); pr_info("%s: FIFO1 %08x\n", __func__, i2s_readl(ifc, I2S_I2S_FIFO1_0)); pr_info("%s: FIFO2 %08x\n", __func__, i2s_readl(ifc, I2S_I2S_FIFO1_0)); + pr_info("%s: TDM CTRL %08x\n", __func__, + i2s_readl(ifc, I2S_TDM_CTRL_0)); + pr_info("%s: TDM RX TX CTRL %08x\n", __func__, + i2s_readl(ifc, I2S_TDM_TX_RX_CTRL_0)); + } struct i2s_controller_info * i2s_get_cont_info(int ifc) @@ -137,8 +141,8 @@ int i2s_suspend(int ifc) ird->i2s__fifo_scr_0 = i2s_readl(ifc, I2S_I2S_FIFO_SCR_0); ird->i2s_pcm_ctrl_0 = i2s_readl(ifc, I2S_I2S_PCM_CTRL_0); ird->i2s_nw_ctrl_0 = i2s_readl(ifc, I2S_I2S_NW_CTRL_0); - ird->i2s_tdm_ctrl_0 = i2s_readl(ifc, I2S_I2S_TDM_CTRL_0); - ird->i2s_tdm_tx_rx_ctrl_0 = i2s_readl(ifc, I2S_I2S_TDM_TX_RX_CTRL_0); + ird->i2s_tdm_ctrl_0 = i2s_readl(ifc, I2S_TDM_CTRL_0); + ird->i2s_tdm_tx_rx_ctrl_0 = i2s_readl(ifc, I2S_TDM_TX_RX_CTRL_0); ird->i2s_fifo1_0 = i2s_readl(ifc, I2S_I2S_FIFO1_0); ird->i2s_fifo2_0 = i2s_readl(ifc, I2S_I2S_FIFO2_0); @@ -159,8 +163,8 @@ int i2s_resume(int ifc) i2s_writel(ifc, ird->i2s__fifo_scr_0, I2S_I2S_FIFO_SCR_0); i2s_writel(ifc, ird->i2s_pcm_ctrl_0, I2S_I2S_PCM_CTRL_0); i2s_writel(ifc, ird->i2s_nw_ctrl_0, I2S_I2S_NW_CTRL_0); - i2s_writel(ifc, ird->i2s_tdm_ctrl_0, I2S_I2S_TDM_CTRL_0); - i2s_writel(ifc, ird->i2s_tdm_tx_rx_ctrl_0, I2S_I2S_TDM_TX_RX_CTRL_0); + i2s_writel(ifc, ird->i2s_tdm_ctrl_0, I2S_TDM_CTRL_0); + i2s_writel(ifc, ird->i2s_tdm_tx_rx_ctrl_0, I2S_TDM_TX_RX_CTRL_0); i2s_writel(ifc, ird->i2s_fifo1_0, I2S_I2S_FIFO1_0); i2s_writel(ifc, ird->i2s_fifo2_0, I2S_I2S_FIFO2_0); return 0; @@ -285,6 +289,9 @@ int i2s_fifo_enable(int ifc, int fifo, int on) check_ifc(ifc, -EINVAL); + if (info->i2sprop.audio_mode == AUDIO_FRAME_FORMAT_TDM) + return i2s_tdm_set_transfer(ifc, fifo, on); + val = i2s_readl(ifc, I2S_I2S_CTRL_0); if (!fifo) { val &= ~I2S_I2S_CTRL_FIFO1_ENABLE; @@ -340,6 +347,11 @@ int i2s_set_bit_format(int ifc, unsigned fmt) check_ifc(ifc, -EINVAL); + if (fmt == AUDIO_FRAME_FORMAT_TDM) { + i2s_tdm_enable(ifc); + return 0; + } + if (fmt > AUDIO_FRAME_FORMAT_DSP) { pr_err("%s: invalid bit-format selector %d\n", __func__, fmt); return -EINVAL; @@ -533,6 +545,10 @@ int i2s_set_fifo_attention(int ifc, int fifo_mode, int buffersize) int fifoattn = I2S_FIFO_ATN_LVL_FOUR_SLOTS; struct i2s_controller_info *info = &i2s_cont_info[ifc]; info->i2s_ch_prop[fifo_mode].fifo_attn = fifoattn; + + if (info->i2sprop.audio_mode == AUDIO_FRAME_FORMAT_TDM) + i2s_tdm_set_fifo_attention(ifc, fifo_mode, buffersize); + return 0; } @@ -545,7 +561,7 @@ int i2s_enable_fifos(int ifc, int on) val = i2s_readl(ifc, I2S_I2S_CTRL_0); if (on) val |= I2S_I2S_QE_FIFO1 | I2S_I2S_QE_FIFO2 | - I2S_I2S_IE_FIFO1_ERR | I2S_I2S_IE_FIFO2_ERR; + I2S_I2S_IE_FIFO1_ERR | I2S_I2S_IE_FIFO2_ERR; else val &= ~(I2S_I2S_QE_FIFO1 | I2S_I2S_QE_FIFO2 | I2S_I2S_IE_FIFO1_ERR | I2S_I2S_IE_FIFO2_ERR); @@ -570,7 +586,13 @@ u32 i2s_fifo_read(int ifc, int fifo) u32 i2s_get_status(int ifc, int fifo) { int regval = 0; + struct i2s_controller_info *info; check_ifc(ifc, 0); + + info = &i2s_cont_info[ifc]; + if (info->i2sprop.audio_mode == AUDIO_FRAME_FORMAT_TDM) + return i2s_tdm_get_status(ifc, fifo); + regval = i2s_readl(ifc, I2S_I2S_STATUS_0); if (fifo == AUDIO_TX_MODE) @@ -623,10 +645,184 @@ u32 i2s_get_fifo_full_empty_count(int ifc, int fifo) return val & I2S_I2S_FIFO_SCR_FIFO_FULL_EMPTY_COUNT_MASK; } +/* I2S TDM Mode Register settings */ + +int i2s_tdm_enable(int ifc) +{ + u32 val; + check_ifc(ifc, -EINVAL); + val = i2s_readl(ifc, I2S_TDM_CTRL_0); + val &= ~I2S_TDM_CTRL_TDM_EN; + val |= I2S_TDM_CTRL_TDM_EN; + i2s_writel(ifc, val, I2S_TDM_CTRL_0); + return 0; +} + +int i2s_tdm_set_msb_first(int ifc, int mode, int msb_first) +{ + u32 val; + check_ifc(ifc, -EINVAL); + val = i2s_readl(ifc, I2S_TDM_CTRL_0); + if (mode == AUDIO_TX_MODE) { + val &= ~I2S_TDM_CTRL_TX_MSB_LSB_MASK; + val |= (msb_first) << I2S_TDM_CTRL_TX_MSB_LSB_SHIFT; + } else { + val &= ~I2S_TDM_CTRL_RX_MSB_LSB_MASK; + val |= (msb_first) << I2S_TDM_CTRL_RX_MSB_LSB_SHIFT; + } + i2s_writel(ifc, val, I2S_TDM_CTRL_0); + return 0; +} + +int i2s_tdm_set_tdm_edge_ctrl_highz(int ifc, int highz) +{ + u32 val; + check_ifc(ifc, -EINVAL); + val = i2s_readl(ifc, I2S_TDM_CTRL_0); + val &= ~I2S_TDM_CTRL_TDM_EDGE_CTRL_MASK; + val |= highz << I2S_TDM_CTRL_TDM_EDGE_CTRL_SHIFT; + i2s_writel(ifc, val, I2S_TDM_CTRL_0); + return 0; +} + +int i2s_tdm_set_total_slots(int ifc, int total_slots) +{ + u32 val; + check_ifc(ifc, -EINVAL); + if (total_slots > 8 || total_slots < 1) + return -EINVAL; + val = i2s_readl(ifc, I2S_TDM_CTRL_0); + val &= ~I2S_TDM_CTRL_TOTAL_SLOTS_MASK; + val |= (total_slots - 1) << I2S_TDM_CTRL_TOTAL_SLOTS_SHIFT; + i2s_writel(ifc, val, I2S_TDM_CTRL_0); + return 0; +} + +int i2s_tdm_set_tdm_bitsize(int ifc, int tdm_bitsize) +{ + u32 val; + check_ifc(ifc, -EINVAL); + if ((tdm_bitsize) & 3) + return -EINVAL; + val = i2s_readl(ifc, I2S_TDM_CTRL_0); + val &= ~I2S_TDM_CTRL_TDM_BIT_SIZE_MASK; + val |= (tdm_bitsize - 1) << I2S_TDM_CTRL_TDM_BIT_SIZE_SHIFT; + i2s_writel(ifc, val, I2S_TDM_CTRL_0); + return 0; +} + +int i2s_tdm_set_data_offset(int ifc, int mode, int data_offset) +{ + u32 val; + check_ifc(ifc, -EINVAL); + if (data_offset < 0 || data_offset > 3) + return -EINVAL; + val = i2s_readl(ifc, I2S_TDM_CTRL_0); + if (mode == AUDIO_TX_MODE) { + val &= ~I2S_TDM_CTRL_TX_DATA_OFFSET_MASK; + val |= (data_offset) << I2S_TDM_CTRL_TX_DATA_OFFSET_SHIFT; + } else { + val &= ~I2S_TDM_CTRL_RX_DATA_OFFSET_MASK; + val |= (data_offset) << I2S_TDM_CTRL_RX_DATA_OFFSET_SHIFT; + } + i2s_writel(ifc, val, I2S_TDM_CTRL_0); + return 0; +} + +int i2s_tdm_set_fsync_width(int ifc, int fsync_width) +{ + u32 val; + check_ifc(ifc, -EINVAL); + val = i2s_readl(ifc, I2S_TDM_CTRL_0); + val &= ~I2S_TDM_CTRL_FSYNC_WIDTH_MASK; + val |= (fsync_width - 1) << I2S_TDM_CTRL_FSYNC_WIDTH_SHIFT; + i2s_writel(ifc, val, I2S_TDM_CTRL_0); + return 0; +} + +int i2s_tdm_set_transfer(int ifc, int mode , int on) +{ + u32 val; + struct i2s_controller_info *info; + check_ifc(ifc, -EINVAL); + + info = &i2s_cont_info[ifc]; + if (on) + i2s_fifo_set_attention_level(ifc, mode , + info->i2s_ch_prop[mode].fifo_attn); + + val = i2s_readl(ifc, I2S_TDM_TX_RX_CTRL_0); + + if (mode == AUDIO_TX_MODE) { + val &= ~I2S_TDM_TX_RX_CTRL_TDM_TX_EN; + val |= on ? I2S_TDM_TX_RX_CTRL_TDM_TX_EN : 0; + } else { + val &= ~I2S_TDM_TX_RX_CTRL_TDM_RX_EN; + val |= on ? I2S_TDM_TX_RX_CTRL_TDM_RX_EN : 0; + } + i2s_writel(ifc, val, I2S_TDM_TX_RX_CTRL_0); + + return 0; +} + +int i2s_tdm_set_slot_enables(int ifc, int mode, int slot_mask) +{ + u32 val; + check_ifc(ifc, -EINVAL); + val = i2s_readl(ifc, I2S_TDM_TX_RX_CTRL_0); + + if (mode == AUDIO_TX_MODE) { + val &= ~I2S_TDM_TX_RX_CTRL_TDM_RX_SLOT_ENABLES_MASK; + val |= (slot_mask) << \ + I2S_TDM_TX_RX_CTRL_TDM_RX_SLOT_ENABLES_SHIFT; + } else { + val &= ~I2S_TDM_TX_RX_CTRL_TDM_TX_SLOT_ENABLES_MASK; + val |= (slot_mask) << \ + I2S_TDM_TX_RX_CTRL_TDM_TX_SLOT_ENABLES_SHIFT; + } + i2s_writel(ifc, val, I2S_TDM_TX_RX_CTRL_0); + return 0; +} + +u32 i2s_tdm_get_status(int ifc , int mode) +{ + u32 val; + check_ifc(ifc, 0); + val = i2s_readl(ifc, I2S_TDM_TX_RX_CTRL_0); + + if (mode == AUDIO_TX_MODE) + val &= I2S_TDM_TX_FIFO_BUSY; + else + val &= I2S_TDM_RX_FIFO_BUSY; + + return val; +} + +int i2s_tdm_set_fifo_attention(int ifc, int fifo_mode, int bitsize) +{ + int fifoattn; + struct i2s_controller_info *info = &i2s_cont_info[ifc]; + + switch (info->i2sprop.total_slots) { + case 1: + fifoattn = I2S_FIFO_ATN_LVL_ONE_SLOT; + break; + case 4: + fifoattn = I2S_FIFO_ATN_LVL_FOUR_SLOTS; + break; + case 8: + fifoattn = I2S_FIFO_ATN_LVL_EIGHT_SLOTS; + break; + default: + fifoattn = I2S_FIFO_ATN_LVL_FOUR_SLOTS; + } + info->i2s_ch_prop[fifo_mode].fifo_attn = fifoattn; + return 0; +} struct clk *i2s_get_clock_by_name(const char *name) { - return tegra_get_clock_by_name(name); + return tegra_get_clock_by_name(name); } int i2s_free_dma_requestor(int ifc, int fifo) @@ -707,11 +903,32 @@ int i2s_init(int ifc, struct tegra_i2s_property* pi2sprop) i2s_set_bit_size(ifc, pi2sprop->bit_size); i2s_set_fifo_format(ifc, pi2sprop->fifo_fmt); + if (info->i2sprop.audio_mode == AUDIO_FRAME_FORMAT_TDM) + i2s_tdm_init(ifc, pi2sprop); + i2s_clock_disable(ifc, 0); return 0; } +int i2s_tdm_init(int ifc, struct tegra_i2s_property *pi2sprop) +{ + + /* Set the TDM controller specific registers */ + i2s_tdm_enable(ifc); + i2s_tdm_set_msb_first(ifc, AUDIO_TX_MODE, 0); /* MSB_FIRST */ + i2s_tdm_set_msb_first(ifc, AUDIO_RX_MODE, 0); /* MSB_FIRST */ + i2s_tdm_set_tdm_edge_ctrl_highz(ifc, 0); /* NO_HIGHZ */ + i2s_tdm_set_total_slots(ifc, pi2sprop->total_slots); + i2s_tdm_set_tdm_bitsize(ifc, pi2sprop->tdm_bitsize); + i2s_tdm_set_data_offset(ifc, AUDIO_TX_MODE, pi2sprop->rx_bit_offset); + i2s_tdm_set_data_offset(ifc, AUDIO_RX_MODE, pi2sprop->tx_bit_offset); + i2s_tdm_set_fsync_width(ifc, pi2sprop->fsync_width); + i2s_tdm_set_slot_enables(ifc, AUDIO_TX_MODE, pi2sprop->tx_slot_enables); + i2s_tdm_set_slot_enables(ifc, AUDIO_RX_MODE, pi2sprop->rx_slot_enables); + + return 0; +} int i2s_clock_enable(int ifc, int fifo_mode) { |