summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVinod G <vinodg@nvidia.com>2011-03-29 18:19:32 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-04-26 15:54:46 -0700
commit437622a591e552169ba7b7443432d081c83a8f73 (patch)
tree3fa95bb44db6e6bb6ffeeaec417b20b032357cfe
parentbe27dfe98c8b7441ff1c521d66e336efbcedde60 (diff)
arm: tegra: Add Dynamic apbif channel allocation
Big 804696 Added the dynamic apbif channel allocation to be used among various controller. Support added to more apbif function calls Original-Change-Id: I5420751037eebb07e4c9a3be339ce5c72174d1be Reviewed-on: http://git-master/r/24774 Reviewed-by: Vinod Gopalakrishnakurup <vinodg@nvidia.com> Tested-by: Vinod Gopalakrishnakurup <vinodg@nvidia.com> Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com> Reviewed-by: Scott Peterson <speterson@nvidia.com> Change-Id: If38be7a842ed7684978a8853106dcadf04e6520d
-rw-r--r--arch/arm/mach-tegra/audio_switch.c388
-rw-r--r--arch/arm/mach-tegra/include/mach/audio.h19
-rw-r--r--arch/arm/mach-tegra/include/mach/audio_switch.h60
-rw-r--r--arch/arm/mach-tegra/include/mach/spdif.h4
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra2_i2s.h5
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra3_i2s.h95
-rw-r--r--arch/arm/mach-tegra/spdif.c227
-rw-r--r--arch/arm/mach-tegra/tegra2_i2s.c10
-rw-r--r--arch/arm/mach-tegra/tegra3_i2s.c206
-rw-r--r--arch/arm/mach-tegra/tegra_spdif_audio.c8
-rw-r--r--sound/soc/tegra/tegra_i2s.c29
-rw-r--r--sound/soc/tegra/tegra_pcm.c4
-rw-r--r--sound/soc/tegra/tegra_soc.h1
-rw-r--r--sound/soc/tegra/tegra_spdif.c4
14 files changed, 637 insertions, 423 deletions
diff --git a/arch/arm/mach-tegra/audio_switch.c b/arch/arm/mach-tegra/audio_switch.c
index a6a805ca405b..1abb82e5c715 100644
--- a/arch/arm/mach-tegra/audio_switch.c
+++ b/arch/arm/mach-tegra/audio_switch.c
@@ -34,7 +34,7 @@
#define NR_APBIF_CHANNELS 4
-#define check_apbif_ifc(n, ...) if ((n) > NR_APBIF_CHANNELS) { \
+#define check_apbif_ifc(n, ...) if ((n) > NR_APBIF_CHANNELS) { \
pr_err("%s: invalid interface %d\n", __func__, (n)); \
return __VA_ARGS__; \
}
@@ -43,96 +43,56 @@
* Audiocif Ctrl
*/
#define AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT 28
-#define AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK \
+#define AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK\
(0xf << AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT)
#define AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 24
-#define AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK \
+#define AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK\
(7 << AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT)
-#define AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16
-#define AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK \
+#define AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16
+#define AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK\
(7 << AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT)
#define AUDIOCIF_CTRL_AUDIO_BITS_SHIFT 12
-#define AUDIOCIF_CTRL_AUDIO_BITS_MASK \
+#define AUDIOCIF_CTRL_AUDIO_BITS_MASK\
(7 << AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
#define AUDIOCIF_CTRL_CLIENT_BITS_SHIFT 8
-#define AUDIOCIF_CTRL_CLIENT_BITS_MASK \
+#define AUDIOCIF_CTRL_CLIENT_BITS_MASK\
(7 << AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
-#define AUDIOCIF_CTRL_EXPAND_SHIFT 6
-#define AUDIOCIF_CTRL_EXPAND_MASK \
+#define AUDIOCIF_CTRL_EXPAND_SHIFT 6
+#define AUDIOCIF_CTRL_EXPAND_MASK\
(3 << AUDIOCIF_CTRL_EXPAND_SHIFT)
#define AUDIOCIF_CTRL_STEREO_CONV_SHIFT 4
-#define AUDIOCIF_CTRL_STEREO_CONV_MASK \
+#define AUDIOCIF_CTRL_STEREO_CONV_MASK\
(3 << AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
#define AUDIOCIF_CTRL_REPLICATE_SHIFT 3
-#define AUDIOCIF_CTRL_REPLICATE_MASK \
+#define AUDIOCIF_CTRL_REPLICATE_MASK\
(1 << AUDIOCIF_CTRL_REPLICATE_SHIFT)
#define AUDIOCIF_CTRL_DIRECTION_SHIFT 2
-#define AUDIOCIF_CTRL_DIRECTION_TXCIF \
+#define AUDIOCIF_CTRL_DIRECTION_TXCIF\
(0 << AUDIOCIF_CTRL_DIRECTION_SHIFT)
-#define AUDIOCIF_CTRL_DIRECTION_RXCIF \
+#define AUDIOCIF_CTRL_DIRECTION_RXCIF\
(1 << AUDIOCIF_CTRL_DIRECTION_SHIFT)
#define AUDIOCIF_CTRL_TRUNCATE_SHIFT 1
-#define AUDIOCIF_CTRL_TRUNCATE_MASK \
+#define AUDIOCIF_CTRL_TRUNCATE_MASK\
(1 << AUDIOCIF_CTRL_TRUNCATE_SHIFT)
#define AUDIOCIF_CTRL_MONO_CONV_SHIFT 0
-#define AUDIOCIF_CTRL_MONO_CONV_MASK \
+#define AUDIOCIF_CTRL_MONO_CONV_MASK\
(1 << AUDIOCIF_CTRL_MONO_CONV_SHIFT)
/* Offsets from AudioSwitch base */
-
-#define AUDIO_APBIF_RX0_0 0x0
-#define AUDIO_APBIF_RX1_0 0x4
-#define AUDIO_APBIF_RX2_0 0x08
-#define AUDIO_APBIF_RX3_0 0x0c
-#define AUDIO_I2S0_RX0_0 0x10
-#define AUDIO_I2S1_RX0_0 0x14
-#define AUDIO_I2S2_RX0_0 0x18
-#define AUDIO_I2S3_RX0_0 0x1c
-#define AUDIO_I2S4_RX0_0 0x20
-#define AUDIO_DAM0_RX0_0 0x24
-#define AUDIO_DAM0_RX1_0 0x28
-#define AUDIO_DAM1_RX0_0 0x2c
-#define AUDIO_DAM1_RX1_0 0x30
-#define AUDIO_DAM2_RX0_0 0x34
-#define AUDIO_DAM2_RX1_0 0x38
-#define AUDIO_SPDIF_RX0_0 0x3c
-#define AUDIO_SPDIF_RX1_0 0x40
-
-/*
-* Control values
-*/
-#define AUDIO_SPDIF_TX1 (1<<13)
-#define AUDIO_SPDIF_TX0 (1<<12)
-#define AUDIO_DAM2_TX0 (1<<11)
-#define AUDIO_DAM1_TX0 (1<<10)
-#define AUDIO_DAM0_TX0 (1<<9)
-#define AUDIO_I2S4_TX0 (1<<8)
-#define AUDIO_I2S3_TX0 (1<<7)
-#define AUDIO_I2S2_TX0 (1<<6)
-#define AUDIO_I2S1_TX0 (1<<5)
-#define AUDIO_I2S0_TX0 (1<<4)
-#define AUDIO_APBIF_TX3 (1<<3)
-#define AUDIO_APBIF_TX2 (1<<2)
-#define AUDIO_APBIF_TX1 (1<<1)
-#define AUDIO_APBIF_TX0 (1<<0)
-
-#define APBIF_CHANNEL_0 0
-#define APBIF_CHANNEL_1 1
-#define APBIF_CHANNEL_2 2
-#define APBIF_CHANNEL_3 3
+#define AUDIO_APBIF_RX_OFFSET 0x4
/*
* APBIF REGSITER OFFSETS
@@ -166,7 +126,7 @@
#define APBIF_AUDIOCIF_TX3_CTRL_0 0x74
#define APBIF_AUDIOCIF_RX3_CTRL_0 0x78
#define APBIF_CONFIG_LINK_CTRL_0 0x80
-#define APBIF_MISC_CTRL_0 0x84
+#define APBIF_MISC_CTRL_0 0x84
#define APBIF_APBDMA_LIVE_STATUS_0 0x88
#define APBIF_I2S_LIVE_STATUS_0 0x8c
#define APBIF_DAM0_LIVE_STATUS_0 0x90
@@ -185,8 +145,8 @@
#define APBIF_DAM_INT_SOURCE_0 0xe4
#define APBIF_SPDIF_INT_SOURCE_0 0xec
#define APBIF_APBIF_INT_SOURCE_0 0xf0
-#define APBIF_I2S_INT_SET_0 0xf8
-#define APBIF_DAM_INT_SET_0 0xfc
+#define APBIF_I2S_INT_SET_0 0xf8
+#define APBIF_DAM_INT_SET_0 0xfc
#define APBIF_SPDIF_INT_SET_0 0x100
#define APBIF_APBIF_INT_SET_0 0x104
@@ -201,22 +161,22 @@
#define APBIF_CH_CTRL_THRESHOLD_LIMIT 0xff
#define APBIF_CH_CTRL_TX_THRESHOLD_SHIFT 16
-#define APBIF_CH_CTRL_TX_THRESHOLD_MASK \
- (APBIF_CH_CTRL_THRESHOLD_LIMIT<<APBIF_CH_CTRL_TX_THRESHOLD_SHIFT)
+#define APBIF_CH_CTRL_TX_THRESHOLD_MASK\
+ (APBIF_CH_CTRL_THRESHOLD_LIMIT<<APBIF_CH_CTRL_TX_THRESHOLD_SHIFT)
#define APBIF_CH_CTRL_RX_THRESHOLD_SHIFT 8
-#define APBIF_CH_CTRL_RX_THRESHOLD_MASK \
- (APBIF_CH_CTRL_THRESHOLD_LIMIT<<APBIF_CH_CTRL_RX_THRESHOLD_SHIFT)
+#define APBIF_CH_CTRL_RX_THRESHOLD_MASK\
+ (APBIF_CH_CTRL_THRESHOLD_LIMIT<<APBIF_CH_CTRL_RX_THRESHOLD_SHIFT)
#define APBIF_CH_CTRL_TX_PACK_EN (1<<6)
#define APBIF_CH_CTRL_TX_PACK_SHIFT 4
-#define APBIF_CH_CTRL_TX_PACK_MASK \
+#define APBIF_CH_CTRL_TX_PACK_MASK\
(0x3<<APBIF_CH_CTRL_TX_PACK_SHIFT)
#define APBIF_CH_CTRL_RX_PACK_EN (1<<2)
#define APBIF_CH_CTRL_RX_PACK_SHIFT 0
-#define APBIF_CH_CTRL_RX_PACK_MASK \
+#define APBIF_CH_CTRL_RX_PACK_MASK\
(0x3<<APBIF_CH_CTRL_RX_PACK_SHIFT)
/*
@@ -229,37 +189,39 @@
* APBIF Channel Status
*/
#define APBIF_CH_STATUS_TX_FREE_COUNT_SHIFT 24
-#define APBIF_CH_STATUS_TX_FREE_COUNT_MASK \
+#define APBIF_CH_STATUS_TX_FREE_COUNT_MASK\
(0xff<<APBIF_CH_STATUS_TX_FREE_COUNT_SHIFT)
#define APBIF_CH_STATUS_RX_FREE_COUNT_SHIFT 16
-#define APBIF_CH_STATUS_RX_FREE_COUNT_MASK \
+#define APBIF_CH_STATUS_RX_FREE_COUNT_MASK\
(0x00ff<<APBIF_CH_STATUS_RX_FREE_COUNT_SHIFT)
#define APBIF_CH_STATUS_TX_TRIG (1<<1)
#define APBIF_CH_STATUS_RX_TRIG (1<<0)
-#define APBIF_CH_STATUS_FIFO_SHIFT 0
-#define APBIF_CH_STATUS_FIFO_MASK \
+#define APBIF_CH_STATUS_FIFO_SHIFT 0
+#define APBIF_CH_STATUS_FIFO_MASK\
(0xffff<<APBIF_CH_STATUS_FIFO_SHIFT)
#define ENABLE_AHUB_DEBUG_PRINT 0
-#if ENABLE_AHUB_DEBUG_PRINT
-#define AHUB_DEBUG_PRINT(fmt, arg...) printk(fmt, ## arg)
+#if ENABLE_AHUB_DEBUG_PRINT
+#define AHUB_DEBUG_PRINT(fmt, arg...) printk(fmt, ## arg)
#else
#define AHUB_DEBUG_PRINT(fmt, arg...) do {} while (0)
#endif
+
/*
* Internal functions
*/
struct apbif_channel_info {
- void __iomem *virt_base;
- phys_addr_t phy_base;
- int dma_index;
- int inuse;
- int channel_requestor;
+ void __iomem *virt_base;
+ phys_addr_t phy_base;
+ int dma_index;
+ bool fifo_inuse[AUDIO_FIFO_CNT];
+ int fifo_req[AUDIO_FIFO_CNT];
+ int fifo_refcnt[AUDIO_FIFO_CNT];
};
/* audio switch controller */
@@ -274,50 +236,34 @@ static int enable_audioswitch = 0;
static struct apbif_channel_info apbif_channels[NR_APBIF_CHANNELS];
-static void *audio_hub_base = IO_ADDRESS(TEGRA_AHUB_BASE);
+static void *ahub_reg_base[ahubrx_maxnum];
static inline void audio_switch_writel(u32 reg, u32 val)
{
- writel(val, audio_hub_base + reg);
- AHUB_DEBUG_PRINT("ahub write offset 0x%x: %08x\n",
- (unsigned int) audio_hub_base + reg, val);
+ writel(val, reg);
+ AHUB_DEBUG_PRINT("ahub write offset 0x%x: %08x\n", reg, val);
}
static inline u32 audio_switch_readl(u32 reg)
{
- u32 val = readl(audio_hub_base + reg);
- AHUB_DEBUG_PRINT("ahub read offset 0x%x: %08x\n",
- (unsigned int)audio_hub_base + reg, val);
+ u32 val = readl(reg);
+ AHUB_DEBUG_PRINT("ahub read offset 0x%x: %08x\n", reg, val);
return val;
}
void audio_switch_dump_registers(int ifc)
{
+ int i = 0;
check_apbif_ifc(ifc);
pr_info("%s: \n",__func__);
- audio_switch_readl(AUDIO_APBIF_RX0_0);
- audio_switch_readl(AUDIO_APBIF_RX1_0);
- audio_switch_readl(AUDIO_APBIF_RX2_0);
- audio_switch_readl(AUDIO_APBIF_RX3_0);
- audio_switch_readl(AUDIO_I2S0_RX0_0);
- audio_switch_readl(AUDIO_I2S1_RX0_0);
- audio_switch_readl(AUDIO_I2S2_RX0_0);
- audio_switch_readl(AUDIO_I2S3_RX0_0);
- audio_switch_readl(AUDIO_I2S4_RX0_0);
- audio_switch_readl(AUDIO_DAM0_RX0_0);
- audio_switch_readl(AUDIO_DAM0_RX1_0);
- audio_switch_readl(AUDIO_DAM1_RX0_0);
- audio_switch_readl(AUDIO_DAM1_RX1_0);
- audio_switch_readl(AUDIO_DAM2_RX0_0);
- audio_switch_readl(AUDIO_DAM2_RX1_0);
- audio_switch_readl(AUDIO_SPDIF_RX0_0);
- audio_switch_readl(AUDIO_SPDIF_RX1_0);
+ for (i = 0; i < ahubrx_maxnum; i++)
+ audio_switch_readl((u32)ahub_reg_base[i]);
}
void audio_switch_set_rx_port(int rxport, int txport)
{
/*Get audioswitch base address*/
- audio_switch_writel(rxport, txport);
+ audio_switch_writel((u32)ahub_reg_base[rxport], (1 << txport));
}
int audio_switch_get_rx_port(int rxport)
@@ -341,7 +287,8 @@ void audio_switch_set_acif(int addr, struct audio_cif *cifInfo)
val |= (cifInfo->audio_channels << AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT);
/* client channels */
val &= ~AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK;
- val |= (cifInfo->client_channels << AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
+ val |=
+ (cifInfo->client_channels << AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
/* audio bits */
val &= ~AUDIOCIF_CTRL_AUDIO_BITS_MASK;
val |= (cifInfo->audio_bits << AUDIOCIF_CTRL_AUDIO_BITS_SHIFT);
@@ -426,6 +373,75 @@ void apbif_dump_registers(int ifc)
apbif_readl(0, APBIF_APBIF_INT_SET_0);
}
+int audio_apbif_free_channel(int ifc, int fifo_mode)
+{
+ struct apbif_channel_info *ch = 0;
+ ch = &apbif_channels[ifc];
+
+ if (ch->fifo_inuse[fifo_mode] == true) {
+ ch->fifo_refcnt[fifo_mode] -= 1;
+ if (ch->fifo_refcnt[fifo_mode] <= 0) {
+ ch->fifo_inuse[fifo_mode] = false;
+ ch->fifo_req[fifo_mode] = 0;
+ ch->fifo_refcnt[fifo_mode] = 0;
+ AHUB_DEBUG_PRINT("freed channel %d mode %d\n",
+ ifc, fifo_mode);
+ }
+ }
+
+ return 0;
+}
+
+/* FIXME : Stream with same index has to be taken care of
+ need to figure out the stream->number is differential
+ variable to make use of.
+*/
+static int get_apbif_channel(int fifo_req, int fifo_mode)
+{
+ struct apbif_channel_info *ch = 0;
+ int i = 0;
+
+ AHUB_DEBUG_PRINT(" %s ++ fifo_req 0x%x mode %d \n",
+ __func__, (unsigned int)fifo_req, fifo_mode);
+
+ for (i = 0; i < NR_APBIF_CHANNELS; i++) {
+ ch = &apbif_channels[i];
+ if (ch->fifo_inuse[fifo_mode] == true) {
+ if (ch->fifo_req[fifo_mode] != fifo_req)
+ continue;
+ else
+ goto found;
+ }
+ }
+
+ for (i = 0; i < NR_APBIF_CHANNELS; i++) {
+ ch = &apbif_channels[i];
+
+ if (ch->fifo_inuse[fifo_mode] == true)
+ continue;
+
+ goto found;
+ }
+
+ return -ENOENT;
+
+found:
+ ch->fifo_inuse[fifo_mode] = true;
+ ch->fifo_req[fifo_mode] = fifo_req;
+ ch->fifo_refcnt[fifo_mode] += 1;
+
+ AHUB_DEBUG_PRINT(" %s -- dmaindex 0x%x ch 0x%x refcnt 0x%x\n",
+ __func__, ch->dma_index, i, ch->fifo_refcnt[fifo_mode]);
+
+ /*FIXME: move the connection based on request for apbif if needed */
+ if (fifo_mode == AUDIO_TX_MODE)
+ audio_switch_set_rx_port(fifo_req, i);
+ else
+ audio_switch_set_rx_port(i, fifo_req);
+
+ return ch->dma_index;
+}
+
/*
* Set the fifo mode as Tx or Rx or both
*/
@@ -438,9 +454,9 @@ void apbif_channel_enable(int ifc, int tx, int enable)
val = apbif_readl(ifc, APBIF_CHANNEL0_CTRL_0);
if (tx != AUDIO_TX_MODE) {
set_reg_mode(val, APBIF_CH_CTRL_RX_ENABLE, enable);
+ } else {
+ set_reg_mode(val, APBIF_CH_CTRL_TX_ENABLE, enable);
}
- else {
- set_reg_mode(val, APBIF_CH_CTRL_TX_ENABLE, enable); }
apbif_writel(ifc, val, APBIF_CHANNEL0_CTRL_0);
}
@@ -468,23 +484,20 @@ void apbif_set_pack_mode(int ifc, int tx, int pack_mode)
check_apbif_ifc(ifc);
val = apbif_readl(ifc, APBIF_CHANNEL0_CTRL_0);
- if (tx == AUDIO_TX_MODE)
- {
+ if (tx == AUDIO_TX_MODE) {
val &= ~APBIF_CH_CTRL_TX_PACK_MASK;
val |= pack_mode << APBIF_CH_CTRL_TX_PACK_SHIFT;
val &= ~APBIF_CH_CTRL_TX_PACK_EN;
- if ((pack_mode != AUDIO_PACK_NOP) && (pack_mode != AUDIO_PACK_RSVD))
- {
+ if ((pack_mode != AUDIO_PACK_NOP) &&
+ (pack_mode != AUDIO_PACK_RSVD)) {
val |= APBIF_CH_CTRL_TX_PACK_EN;
}
- }
- else
- {
+ } else {
val &= ~APBIF_CH_CTRL_RX_PACK_MASK;
val |= pack_mode << APBIF_CH_CTRL_RX_PACK_SHIFT;
val &= ~APBIF_CH_CTRL_RX_PACK_EN;
- if ((pack_mode != AUDIO_PACK_NOP) && (pack_mode != AUDIO_PACK_RSVD))
- {
+ if ((pack_mode != AUDIO_PACK_NOP) &&
+ (pack_mode != AUDIO_PACK_RSVD)) {
val |= APBIF_CH_CTRL_RX_PACK_EN;
}
}
@@ -509,13 +522,10 @@ int apbif_fifo_set_attention_level(int ifc, int tx, unsigned level)
val = apbif_readl(ifc, APBIF_CHANNEL0_CTRL_0);
- if (tx != AUDIO_TX_MODE)
- {
+ if (tx != AUDIO_TX_MODE) {
val &= ~APBIF_CH_CTRL_RX_THRESHOLD_MASK;
val |= level << APBIF_CH_CTRL_RX_THRESHOLD_SHIFT;
- }
- else
- {
+ } else {
val &= ~APBIF_CH_CTRL_TX_THRESHOLD_MASK;
val |= level << APBIF_CH_CTRL_TX_THRESHOLD_SHIFT;
}
@@ -524,25 +534,50 @@ int apbif_fifo_set_attention_level(int ifc, int tx, unsigned level)
return 0;
}
+void apbif_fifo_write(int ifc, int fifo_mode, u32 data)
+{
+ check_apbif_ifc(ifc);
+
+ if (fifo_mode == AUDIO_TX_MODE) {
+ apbif_writel(ifc, data, APBIF_CHANNEL0_TXFIFO_0);
+ } else {
+ apbif_writel(ifc, data, APBIF_CHANNEL0_RXFIFO_0);
+ }
+}
+
+u32 apbif_fifo_read(int ifc, int fifo_mode)
+{
+ u32 val;
+
+ check_apbif_ifc(ifc, 0);
+
+ if (fifo_mode == AUDIO_TX_MODE) {
+ val = apbif_readl(ifc, APBIF_CHANNEL0_TXFIFO_0);
+ } else {
+ val = apbif_readl(ifc, APBIF_CHANNEL0_RXFIFO_0);
+ }
+
+ return val;
+}
+
/*
* Apbif soft channel reset
*/
-void apbif_soft_reset(int ifc, int tx, int enable)
+void apbif_soft_reset(int ifc, int fifo_mode, int enable)
{
u32 val;
check_apbif_ifc(ifc);
+
val = apbif_readl(ifc, APBIF_CHANNEL0_CTRL_0);
- if (tx == AUDIO_TX_MODE)
- {
+
+ if (fifo_mode == AUDIO_TX_MODE) {
set_reg_mode(val, APBIF_CH_CLEAR_TX_SOFT_RESET_EN, enable);
- }
- else
- {
+ } else {
set_reg_mode(val, APBIF_CH_CLEAR_RX_SOFT_RESET_EN, enable);
}
- apbif_writel(ifc, val, APBIF_CHANNEL0_CTRL_0);
+ apbif_writel(ifc, val, APBIF_CHANNEL0_CLEAR_0);
}
/*
@@ -559,8 +594,7 @@ int apbif_get_fifo_freecount(int ifc, int tx)
if (tx != AUDIO_TX_MODE) {
val = val >> APBIF_CH_STATUS_RX_FREE_COUNT_SHIFT;
return val & APBIF_CH_STATUS_RX_FREE_COUNT_MASK;
- }
- else {
+ } else {
val = val >> APBIF_CH_STATUS_TX_FREE_COUNT_SHIFT;
return val & APBIF_CH_STATUS_TX_FREE_COUNT_MASK;
}
@@ -580,8 +614,7 @@ int apbif_get_fifo_mode(int ifc, int tx)
if (tx != AUDIO_TX_MODE) {
val = val & APBIF_CH_STATUS_RX_TRIG;
return val >> APBIF_CH_STATUS_RX_TRIG;
- }
- else {
+ } else {
val = val & APBIF_CH_STATUS_TX_TRIG;
return val >> APBIF_CH_STATUS_TX_TRIG;
}
@@ -595,20 +628,15 @@ phys_addr_t apbif_get_fifo_phy_base(int ifc, int tx)
struct apbif_channel_info *ch = &apbif_channels[ifc];
check_apbif_ifc(ifc, 0);
- return (ch->phy_base +
- ((tx == AUDIO_TX_MODE)?APBIF_CHANNEL0_TXFIFO_0:APBIF_CHANNEL0_RXFIFO_0));
+ return (ch->phy_base + ((tx == AUDIO_TX_MODE)?
+ APBIF_CHANNEL0_TXFIFO_0:APBIF_CHANNEL0_RXFIFO_0));
}
-int apbif_get_channel(int ifc)
+int apbif_get_channel(int regindex, int fifo_mode)
{
- /* FIXME: proper code to be added based on connection being done
- Currently channel 0 being used for verification
- */
- struct apbif_channel_info *ch = &apbif_channels[ifc];
- return ch->dma_index;
+ return get_apbif_channel(regindex, fifo_mode);
}
-
static void apbif_disable_clock(void)
{
if (!acinfo) return;
@@ -649,43 +677,30 @@ fail_audio_clock:
return err;
}
-
-int apbif_initialize(int ifc, struct audio_cif *cifInfo)
+int audio_apbif_set_acif(int ifc, int fifo_mode, struct audio_cif *cifInfo)
{
struct apbif_channel_info *ch;
- /* packed mode as default */
+ ch = &apbif_channels[ifc];
- apbif_set_pack_mode(ifc, AUDIO_TX_MODE, AUDIO_PACK_16);
- apbif_set_pack_mode(ifc, AUDIO_RX_MODE, AUDIO_PACK_16);
+ if (fifo_mode == AUDIO_TX_MODE) {
+ audio_switch_set_acif((unsigned int)ch->virt_base +
+ APBIF_AUDIOCIF_TX0_CTRL_0, cifInfo);
- ch = &apbif_channels[ifc];
- ch->inuse = 1;
- ch->channel_requestor = ifc;
-
- /*set apbif acif*/
- audio_switch_set_acif((unsigned int)ch->virt_base +
- APBIF_AUDIOCIF_TX0_CTRL_0, cifInfo);
- audio_switch_set_acif((unsigned int)ch->virt_base +
- APBIF_AUDIOCIF_RX0_CTRL_0, cifInfo);
-
- /* default ahub connection */
- if (ifc == 0)
- {
- audio_switch_set_rx_port(AUDIO_I2S0_RX0_0, AUDIO_APBIF_TX0);
- audio_switch_set_rx_port(AUDIO_APBIF_RX0_0, AUDIO_I2S0_TX0);
- }
- else if (ifc == 1)
- {
- audio_switch_set_rx_port(AUDIO_I2S1_RX0_0, AUDIO_APBIF_TX1);
- audio_switch_set_rx_port(AUDIO_APBIF_RX1_0, AUDIO_I2S1_TX0);
- }
- /* FIXME: setting apdif channel 4 for spdif - this will be cleaned up */
- else if (ifc == 3)
- {
- audio_switch_set_rx_port(AUDIO_SPDIF_RX0_0, AUDIO_APBIF_TX3);
- audio_switch_set_rx_port(AUDIO_APBIF_RX3_0, AUDIO_SPDIF_TX0);
+ /* FIXME: packed mode as default */
+ apbif_set_pack_mode(ifc, AUDIO_TX_MODE, AUDIO_PACK_16);
+
+ } else {
+ audio_switch_set_acif((unsigned int)ch->virt_base +
+ APBIF_AUDIOCIF_RX0_CTRL_0, cifInfo);
+
+ /* FIXME: packed mode as default */
+ apbif_set_pack_mode(ifc, AUDIO_RX_MODE, AUDIO_PACK_16);
}
+ return 0;
+}
+int apbif_initialize(int ifc, struct audio_cif *cifInfo)
+{
return 0;
}
@@ -694,28 +709,26 @@ int audio_switch_open(void)
int err = 0, i = 0;
AHUB_DEBUG_PRINT(" audio_switch_open acinfo 0x%x enable %d ++ \n",
- (unsigned int)acinfo, enable_audioswitch);
+ (unsigned int)acinfo, enable_audioswitch);
- if (!acinfo && !enable_audioswitch)
- {
+ if (!acinfo && !enable_audioswitch) {
struct apbif_channel_info *ch;
- acinfo = kzalloc(sizeof(struct tegra_audiocont_info), GFP_KERNEL);
+ acinfo =
+ kzalloc(sizeof(struct tegra_audiocont_info), GFP_KERNEL);
+
if (!acinfo)
return -ENOMEM;
memset(apbif_channels, 0, sizeof(apbif_channels));
- for (i = 0; i < NR_APBIF_CHANNELS; i++)
- {
+ for (i = 0; i < NR_APBIF_CHANNELS; i++) {
ch = &apbif_channels[i];
ch->phy_base = TEGRA_APBIF0_BASE +
- (TEGRA_APBIF0_SIZE * i);
+ (TEGRA_APBIF0_SIZE * i);
ch->virt_base = IO_ADDRESS(TEGRA_APBIF0_BASE) +
- (TEGRA_APBIF0_SIZE * i);
+ (TEGRA_APBIF0_SIZE * i);
ch->dma_index = i + 1;
- ch->inuse = 0;
- ch->channel_requestor = 0;
}
acinfo->apbif_clk = clk_get_sys("apbif", NULL);
@@ -732,7 +745,11 @@ int audio_switch_open(void)
goto fail_audio_open;
}
- audio_hub_base = IO_ADDRESS(TEGRA_AHUB_BASE);
+ /*FIXME: add interface to set the audiohub rate and parent */
+ for (i = 0; i < ahubrx_maxnum; i++) {
+ ahub_reg_base[i] = IO_ADDRESS(TEGRA_AHUB_BASE) +
+ (i * AUDIO_APBIF_RX_OFFSET);
+ }
err = apbif_enable_clock();
@@ -745,13 +762,12 @@ int audio_switch_open(void)
acinfo->refcnt += 1;
AHUB_DEBUG_PRINT(" audio_switch_open -- acinfo 0x%x refcnt %d \n",
- (unsigned int)acinfo, acinfo->refcnt);
+ (unsigned int)acinfo, acinfo->refcnt);
return 0;
fail_audio_open:
- if (acinfo)
- {
+ if (acinfo) {
apbif_disable_clock();
kfree(acinfo);
}
@@ -761,12 +777,10 @@ fail_audio_open:
int audio_switch_close(void)
{
- if (acinfo && enable_audioswitch)
- {
+ if (acinfo && enable_audioswitch) {
acinfo->refcnt -= 1;
- if (!acinfo->refcnt)
- {
+ if (!acinfo->refcnt) {
apbif_disable_clock();
kfree(acinfo);
enable_audioswitch = 0;
diff --git a/arch/arm/mach-tegra/include/mach/audio.h b/arch/arm/mach-tegra/include/mach/audio.h
index b4ea6cae4874..2687dd508686 100644
--- a/arch/arm/mach-tegra/include/mach/audio.h
+++ b/arch/arm/mach-tegra/include/mach/audio.h
@@ -37,6 +37,7 @@
#define TEGRA_AUDIO_ENABLE_TX 1
#define TEGRA_AUDIO_ENABLE_RX 2
+#define AUDIO_FIFO_CNT 2
/*
* Audio format modes
@@ -53,16 +54,16 @@
/*
*
*/
-#define AUDIO_LRCK_LEFT_LOW 0
+#define AUDIO_LRCK_LEFT_LOW 0
#define AUDIO_LRCK_RIGHT_LOW 1
/*
* Audio Bit code - based on compression/decompression
*/
#define AUDIO_BIT_CODE_LINEAR 0
-#define AUDIO_BIT_CODE_ULAW 1
-#define AUDIO_BIT_CODE_ALAW 2
-#define AUDIO_BIT_CODE_RSVD 3
+#define AUDIO_BIT_CODE_ULAW 1
+#define AUDIO_BIT_CODE_ALAW 2
+#define AUDIO_BIT_CODE_RSVD 3
/*
* Audio channels
@@ -109,19 +110,19 @@
* Audio Mask Bits
*/
#define AUDIO_MASK_BITS_ZERO 0
-#define AUDIO_MASK_BITS_ONE 1
-#define AUDIO_MASK_BITS_TWO 2
+#define AUDIO_MASK_BITS_ONE 1
+#define AUDIO_MASK_BITS_TWO 2
#define AUDIO_MASK_BITS_THREE 3
#define AUDIO_MASK_BITS_FOUR 4
#define AUDIO_MASK_BITS_FIVE 5
-#define AUDIO_MASK_BITS_SIX 6
+#define AUDIO_MASK_BITS_SIX 6
#define AUDIO_MASK_BITS_SEVEN 7
/*
* Audio Highz control
*/
-#define AUDIO_NO_HIGHZ 0
-#define AUDIO_HIGHZ 1
+#define AUDIO_NO_HIGHZ 0
+#define AUDIO_HIGHZ 1
#define AUDIO_HIGHZ_HALF_BIT_CLK 2
/*
diff --git a/arch/arm/mach-tegra/include/mach/audio_switch.h b/arch/arm/mach-tegra/include/mach/audio_switch.h
index 770fcbafe472..7d58cfef3fe1 100644
--- a/arch/arm/mach-tegra/include/mach/audio_switch.h
+++ b/arch/arm/mach-tegra/include/mach/audio_switch.h
@@ -28,7 +28,7 @@
#include <linux/types.h>
#define AUDIOCIF_EXPAND_ZERO 0
-#define AUDIOCIF_EXPAND_ONE 1
+#define AUDIOCIF_EXPAND_ONE 1
#define AUDIOCIF_EXPAND_LFSR 2
#define AUDIO_PACK_NOP 0
@@ -38,10 +38,51 @@
/* generic macro to set modes */
#define set_reg_mode(r,m,v) { \
- ((r) &= (~(m))); \
- ((r) |= (v)?(m):(0)); \
+ ((r) &= (~(m))); \
+ ((r) |= (v)?(m):(0)); \
}
+typedef enum ahubtx_
+{
+ ahubtx0_apbif = 0,
+ ahubtx1_apbif,
+ ahubtx2_apbif,
+ ahubtx3_apbif,
+ ahubtx_i2s0,
+ ahubtx_i2s1,
+ ahubtx_i2s2,
+ ahubtx_i2s3,
+ ahubtx_i2s4,
+ ahubtx_dam0,
+ ahubtx_dam1,
+ ahubtx_dam2,
+ ahubtx0_spdif,
+ ahubtx1_spdif,
+ ahubtx_maxnum
+} ahubtx;
+
+typedef enum ahubrx_
+{
+ ahubrx0_apbif = 0x0,
+ ahubrx1_apbif,
+ ahubrx2_apbif,
+ ahubrx3_apbif,
+ ahubrx_i2s0,
+ ahubrx_i2s1,
+ ahubrx_i2s2,
+ ahubrx_i2s3,
+ ahubrx_i2s4,
+ ahubrx0_dam0,
+ ahubrx1_dam0,
+ ahubrx0_dam1,
+ ahubrx1_dam1,
+ ahubrx0_dam2,
+ ahubrx1_dam2,
+ ahubrx0_spdif,
+ ahubrx1_spdif,
+ ahubrx_maxnum
+} ahubrx;
+
struct audio_cif
{
int threshold;
@@ -70,12 +111,19 @@ int apbif_fifo_set_attention_level(int ifc, int tx, unsigned level);
void apbif_set_pack_mode(int ifc, int tx, int pack_mode);
void apbif_channel_set_loopback(int ifc, int on);
void apbif_channel_enable(int ifc, int tx, int enable);
-int apbif_get_channel(int ifc);
+int apbif_get_channel(int regindex, int fifo_mode);
int apbif_initialize(int ifc, struct audio_cif *cifInfo);
+void apbif_soft_reset(int ifc, int fifo_mode, int enable);
+void apbif_fifo_write(int ifc, int fifo_mode, u32 data);
+u32 apbif_fifo_read(int ifc, int fifo_mode);
void audio_switch_set_acif(int addr, struct audio_cif *cifInfo);
int audio_switch_get_rx_port(int rxport);
void audio_switch_set_rx_port(int rxport, int txport);
-int audio_switch_close(void);
-int audio_switch_open(void);
+
+int audio_switch_close(void);
+int audio_switch_open(void);
+int audio_apbif_free_channel(int ifc, int fifo_mode);
+int audio_apbif_set_acif(int ifc, int fifo_mode, struct audio_cif *cifInfo);
+
#endif /* __ARCH_ARM_MACH_AUDIO_SWITCH_H */
diff --git a/arch/arm/mach-tegra/include/mach/spdif.h b/arch/arm/mach-tegra/include/mach/spdif.h
index 10bf65660446..612db56255bb 100644
--- a/arch/arm/mach-tegra/include/mach/spdif.h
+++ b/arch/arm/mach-tegra/include/mach/spdif.h
@@ -487,7 +487,7 @@ int spdif_fifo_set_attention_level(unsigned long base,
int mode,
unsigned int level);
void spdif_fifo_clear(unsigned long base, int mode);
-u32 spdif_get_status(unsigned long base);
+u32 spdif_get_status(unsigned long base, int mode);
u32 spdif_get_control(unsigned long base);
void spdif_ack_status(unsigned long base);
u32 spdif_get_fifo_scr(unsigned long base);
@@ -496,6 +496,6 @@ u32 spdif_get_fifo_full_empty_count(unsigned long base, int mode);
int spdif_initialize(unsigned long base, int mode);
void spdif_get_all_regs(unsigned long base, struct spdif_regs_cache* regs);
void spdif_set_all_regs(unsigned long base, struct spdif_regs_cache* regs);
-int spdif_get_dma_requestor(int ifc);
+int spdif_get_dma_requestor(int ifc, int mode);
#endif /* __ARCH_ARM_MACH_TEGRA_SPDIF_H */
diff --git a/arch/arm/mach-tegra/include/mach/tegra2_i2s.h b/arch/arm/mach-tegra/include/mach/tegra2_i2s.h
index 5bfbfb15ccdb..f37b96cc04be 100644
--- a/arch/arm/mach-tegra/include/mach/tegra2_i2s.h
+++ b/arch/arm/mach-tegra/include/mach/tegra2_i2s.h
@@ -302,7 +302,7 @@ void i2s_set_fifo_irq_on_qe(int ifc, int fifo, int on);
void i2s_enable_fifos(int ifc, int on);
void i2s_fifo_write(int ifc, int fifo, u32 data);
u32 i2s_fifo_read(int ifc, int fifo);
-u32 i2s_get_status(int ifc);
+u32 i2s_get_status(int ifc, int fifo);
u32 i2s_get_control(int ifc);
void i2s_ack_status(int ifc);
u32 i2s_get_fifo_scr(int ifc);
@@ -310,6 +310,7 @@ u32 i2s_get_fifo_full_empty_count(int ifc, int fifo);
phys_addr_t i2s_get_fifo_phy_base(int ifc, int fifo);
struct clk *i2s_get_clock_by_name(const char *name);
int i2s_initialize(int ifc);
-int i2s_get_dma_requestor(int ifc);
+int i2s_get_dma_requestor(int ifc, int fifo_mode);
+int i2s_free_dma_requestor(int ifc, int fifo_mode);
#endif /* __ARCH_ARM_MACH_TEGRA_I2S_H */
diff --git a/arch/arm/mach-tegra/include/mach/tegra3_i2s.h b/arch/arm/mach-tegra/include/mach/tegra3_i2s.h
index bc2f8d42f280..763ae9770eb9 100644
--- a/arch/arm/mach-tegra/include/mach/tegra3_i2s.h
+++ b/arch/arm/mach-tegra/include/mach/tegra3_i2s.h
@@ -40,13 +40,13 @@
/* Register Offsets from TEGRA_I2S_BASE */
-#define I2S_CTRL_0 0x0
+#define I2S_CTRL_0 0x0
#define I2S_TIMING_0 0x4
#define I2S_OFFSET_0 0x08
#define I2S_CH_CTRL_0 0x0c
#define I2S_SLOT_CTRL_0 0x10
-#define I2S_AUDIOCIF_I2STX_CTRL_0 0x14
-#define I2S_AUDIOCIF_I2SRX_CTRL_0 0x18
+#define I2S_AUDIOCIF_I2STX_CTRL_0 0x14
+#define I2S_AUDIOCIF_I2SRX_CTRL_0 0x18
#define I2S_FLOWCTL_0 0x1c
#define I2S_TX_STEP_0 0x20
#define I2S_FLOW_STATUS_0 0x24
@@ -70,11 +70,11 @@
#define I2S_CTRL_XFER_EN_RX (1<<30)
#define I2S_CTRL_CG_EN (1<<29)
#define I2S_CTRL_SOFT_RESET (1<<28)
-#define I2S_CTRL_TX_FLOWCTL_EN (1<<27)
+#define I2S_CTRL_TX_FLOWCTL_EN (1<<27)
#define I2S_CTRL_OBS_SEL (1<<24)
-#define I2S_CTRL_FRAME_FORMAT_SHIFT 12
-#define I2S_CTRL_FRAME_FORMAT_MASK \
+#define I2S_CTRL_FRAME_FORMAT_SHIFT 12
+#define I2S_CTRL_FRAME_FORMAT_MASK \
(0x3<<I2S_CTRL_FRAME_FORMAT_SHIFT);
#define I2S_CTRL_FRAME_FORMAT_LRCK \
(0<<I2S_CTRL_FRAME_FORMAT_SHIFT) /* BASIC/LJM/RJM */
@@ -89,9 +89,9 @@
*/
#define I2S_LRCK_SHIFT 9
-#define I2S_CTRL_LRCK_MASK (1<<I2S_LRCK_SHIFT)
-#define I2S_CTRL_LRCK_L_LOW (AUDIO_LRCK_LEFT_LOW << I2S_LRCK_SHIFT)
-#define I2S_CTRL_LRCK_R_LOW (AUDIO_LRCK_RIGHT_LOW << I2S_LRCK_SHIFT)
+#define I2S_CTRL_LRCK_MASK (1<<I2S_LRCK_SHIFT)
+#define I2S_CTRL_LRCK_L_LOW (AUDIO_LRCK_LEFT_LOW << I2S_LRCK_SHIFT)
+#define I2S_CTRL_LRCK_R_LOW (AUDIO_LRCK_RIGHT_LOW << I2S_LRCK_SHIFT)
#define I2S_CTRL_LPBK_ENABLE (1<<8)
@@ -107,10 +107,10 @@
#define I2S_CTRL_BIT_CODE_RSVD \
(AUDIO_BIT_CODE_RSVD<<I2S_CTRL_BIT_CODE_SHIFT)
-#define I2S_CTRL_BIT_SIZE_SHIFT 0
+#define I2S_CTRL_BIT_SIZE_SHIFT 0
#define I2S_CTRL_BIT_SIZE_MASK (0x7 << I2S_CTRL_BIT_SIZE_SHIFT)
-#define I2S_CTRL_BIT_SIZE_8 \
+#define I2S_CTRL_BIT_SIZE_8 \
(AUDIO_BIT_SIZE_8 << I2S_CTRL_BIT_SIZE_SHIFT)
#define I2S_CTRL_BIT_SIZE_12 \
(AUDIO_BIT_SIZE_12 << I2S_CTRL_BIT_SIZE_SHIFT)
@@ -130,7 +130,7 @@
* I2S_TIMING_0
*/
-#define I2S_TIMING_NON_SYM_ENABLE (1<<12)
+#define I2S_TIMING_NON_SYM_ENABLE (1<<12)
#define I2S_TIMING_CHANNEL_BIT_COUNT_MASK 0x7ff
#define I2S_TIMING_CHANNEL_BIT_COUNT (1<<0)
@@ -167,15 +167,15 @@
/*
* Highz control
*/
-#define I2S_CH_CTRL_HIGHZ_CTRL_SHIFT 12
+#define I2S_CH_CTRL_HIGHZ_CTRL_SHIFT 12
#define I2S_CH_CTRL_HIGHZ_CTRL_MASK \
(3 << I2S_CH_CTRL_HIGHZ_CTRL_SHIFT)
/*
* BIT_ORDER
*/
-#define I2S_CH_CTRL_RX_BIT_ORDER_SHIFT 10
-#define I2S_CH_CTRL_TX_BIT_ORDER_SHIFT 9
+#define I2S_CH_CTRL_RX_BIT_ORDER_SHIFT 10
+#define I2S_CH_CTRL_TX_BIT_ORDER_SHIFT 9
#define I2S_CH_CTRL_RX_BIT_MSB_FIRST \
(AUDIO_BIT_ORDER_MSB_FIRST << I2S_CH_CTRL_RX_BIT_ORDER_SHIFT)
#define I2S_CH_CTRL_TX_BIT_MSB_FIRST \
@@ -201,15 +201,15 @@
#define I2S_CH_CTRL_TX_MASK_BITS_SHIFT 0
-#define I2S_CH_CTRL_RX_MASK_BITS_MASK \
+#define I2S_CH_CTRL_RX_MASK_BITS_MASK \
(7 << I2S_CH_CTRL_RX_MASK_BITS_SHIFT)
-#define I2S_CH_CTRL_RX_MASK_BITS_ZERO \
+#define I2S_CH_CTRL_RX_MASK_BITS_ZERO \
(AUDIO_MASK_BITS_ZERO << I2S_CH_CTRL_RX_MASK_BITS_SHIFT)
-#define I2S_CH_CTRL_RX_MASK_BITS_ONE \
+#define I2S_CH_CTRL_RX_MASK_BITS_ONE \
(AUDIO_MASK_BITS_ONE << I2S_CH_CTRL_RX_MASK_BITS_SHIFT)
-#define I2S_CH_CTRL_RX_MASK_BITS_TWO \
+#define I2S_CH_CTRL_RX_MASK_BITS_TWO \
(AUDIO_MASK_BITS_TWO << I2S_CH_CTRL_RX_MASK_BITS_SHIFT)
-#define I2S_CH_CTRL_RX_MASK_BITS_THREE \
+#define I2S_CH_CTRL_RX_MASK_BITS_THREE \
(AUDIO_MASK_BITS_THREE << I2S_CH_CTRL_RX_MASK_BITS_SHIFT)
#define I2S_CH_CTRL_RX_MASK_BITS_FOUR \
(AUDIO_MASK_BITS_FOUR << I2S_CH_CTRL_RX_MASK_BITS_SHIFT)
@@ -220,15 +220,15 @@
#define I2S_CH_CTRL_RX_MASK_BITS_SEVEN \
(AUDIO_MASK_BITS_SEVEN << I2S_CH_CTRL_RX_MASK_BITS_SHIFT)
-#define I2S_CH_CTRL_TX_MASK_BITS_MASK \
+#define I2S_CH_CTRL_TX_MASK_BITS_MASK \
(7 << I2S_CH_CTRL_TX_MASK_BITS_SHIFT)
-#define I2S_CH_CTRL_TX_MASK_BITS_ZERO \
+#define I2S_CH_CTRL_TX_MASK_BITS_ZERO \
(AUDIO_MASK_BITS_ZERO << I2S_CH_CTRL_TX_MASK_BITS_SHIFT)
-#define I2S_CH_CTRL_TX_MASK_BITS_ONE \
+#define I2S_CH_CTRL_TX_MASK_BITS_ONE \
(AUDIO_MASK_BITS_ONE << I2S_CH_CTRL_TX_MASK_BITS_SHIFT)
-#define I2S_CH_CTRL_TX_MASK_BITS_TWO \
+#define I2S_CH_CTRL_TX_MASK_BITS_TWO \
(AUDIO_MASK_BITS_TWO << I2S_CH_CTRL_TX_MASK_BITS_SHIFT)
-#define I2S_CH_CTRL_TX_MASK_BITS_THREE \
+#define I2S_CH_CTRL_TX_MASK_BITS_THREE \
(AUDIO_MASK_BITS_THREE << I2S_CH_CTRL_TX_MASK_BITS_SHIFT)
#define I2S_CH_CTRL_TX_MASK_BITS_FOUR \
(AUDIO_MASK_BITS_FOUR << I2S_CH_CTRL_TX_MASK_BITS_SHIFT)
@@ -245,9 +245,9 @@
* 1 - frame with 2 slot
* n - frame with n+1 slot
*/
-#define I2S_SLOT_CTRL_TOTAL_SLOT_SHIFT 16
-#define I2S_SLOT_CTRL_RX_SLOT_SHIFT 8
-#define I2S_SLOT_CTRL_TX_SLOT_SHIFT 0
+#define I2S_SLOT_CTRL_TOTAL_SLOT_SHIFT 16
+#define I2S_SLOT_CTRL_RX_SLOT_SHIFT 8
+#define I2S_SLOT_CTRL_TX_SLOT_SHIFT 0
#define I2S_SLOT_CTRL_TOTAL_SLOT_MASK \
(7 << I2S_SLOT_CTRL_TOTAL_SLOT_SHIFT)
@@ -271,8 +271,8 @@
/*
* Flow control
*/
-#define I2S_FLOWCTL_FILTER_SHIFT 31
-#define I2S_FLOWCTL_FILTER_LINEAR \
+#define I2S_FLOWCTL_FILTER_SHIFT 31
+#define I2S_FLOWCTL_FILTER_LINEAR \
(0 << I2S_FLOWCTL_FILTER_SHIFT)
#define I2S_FLOWCTL_FILTER_QUAD \
(1 << I2S_FLOWCTL_FILTER_SHIFT)
@@ -280,7 +280,7 @@
/*
* Tx Step
*/
-#define I2S_TX_STEP_SHIFT 0
+#define I2S_TX_STEP_SHIFT 0
#define I2S_TX_STEP_MASK \
(0xffff << I2S_TX_STEP_SHIFT)
@@ -289,18 +289,15 @@
*/
#define I2S_FLOW_STATUS_UNDERFLOW_UNDER (1<<31)
#define I2S_FLOW_STATUS_OVERFLOW_OVER (1<<30)
-#define I2S_FLOW_MONITOR_INT_EN (1<<4)
-#define I2S_FLOW_COUNTER_EN (1<<1)
-#define I2S_FLOW_MONITOR_EN (1<<0)
+#define I2S_FLOW_MONITOR_INT_EN (1<<4)
+#define I2S_FLOW_COUNTER_EN (1<<1)
+#define I2S_FLOW_MONITOR_EN (1<<0)
/*
* coefficients
*/
#define I2S_LCOEF_COEF_MASK (0xffff<<0)
-/* FIXME: temporarily added attn level
-* this will be part of apbif fifo
-*/
#define I2S_FIFO_ATN_LVL_FOUR_SLOTS 4
#define I2S_FIFO_ATN_LVL_EIGHT_SLOTS 8
#define I2S_FIFO_ATN_LVL_ONE_SLOT 1
@@ -357,18 +354,19 @@ int i2s_set_bit_code(int ifc, unsigned bitcode);
int i2s_set_bit_format(int ifc, unsigned fmt);
int i2s_set_bit_size(int ifc, unsigned bit_size);
int i2s_set_channel_bit_count(int ifc, int sampling, int bitclk);
-int i2s_set_data_offset(int ifc, int tx, int dataoffset);
-int i2s_set_edge_control(int ifc, int edgectrl);
-int i2s_set_highz_control(int ifc, int highzvalue);
-int i2s_set_fsync_width(int ifc, int fifo, int fsyncwidth);
-int i2s_set_slot_control(int ifc, int tx, int totalslot, int numslots);
-int i2s_set_bit_order(int ifc, int tx, int bitorder);
-int i2s_set_bit_mask(int ifc, int tx, int maskbit);
-int i2s_set_flow_control(int ifc, int enable, int filtertype, int stepsize);
-int i2s_initialize(int ifc);
+int i2s_set_data_offset(int ifc, int tx, int dataoffset);
+int i2s_set_edge_control(int ifc, int edgectrl);
+int i2s_set_highz_control(int ifc, int highzvalue);
+int i2s_set_fsync_width(int ifc, int fifo, int fsyncwidth);
+int i2s_set_slot_control(int ifc, int tx, int totalslot, int numslots);
+int i2s_set_bit_order(int ifc, int tx, int bitorder);
+int i2s_set_bit_mask(int ifc, int tx, int maskbit);
+int i2s_set_flow_control(int ifc, int enable, int filtertype, int stepsize);
+int i2s_initialize(int ifc);
phys_addr_t i2s_get_fifo_phy_base(int ifc, int fifo);
struct clk *i2s_get_clock_by_name(const char *name);
-int i2s_get_dma_requestor(int ifc);
+int i2s_get_dma_requestor(int ifc, int fifo_mode);
+int i2s_free_dma_requestor(int ifc, int fifo_mode);
/*
* FIXME: recheck how much of these apis needed, need to check with
* audio switch apbif apis.
@@ -380,11 +378,12 @@ void i2s_set_fifo_irq_on_qe(int ifc, int fifo, int on);
void i2s_enable_fifos(int ifc, int on);
void i2s_fifo_write(int ifc, int fifo, u32 data);
u32 i2s_fifo_read(int ifc, int fifo);
-u32 i2s_get_status(int ifc);
+u32 i2s_get_status(int ifc, int fifo);
u32 i2s_get_control(int ifc);
void i2s_ack_status(int ifc);
u32 i2s_get_fifo_scr(int ifc);
u32 i2s_get_fifo_full_empty_count(int ifc, int fifo);
+int i2s_set_acif(int ifc, int fifo_mode, struct audio_cif *cifInfo);
#endif /* __ARCH_ARM_MACH_TEGRA3_I2S_H */
diff --git a/arch/arm/mach-tegra/spdif.c b/arch/arm/mach-tegra/spdif.c
index f65dda4ed526..901ba540e692 100644
--- a/arch/arm/mach-tegra/spdif.c
+++ b/arch/arm/mach-tegra/spdif.c
@@ -51,33 +51,6 @@ static inline u32 spdif_readl(unsigned long base, u32 reg)
return val;
}
-void spdif_fifo_enable(unsigned long base, int mode, int on)
-{
- u32 val = 0;
-
- /*FIXME: change the fixed channel index later */
-#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
-
- int ifc = 3;
- apbif_channel_enable(ifc, mode, on);
-
-#endif
- val = spdif_readl(base, SPDIF_CTRL_0);
- if (mode == AUDIO_TX_MODE)
- {
- val &= ~(SPDIF_CTRL_0_TU_EN | SPDIF_CTRL_0_TC_EN | SPDIF_CTRL_0_TX_EN);
- val |= on ? (SPDIF_CTRL_0_TX_EN) : 0;
- val |= on ? (SPDIF_CTRL_0_TC_EN) : 0;
- }
- if (mode == AUDIO_RX_MODE)
- {
- val &= ~SPDIF_CTRL_0_RX_EN;
- val |= on ? (SPDIF_CTRL_0_RX_EN) : 0;
- }
-
- spdif_writel(base, val, SPDIF_CTRL_0);
-}
-
int spdif_set_bit_mode(unsigned long base, unsigned mode)
{
u32 val = spdif_readl(base, SPDIF_CTRL_0);
@@ -147,18 +120,14 @@ u32 spdif_get_control(unsigned long base)
void spdif_fifo_write(unsigned long base, int mode, u32 data)
{
- if (mode == AUDIO_TX_MODE)
- {
+ if (mode == AUDIO_TX_MODE) {
spdif_writel(base, data, SPDIF_DATA_OUT_0);
- }
- if (mode == AUDIO_RX_MODE)
- {
+ } else {
spdif_writel(base, data, SPDIF_DATA_IN_0);
}
}
-int spdif_fifo_set_attention_level(unsigned long base, int mode,
- unsigned level)
+int spdif_fifo_set_attention_level(unsigned long base, int mode, unsigned level)
{
u32 val;
@@ -170,8 +139,7 @@ int spdif_fifo_set_attention_level(unsigned long base, int mode,
val = spdif_readl(base, SPDIF_DATA_FIFO_CSR_0);
- if (mode == AUDIO_TX_MODE)
- {
+ if (mode == AUDIO_TX_MODE) {
val &= ~SPDIF_DATA_FIFO_CSR_0_TX_ATN_LVL_MASK;
val |= level << SPDIF_DATA_FIFO_CSR_0_TX_ATN_LVL_SHIFT;
}
@@ -183,10 +151,12 @@ int spdif_fifo_set_attention_level(unsigned long base, int mode,
void spdif_fifo_clear(unsigned long base, int mode)
{
u32 val = spdif_readl(base, SPDIF_DATA_FIFO_CSR_0);
- if (mode == AUDIO_TX_MODE)
- {
- val &= ~(SPDIF_DATA_FIFO_CSR_0_TX_CLR | SPDIF_DATA_FIFO_CSR_0_TU_CLR);
- val |= SPDIF_DATA_FIFO_CSR_0_TX_CLR | SPDIF_DATA_FIFO_CSR_0_TU_CLR;
+
+ if (mode == AUDIO_TX_MODE) {
+ val &= ~(SPDIF_DATA_FIFO_CSR_0_TX_CLR |
+ SPDIF_DATA_FIFO_CSR_0_TU_CLR);
+ val |= SPDIF_DATA_FIFO_CSR_0_TX_CLR |
+ SPDIF_DATA_FIFO_CSR_0_TU_CLR;
}
spdif_writel(base, val, SPDIF_DATA_FIFO_CSR_0);
}
@@ -201,7 +171,7 @@ int spdif_set_fifo_packed(unsigned long base, unsigned on)
return 0;
}
-u32 spdif_get_status(unsigned long base)
+u32 spdif_get_status(unsigned long base, int mode)
{
return spdif_readl(base, SPDIF_STATUS_0);
}
@@ -231,8 +201,7 @@ u32 spdif_get_fifo_full_empty_count(unsigned long base, int mode)
{
u32 val = spdif_readl(base, SPDIF_DATA_FIFO_CSR_0);
- if (mode == AUDIO_TX_MODE)
- {
+ if (mode == AUDIO_TX_MODE) {
val = val >> SPDIF_DATA_FIFO_CSR_0_TD_EMPTY_COUNT_SHIFT;
return val & SPDIF_DATA_FIFO_CSR_0_TD_EMPTY_COUNT_MASK;
}
@@ -240,7 +209,7 @@ u32 spdif_get_fifo_full_empty_count(unsigned long base, int mode)
return 0;
}
-int spdif_get_dma_requestor(int ifc)
+int spdif_get_dma_requestor(int ifc, int fifo_mode)
{
return TEGRA_DMA_REQ_SEL_SPD_I;
}
@@ -305,6 +274,20 @@ void spdif_set_all_regs(unsigned long base, struct spdif_regs_cache* regs)
}
#else
+struct spdif_controller_info {
+/*FIXME: add clock here or move the struct to common place */
+ int dma_ch[AUDIO_FIFO_CNT];
+ int stream_index[AUDIO_FIFO_CNT];
+ unsigned int base;
+};
+
+static struct spdif_controller_info spdif_cont_info;
+
+static int spdif_get_apbif_channel(int fifo_mode)
+{
+ return spdif_cont_info.dma_ch[fifo_mode];
+}
+
int spdif_set_fifo_packed(unsigned long base, unsigned on)
{
/* This register is obsolete after T20 */
@@ -313,29 +296,43 @@ int spdif_set_fifo_packed(unsigned long base, unsigned on)
void spdif_fifo_write(unsigned long base, int mode, u32 data)
{
- /*FIXME: add apbif call here */
+ int apbif_ifc = spdif_get_apbif_channel(mode);
+
+ if (apbif_ifc != -ENOENT)
+ apbif_fifo_write(apbif_ifc, mode, data);
}
int spdif_fifo_set_attention_level(unsigned long base, int mode,
unsigned level)
{
- /*FIXME: currently used apbif channel 4 for spdif*/
- int ifc = 3;
+ int apbif_ifc = spdif_get_apbif_channel(mode);
+
/* expected the level as four slots now */
level = SPDIF_FIFO_ATN_LVL_FOUR_SLOTS;
- return apbif_fifo_set_attention_level(ifc, mode, level);
+
+ if (apbif_ifc != -ENOENT)
+ return apbif_fifo_set_attention_level(apbif_ifc,
+ mode, (level - 1));
+
+ return 0;
}
void spdif_fifo_clear(unsigned long base, int mode)
{
- /*FIXME: add apbif call here */
+ int apbif_ifc = spdif_get_apbif_channel(mode);
+
+ if (apbif_ifc != -ENOENT)
+ apbif_soft_reset(apbif_ifc, mode, 1);
}
-u32 spdif_get_status(unsigned long base)
+u32 spdif_get_status(unsigned long base, int mode)
{
- /*FIXME: currently used apbif channel 4 for spdif*/
- int ifc = 3;
- return apbif_get_fifo_mode(ifc, AUDIO_TX_MODE);;
+ int apbif_ifc = spdif_get_apbif_channel(mode);
+
+ if (apbif_ifc != -ENOENT)
+ return apbif_get_fifo_mode(apbif_ifc, mode);
+
+ return 0;
}
void spdif_ack_status(unsigned long base)
@@ -351,29 +348,88 @@ u32 spdif_get_fifo_scr(unsigned long base)
phys_addr_t spdif_get_fifo_phy_base(phys_addr_t phy_base, int mode)
{
- /*FIXME: currently used apbif channel 4 for spdif*/
- int ifc = 3;
- return apbif_get_fifo_phy_base(ifc, mode);
+ int apbif_ifc = spdif_get_apbif_channel(mode);
+
+ if (apbif_ifc != -ENOENT)
+ return apbif_get_fifo_phy_base(apbif_ifc, mode);
+
+ return 0;
}
u32 spdif_get_fifo_full_empty_count(unsigned long base, int mode)
{
- /*FIXME: add apbif call here */
+ int apbif_ifc = spdif_get_apbif_channel(mode);
+
+ if (apbif_ifc != -ENOENT)
+ return apbif_get_fifo_freecount(apbif_ifc, mode);
+
return 0;
}
-int spdif_get_dma_requestor(int ifc)
+int spdif_free_dma_requestor(int ifc, int fifo_mode)
{
- /*FIXME: currently used apbif channel 4 for spdif*/
- ifc = 3;
- return apbif_get_channel(ifc);
+ int apbif_ifc = spdif_get_apbif_channel(fifo_mode);
+
+ if (apbif_ifc != -ENOENT)
+ audio_apbif_free_channel(apbif_ifc, fifo_mode);
+
+ return 0;
}
static struct audio_cif spdif_audiocif;
-int spdif_initialize(unsigned long base, int mode)
+
+int spdif_set_acif(int fifo_mode, struct audio_cif *cifInfo)
{
struct audio_cif *tx_audio_cif = &spdif_audiocif;
- int ifc = 3, err = 0;
+
+ /* set spdif audiocif */
+ /* setting base value for acif */
+ memset(tx_audio_cif, 0 , sizeof(struct audio_cif));
+ tx_audio_cif->audio_channels = AUDIO_CHANNEL_2;
+ tx_audio_cif->client_channels = AUDIO_CHANNEL_2;
+ tx_audio_cif->audio_bits = AUDIO_BIT_SIZE_16;
+ tx_audio_cif->client_bits = AUDIO_BIT_SIZE_16;
+
+ if (fifo_mode == AUDIO_TX_MODE)
+ audio_switch_set_acif(spdif_cont_info.base +
+ SPDIF_AUDIOCIF_TXDATA_CTRL_0, tx_audio_cif);
+ else
+ audio_switch_set_acif(spdif_cont_info.base +
+ SPDIF_AUDIOCIF_RXDATA_CTRL_0, tx_audio_cif);
+
+ audio_apbif_set_acif(spdif_get_apbif_channel(fifo_mode),
+ fifo_mode, tx_audio_cif);
+
+ return 0;
+}
+
+int spdif_get_dma_requestor(int ifc, int fifo_mode)
+{
+ int dma_index = 0;
+ int apbif_ifc = ahubtx0_spdif;
+
+ if (fifo_mode == AUDIO_RX_MODE)
+ apbif_ifc = ahubrx0_spdif;
+
+ dma_index = apbif_get_channel(apbif_ifc, fifo_mode);
+
+ if (dma_index != -ENOENT) {
+ spdif_cont_info.dma_ch[fifo_mode] = dma_index - 1;
+ /* FIXME : this need to be called on connection request
+ */
+ spdif_set_acif(fifo_mode, 0);
+ }
+
+ return dma_index;
+}
+
+int spdif_initialize(unsigned long base, int mode)
+{
+ int err = 0;
+
+ spdif_cont_info.dma_ch[0] = -ENOENT;
+ spdif_cont_info.dma_ch[1] = -ENOENT;
+ spdif_cont_info.base = base;
err = audio_switch_open();
if (err)
@@ -383,25 +439,6 @@ int spdif_initialize(unsigned long base, int mode)
spdif_writel(base, 0x0, SPDIF_CTRL_0);
spdif_fifo_clear(base, mode);
- /* FIXME: move all the apbif call to a generic function
- inside audio_switch code - temporarily added here to
- get minimum audio function working
- */
-
- /* set spdif audiocif */
- /* setting base value for acif */
- memset(tx_audio_cif, 0 , sizeof(struct audio_cif));
- tx_audio_cif->audio_channels = AUDIO_CHANNEL_2;
- tx_audio_cif->client_channels = AUDIO_CHANNEL_2;
- tx_audio_cif->audio_bits = AUDIO_BIT_SIZE_16;
- tx_audio_cif->client_bits = AUDIO_BIT_SIZE_16;
- audio_switch_set_acif(base +
- SPDIF_AUDIOCIF_TXDATA_CTRL_0, tx_audio_cif);
- audio_switch_set_acif(base +
- SPDIF_AUDIOCIF_RXDATA_CTRL_0, tx_audio_cif);
-
- apbif_initialize(ifc, tx_audio_cif);
-
spdif_fifo_enable(base, mode, 0);
spdif_set_bit_mode(base, SPDIF_BIT_MODE_MODE16BIT);
@@ -411,5 +448,31 @@ int spdif_initialize(unsigned long base, int mode)
return 0;
}
+#endif
+
+void spdif_fifo_enable(unsigned long base, int mode, int on)
+{
+ u32 val = 0;
+#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
+
+ int apbif_ifc = spdif_get_apbif_channel(mode);
+
+ if (apbif_ifc == -ENOENT)
+ return;
+
+ apbif_channel_enable(apbif_ifc, mode, on);
#endif
+
+ val = spdif_readl(base, SPDIF_CTRL_0);
+
+ if (mode == AUDIO_TX_MODE) {
+ val &= ~(SPDIF_CTRL_0_TU_EN);
+ set_reg_mode(val, SPDIF_CTRL_0_TC_EN, on);
+ set_reg_mode(val, SPDIF_CTRL_0_TX_EN, on);
+ } else {
+ set_reg_mode(val, SPDIF_CTRL_0_RX_EN, on);
+ }
+
+ spdif_writel(base, val, SPDIF_CTRL_0);
+}
diff --git a/arch/arm/mach-tegra/tegra2_i2s.c b/arch/arm/mach-tegra/tegra2_i2s.c
index 4474751353ff..a23992a96df0 100644
--- a/arch/arm/mach-tegra/tegra2_i2s.c
+++ b/arch/arm/mach-tegra/tegra2_i2s.c
@@ -450,7 +450,7 @@ u32 i2s_fifo_read(int ifc, int fifo)
return i2s_readl(ifc, fifo ? I2S_I2S_FIFO2_0 : I2S_I2S_FIFO1_0);
}
-u32 i2s_get_status(int ifc)
+u32 i2s_get_status(int ifc, int fifo)
{
check_ifc(ifc, 0);
return i2s_readl(ifc, I2S_I2S_STATUS_0);
@@ -515,7 +515,13 @@ int i2s_initialize(int ifc)
return 0;
}
-int i2s_get_dma_requestor(int ifc)
+int i2s_free_dma_requestor(int ifc, int fifo)
+{
+ /* NULL function */
+ return 0;
+}
+
+int i2s_get_dma_requestor(int ifc, int fifo)
{
return ((ifc)? 1 : 2); /* 1 = I2S2, 2 = I2S1 */
}
diff --git a/arch/arm/mach-tegra/tegra3_i2s.c b/arch/arm/mach-tegra/tegra3_i2s.c
index 784969c295e1..7c2f21dde22a 100644
--- a/arch/arm/mach-tegra/tegra3_i2s.c
+++ b/arch/arm/mach-tegra/tegra3_i2s.c
@@ -38,6 +38,17 @@
#define I2S_DEBUG_PRINT(fmt, arg...) do {} while (0)
#endif
+struct i2s_controller_info {
+/*FIXME: add clock here or move the struct to common place
+ Make use of tegra_i2s_channel_property & tegra_i2s_property
+ struct defined in the i2s header
+*/
+ int dma_ch[AUDIO_FIFO_CNT];
+ int stream_index[AUDIO_FIFO_CNT];
+};
+
+static struct i2s_controller_info i2s_cont_info[NR_I2S_IFC];
+
static void *i2s_base[NR_I2S_IFC] = {
IO_ADDRESS(TEGRA_I2S0_BASE),
IO_ADDRESS(TEGRA_I2S1_BASE),
@@ -50,17 +61,25 @@ static inline void i2s_writel(int ifc, u32 val, u32 reg)
{
I2S_DEBUG_PRINT("i2s Write 0x%x : %08x\n",
(unsigned int)i2s_base[ifc] + reg, val);
+
__raw_writel(val, i2s_base[ifc] + reg);
}
static inline u32 i2s_readl(int ifc, u32 reg)
{
u32 val = __raw_readl(i2s_base[ifc] + reg);
+
I2S_DEBUG_PRINT("i2s Read 0x%x : %08x\n",
(unsigned int) i2s_base[ifc] + reg, val);
+
return val;
}
+static int i2s_get_apbif_channel(int ifc, int fifo_mode)
+{
+ return i2s_cont_info[ifc].dma_ch[fifo_mode];
+}
+
void i2s_dump_registers(int ifc)
{
check_i2s_ifc(ifc);
@@ -88,21 +107,22 @@ void i2s_set_all_regs(int ifc, struct i2s_runtime_data* ird)
void i2s_fifo_enable(int ifc, int tx, int enable)
{
u32 val;
+ int apbif_ifc = 0;
check_i2s_ifc(ifc);
- /* FIXME : this is to moved to a common
- place in the audio_switch call
- */
- apbif_channel_enable(ifc, tx, enable);
+ apbif_ifc = i2s_get_apbif_channel(ifc, tx);
+
+ apbif_channel_enable(apbif_ifc, tx, enable);
val = i2s_readl(ifc, I2S_CTRL_0);
- if (tx != I2S_FIFO_TX) { /* receive */
+
+ if (tx != I2S_FIFO_TX) {
set_reg_mode(val, I2S_CTRL_XFER_EN_RX, enable);
- }
- else { /* transmit */
+ } else {
set_reg_mode(val, I2S_CTRL_XFER_EN_TX, enable);
}
+
i2s_writel(ifc, val, I2S_CTRL_0);
}
@@ -215,12 +235,9 @@ int i2s_set_bit_format(int ifc, unsigned fmt)
if ((fmt == AUDIO_FRAME_FORMAT_I2S) ||
(fmt == AUDIO_FRAME_FORMAT_RJM) ||
- (fmt == AUDIO_FRAME_FORMAT_LJM))
- {
+ (fmt == AUDIO_FRAME_FORMAT_LJM)) {
val |= I2S_CTRL_FRAME_FORMAT_LRCK;
- }
- else /*Dsp,Pcm,Tdm,Nw*/
- {
+ } else { /*Dsp,Pcm,Tdm,Nw*/
val |= I2S_CTRL_FRAME_FORMAT_FSYNC;
}
@@ -295,13 +312,10 @@ int i2s_set_data_offset(int ifc, int tx, int dataoffset)
val = i2s_readl(ifc, I2S_OFFSET_0);
- if (tx != AUDIO_TX_MODE)
- {
+ if (tx != AUDIO_TX_MODE) {
val &= ~I2S_OFFSET_RX_DATA_OFFSET_MASK;
val |= (dataoffset << I2S_OFFSET_RX_DATA_OFFSET_SHIFT);
- }
- else
- {
+ } else {
val &= ~I2S_OFFSET_TX_DATA_OFFSET_MASK;
val |= (dataoffset << I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
}
@@ -376,13 +390,10 @@ int i2s_set_slot_control(int ifc, int tx, int totalslot, int numslots)
val &= ~I2S_SLOT_CTRL_TOTAL_SLOT_MASK;
val |= (totalslot << I2S_CH_CTRL_FSYNC_WIDTH_SHIFT);
- if (tx != AUDIO_TX_MODE)
- {
+ if (tx != AUDIO_TX_MODE) {
val &= ~I2S_SLOT_CTRL_RX_SLOT_MASK;
val |= (numslots << I2S_SLOT_CTRL_RX_SLOT_SHIFT);
- }
- else
- {
+ } else {
val &= ~I2S_SLOT_CTRL_TX_SLOT_MASK;
val |= (numslots << I2S_SLOT_CTRL_TX_SLOT_SHIFT);
}
@@ -402,12 +413,9 @@ int i2s_set_bit_order(int ifc, int tx, int bitorder)
val = i2s_readl(ifc, I2S_CH_CTRL_0);
- if (tx != AUDIO_TX_MODE)
- {
+ if (tx != AUDIO_TX_MODE) {
set_reg_mode(val,I2S_CH_CTRL_RX_BIT_LSB_FIRST, bitorder);
- }
- else
- {
+ } else {
set_reg_mode(val, I2S_CH_CTRL_TX_BIT_LSB_FIRST, bitorder);
}
@@ -428,13 +436,10 @@ int i2s_set_bit_mask(int ifc, int tx, int maskbit)
val = i2s_readl(ifc, I2S_CH_CTRL_0);
- if (tx != AUDIO_TX_MODE)
- {
+ if (tx != AUDIO_TX_MODE) {
val &= ~I2S_CH_CTRL_RX_MASK_BITS_MASK;
val |= (maskbit << I2S_CH_CTRL_RX_MASK_BITS_SHIFT);
- }
- else
- {
+ } else {
val &= ~I2S_CH_CTRL_TX_MASK_BITS_MASK;
val |= (maskbit << I2S_CH_CTRL_TX_MASK_BITS_SHIFT);
}
@@ -473,14 +478,20 @@ int i2s_set_flow_control(int ifc, int enable, int filtertype, int stepsize)
int i2s_fifo_set_attention_level(int ifc, int fifo, unsigned level)
{
- return apbif_fifo_set_attention_level(ifc, fifo, (level - 1));
+ int apbif_ifc = i2s_get_apbif_channel(ifc, fifo);
+
+ if (apbif_ifc != -ENOENT)
+ return apbif_fifo_set_attention_level(apbif_ifc,
+ fifo, (level - 1));
+ return 0;
}
void i2s_fifo_clear(int ifc, int fifo)
{
-/* FIXME: fifo are part of apbif channel, so pass call to apbif
-* or provide generic call to apbif to handle this
-*/
+ int apbif_ifc = i2s_get_apbif_channel(ifc, fifo);
+
+ if (apbif_ifc != -ENOENT)
+ apbif_soft_reset(apbif_ifc, fifo, 1);
}
@@ -506,25 +517,29 @@ void i2s_enable_fifos(int ifc, int on)
void i2s_fifo_write(int ifc, int fifo, u32 data)
{
-/* FIXME: fifo are part of apbif channel, so pass call to apbif
-* or provide generic call to apbif to handle this
-*/
+ int apbif_ifc = i2s_get_apbif_channel(ifc, fifo);
+
+ if (apbif_ifc != -ENOENT)
+ apbif_fifo_write(apbif_ifc, fifo, data);
}
u32 i2s_fifo_read(int ifc, int fifo)
{
-/* FIXME: fifo are part of apbif channel, so pass call to apbif
-* or provide generic call to apbif to handle this
-*/
+ int apbif_ifc = i2s_get_apbif_channel(ifc, fifo);
+
+ if (apbif_ifc != -ENOENT)
+ return apbif_fifo_read(apbif_ifc, fifo);
return 0;
}
-u32 i2s_get_status(int ifc)
+u32 i2s_get_status(int ifc, int fifo)
{
-/* FIXME: fifo are part of apbif channel, so pass call to apbif
-* or provide generic call to apbif to handle this
-*/
- return apbif_get_fifo_mode(ifc, AUDIO_TX_MODE);
+ int apbif_ifc = i2s_get_apbif_channel(ifc, fifo);
+
+ if (apbif_ifc != -ENOENT)
+ return apbif_get_fifo_mode(apbif_ifc, fifo);
+
+ return 0;
}
u32 i2s_get_control(int ifc)
@@ -548,22 +563,56 @@ u32 i2s_get_fifo_scr(int ifc)
return 0;
}
-phys_addr_t i2s_get_fifo_phy_base(int ifc, int fifo)
+phys_addr_t i2s_get_fifo_phy_base(int ifc, int fifo_mode)
{
- return apbif_get_fifo_phy_base(ifc, fifo);
+ int apbif_ifc = i2s_get_apbif_channel(ifc, fifo_mode);
+
+ if (apbif_ifc == -ENOENT) {
+ pr_err("%s: dma not assigned \n", __func__);
+ return -EINVAL;
+ }
+
+ return apbif_get_fifo_phy_base(apbif_ifc, fifo_mode);
}
u32 i2s_get_fifo_full_empty_count(int ifc, int fifo)
{
-/* FIXME: fifo are part of apbif channel, so pass call to apbif
-* or provide generic call to apbif to handle this
-*/
+ int apbif_ifc = i2s_get_apbif_channel(ifc, fifo);
+
+ if (apbif_ifc != -ENOENT)
+ return apbif_get_fifo_freecount(apbif_ifc, fifo);
+
return 0;
}
-int i2s_get_dma_requestor(int ifc)
+int i2s_get_dma_requestor(int ifc, int fifo_mode)
{
- return apbif_get_channel(ifc);
+ int dma_index = 0;
+ int regIndex = ifc + ahubrx_i2s0;
+
+ if (fifo_mode == AUDIO_TX_MODE)
+ regIndex = ifc + ahubtx_i2s0;
+
+ dma_index = apbif_get_channel(regIndex, fifo_mode);
+
+ if (dma_index != -ENOENT) {
+ i2s_cont_info[ifc].dma_ch[fifo_mode] = dma_index - 1;
+ /* FIXME : this need to be called on connection request
+ */
+ i2s_set_acif(ifc, fifo_mode, 0);
+ }
+
+ return dma_index;
+}
+
+int i2s_free_dma_requestor(int ifc, int fifo_mode)
+{
+ int apbif_ifc = i2s_get_apbif_channel(ifc, fifo_mode);
+
+ if (apbif_ifc != -ENOENT)
+ audio_apbif_free_channel(apbif_ifc, fifo_mode);
+
+ return 0;
}
struct clk *i2s_get_clock_by_name(const char *name)
@@ -572,10 +621,39 @@ struct clk *i2s_get_clock_by_name(const char *name)
}
static struct audio_cif audiocif;
+
+int i2s_set_acif(int ifc, int fifo_mode, struct audio_cif *cifInfo)
+{
+ struct audio_cif *tx_audio_cif = &audiocif;
+
+ /* set i2s audiocif */
+ /* setting base value for acif */
+ memset(tx_audio_cif, 0 , sizeof(struct audio_cif));
+ tx_audio_cif->audio_channels = AUDIO_CHANNEL_2;
+ tx_audio_cif->client_channels = AUDIO_CHANNEL_2;
+ tx_audio_cif->audio_bits = AUDIO_BIT_SIZE_16;
+ tx_audio_cif->client_bits = AUDIO_BIT_SIZE_16;
+
+ if (fifo_mode == AUDIO_TX_MODE)
+ audio_switch_set_acif((unsigned int)i2s_base[ifc] +
+ I2S_AUDIOCIF_I2STX_CTRL_0, tx_audio_cif);
+ else
+ audio_switch_set_acif((unsigned int)i2s_base[ifc] +
+ I2S_AUDIOCIF_I2SRX_CTRL_0, tx_audio_cif);
+
+ audio_apbif_set_acif(i2s_get_apbif_channel(ifc, fifo_mode),
+ fifo_mode, tx_audio_cif);
+
+ return 0;
+}
+
int i2s_initialize(int ifc)
{
int err = 0;
- struct audio_cif *tx_audio_cif = &audiocif;
+
+
+ i2s_cont_info[ifc].dma_ch[0] = -ENOENT;
+ i2s_cont_info[ifc].dma_ch[1] = -ENOENT;
/* open audio_switch first */
err = audio_switch_open();
@@ -591,24 +669,6 @@ int i2s_initialize(int ifc)
i2s_set_data_offset(ifc, AUDIO_TX_MODE, 1);
i2s_set_data_offset(ifc, AUDIO_RX_MODE, 1);
- /* FIXME: move all the apbif call to a generic function
- inside audio_switch code - temporarily added here to
- get minimum audio function working
- */
-
- /* set i2s audiocif */
- /* setting base value for acif */
- memset(tx_audio_cif, 0 , sizeof(struct audio_cif));
- tx_audio_cif->audio_channels = AUDIO_CHANNEL_2;
- tx_audio_cif->client_channels = AUDIO_CHANNEL_2;
- tx_audio_cif->audio_bits = AUDIO_BIT_SIZE_16;
- tx_audio_cif->client_bits = AUDIO_BIT_SIZE_16;
- audio_switch_set_acif((unsigned int)i2s_base[ifc] +
- I2S_AUDIOCIF_I2STX_CTRL_0, tx_audio_cif);
- audio_switch_set_acif((unsigned int)i2s_base[ifc] +
- I2S_AUDIOCIF_I2SRX_CTRL_0, tx_audio_cif);
-
- apbif_initialize(ifc, tx_audio_cif);
return 0;
}
diff --git a/arch/arm/mach-tegra/tegra_spdif_audio.c b/arch/arm/mach-tegra/tegra_spdif_audio.c
index a3dcd02c15ce..555d347d1581 100644
--- a/arch/arm/mach-tegra/tegra_spdif_audio.c
+++ b/arch/arm/mach-tegra/tegra_spdif_audio.c
@@ -472,8 +472,8 @@ static void stop_dma_playback(struct audio_stream *aos)
struct audio_driver_state *ads = ads_from_out(aos);
pr_debug("%s\n", __func__);
spdif_fifo_enable(ads->spdif_base, AUDIO_TX_MODE, 0);
- while ((spdif_get_status(ads->spdif_base) & SPDIF_STATUS_0_TX_BSY) &&
- spin < 100) {
+ while ((spdif_get_status(ads->spdif_base, AUDIO_TX_MODE) &
+ SPDIF_STATUS_0_TX_BSY) && spin < 100) {
udelay(10);
if (spin++ > 50)
pr_info("%s: spin %d\n", __func__, spin);
@@ -488,7 +488,7 @@ static void stop_dma_playback(struct audio_stream *aos)
static irqreturn_t spdif_interrupt(int irq, void *data)
{
struct audio_driver_state *ads = data;
- u32 status = spdif_get_status(ads->spdif_base);
+ u32 status = spdif_get_status(ads->spdif_base, AUDIO_TX_MODE);
pr_debug("%s: %08x\n", __func__, status);
@@ -496,7 +496,7 @@ static irqreturn_t spdif_interrupt(int irq, void *data)
spdif_ack_status(ads->spdif_base);
pr_debug("%s: done %08x\n", __func__,
- spdif_get_status(ads->spdif_base));
+ spdif_get_status(ads->spdif_base, AUDIO_TX_MODE));
return IRQ_HANDLED;
}
#endif
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
index 3474857cf5cb..33a2c4a1ff1e 100644
--- a/sound/soc/tegra/tegra_i2s.c
+++ b/sound/soc/tegra/tegra_i2s.c
@@ -43,6 +43,19 @@ struct tegra_i2s_info {
struct das_regs_cache das_regs;
};
+void free_dma_request(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+ int fifo_mode = I2S_FIFO_RX;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ fifo_mode = I2S_FIFO_TX;
+
+ i2s_free_dma_requestor(cpu_dai->id, fifo_mode);
+}
+
void setup_i2s_dma_request(struct snd_pcm_substream *substream,
struct tegra_dma_req *req,
void (*dma_callback)(struct tegra_dma_req *req),
@@ -52,10 +65,17 @@ void setup_i2s_dma_request(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct tegra_i2s_info *info = cpu_dai->private_data;
+ int fifo_mode = I2S_FIFO_RX;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ fifo_mode = I2S_FIFO_TX;
+
+ req->req_sel = i2s_get_dma_requestor(cpu_dai->id, fifo_mode);
+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
req->to_memory = false;
req->dest_addr =
- i2s_get_fifo_phy_base(cpu_dai->id, I2S_FIFO_TX);
+ i2s_get_fifo_phy_base(cpu_dai->id, fifo_mode);
req->dest_wrap = 4;
req->source_wrap = 0;
if (info->bit_format == TEGRA_AUDIO_BIT_FORMAT_DSP)
@@ -66,7 +86,7 @@ void setup_i2s_dma_request(struct snd_pcm_substream *substream,
} else {
req->to_memory = true;
req->source_addr =
- i2s_get_fifo_phy_base(cpu_dai->id, I2S_FIFO_RX);
+ i2s_get_fifo_phy_base(cpu_dai->id, fifo_mode);
req->dest_wrap = 0;
req->source_wrap = 4;
if (info->bit_format == TEGRA_AUDIO_BIT_FORMAT_DSP)
@@ -78,7 +98,6 @@ void setup_i2s_dma_request(struct snd_pcm_substream *substream,
req->complete = dma_callback;
req->dev = dma_data;
- req->req_sel = info->dma_req_sel;
return;
}
@@ -121,7 +140,7 @@ static inline void stop_i2s_playback(struct snd_soc_dai *cpu_dai)
i2s_set_fifo_irq_on_err(cpu_dai->id, I2S_FIFO_TX, 0);
i2s_set_fifo_irq_on_qe(cpu_dai->id, I2S_FIFO_TX, 0);
i2s_fifo_enable(cpu_dai->id, I2S_FIFO_TX, 0);
- while (i2s_get_status(cpu_dai->id) & I2S_I2S_FIFO_TX_BUSY);
+ while (i2s_get_status(cpu_dai->id, I2S_FIFO_TX) & I2S_I2S_FIFO_TX_BUSY);
}
/* recording */
@@ -139,7 +158,7 @@ static inline void stop_i2s_capture(struct snd_soc_dai *cpu_dai)
i2s_set_fifo_irq_on_err(cpu_dai->id, I2S_FIFO_RX, 0);
i2s_set_fifo_irq_on_qe(cpu_dai->id, I2S_FIFO_RX, 0);
i2s_fifo_enable(cpu_dai->id, I2S_FIFO_RX, 0);
- while (i2s_get_status(cpu_dai->id) & I2S_I2S_FIFO_RX_BUSY);
+ while (i2s_get_status(cpu_dai->id, I2S_FIFO_RX) & I2S_I2S_FIFO_RX_BUSY);
}
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 3c1abacf2165..25a8c553e5ed 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -304,8 +304,10 @@ static int tegra_pcm_close(struct snd_pcm_substream *substream)
if (prtd->dma_chan) {
prtd->dma_state = STATE_EXIT;
- for (i = 0; i < DMA_REQ_QCOUNT; i++)
+ for (i = 0; i < DMA_REQ_QCOUNT; i++) {
tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[i]);
+ free_dma_request(substream);
+ }
tegra_dma_flush(prtd->dma_chan);
tegra_dma_free_channel(prtd->dma_chan);
prtd->dma_chan = NULL;
diff --git a/sound/soc/tegra/tegra_soc.h b/sound/soc/tegra/tegra_soc.h
index 05c9e18ccb43..cf054286b5be 100644
--- a/sound/soc/tegra/tegra_soc.h
+++ b/sound/soc/tegra/tegra_soc.h
@@ -145,6 +145,7 @@ void setup_dma_request(struct snd_pcm_substream *substream,
struct tegra_dma_req *req,
void (*dma_callback)(struct tegra_dma_req *req),
void *dma_data);
+void free_dma_request(struct snd_pcm_substream *substream);
void set_fifo_attention(struct snd_pcm_substream *substream,
int buffersize);
diff --git a/sound/soc/tegra/tegra_spdif.c b/sound/soc/tegra/tegra_spdif.c
index 53c0b19c15d2..99e275db8d3e 100644
--- a/sound/soc/tegra/tegra_spdif.c
+++ b/sound/soc/tegra/tegra_spdif.c
@@ -83,7 +83,7 @@ static inline void stop_spdif_playback(struct snd_soc_dai *dai)
struct tegra_spdif_info *info = dai->private_data;
spdif_fifo_enable(info->spdif_base, AUDIO_TX_MODE, false);
- while (spdif_get_status(info->spdif_base) & SPDIF_STATUS_0_TX_BSY);
+ while (spdif_get_status(info->spdif_base, AUDIO_TX_MODE) & SPDIF_STATUS_0_TX_BSY);
}
/* capture */
@@ -101,7 +101,7 @@ static inline void stop_spdif_capture(struct snd_soc_dai *dai)
struct tegra_spdif_info *info = dai->private_data;
spdif_fifo_enable(info->spdif_base, AUDIO_RX_MODE, false);
- while (spdif_get_status(info->spdif_base) & SPDIF_STATUS_0_RX_BSY);
+ while (spdif_get_status(info->spdif_base, AUDIO_RX_MODE) & SPDIF_STATUS_0_RX_BSY);
}
static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,