diff options
author | Vinod G <vinodg@nvidia.com> | 2011-03-29 18:19:32 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-04-26 15:54:46 -0700 |
commit | 437622a591e552169ba7b7443432d081c83a8f73 (patch) | |
tree | 3fa95bb44db6e6bb6ffeeaec417b20b032357cfe | |
parent | be27dfe98c8b7441ff1c521d66e336efbcedde60 (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.c | 388 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/audio.h | 19 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/audio_switch.h | 60 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/spdif.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/tegra2_i2s.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/tegra3_i2s.h | 95 | ||||
-rw-r--r-- | arch/arm/mach-tegra/spdif.c | 227 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_i2s.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_i2s.c | 206 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra_spdif_audio.c | 8 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_i2s.c | 29 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_pcm.c | 4 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_soc.h | 1 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_spdif.c | 4 |
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, |