diff options
author | Vinod G <vinodg@nvidia.com> | 2011-09-27 13:48:25 -0700 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2011-09-30 02:16:25 -0700 |
commit | 5d34059acad845ca7466e6774ffb126f08940177 (patch) | |
tree | e090c3ca204e3dd00f6fcac8a55c6db3e0a93d96 | |
parent | 7beddf4e72024e6f140ed306e80a7e1d19d7f36b (diff) |
arm: tegra: audio: Save register values to cache.
Save register values to cache on register write.
So resume calls does not overwrite the register with old cache
values.
bug 874443
Change-Id: Iedbc27d6ffc0477066aa62cc14732d64f5aeff5e
Reviewed-on: http://git-master/r/54795
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: Chandrakanth Gorantla <cgorantla@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/audio_switch.c | 19 | ||||
-rw-r--r-- | arch/arm/mach-tegra/dam.c | 17 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/audio_switch.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_i2s.c | 12 |
4 files changed, 36 insertions, 14 deletions
diff --git a/arch/arm/mach-tegra/audio_switch.c b/arch/arm/mach-tegra/audio_switch.c index 900d98e9b592..f6e738c2e252 100644 --- a/arch/arm/mach-tegra/audio_switch.c +++ b/arch/arm/mach-tegra/audio_switch.c @@ -269,10 +269,12 @@ void audio_switch_dump_registers(int ifc) void audio_switch_clear_rx_port(int rxport) { audio_switch_writel(ahub_reginfo[rxport].regbase, 0); + ahub_reginfo[rxport].regcache = 0; } void audio_switch_set_rx_port(int rxport, int txport) { audio_switch_writel(ahub_reginfo[rxport].regbase, (1 << txport)); + ahub_reginfo[rxport].regcache = (1 << txport); } int audio_switch_get_rx_port(int rxport) @@ -300,7 +302,7 @@ void ahub_restore_registers(void) } /* audiocif control */ -void audio_switch_set_acif(int addr, struct audio_cif *cifInfo) +u32 audio_switch_set_acif(int addr, struct audio_cif *cifInfo) { u32 val; @@ -341,6 +343,8 @@ void audio_switch_set_acif(int addr, struct audio_cif *cifInfo) __raw_writel(val, addr); AHUB_DEBUG_PRINT("acif value written 0x%x: %08x\n", addr, val); + + return val; } @@ -352,6 +356,7 @@ static inline void apbif_writel(int ifc, u32 val, u32 reg) (unsigned int)ch->virt_base + reg, val); __raw_writel(val, ch->virt_base + reg); + ch->reg_cache[(reg >> 2)] = val; } static inline u32 apbif_readl(int ifc, u32 reg) @@ -767,11 +772,13 @@ int audio_apbif_set_acif(int ifc, int fifo_mode, struct audio_cif *cifInfo) ch = &apbif_channels[ifc]; if (fifo_mode == AUDIO_TX_MODE) { - audio_switch_set_acif((unsigned int)ch->virt_base + - APBIF_AUDIOCIF_TX0_CTRL_0, cifInfo); + ch->reg_cache[(APBIF_AUDIOCIF_TX0_CTRL_0 >> 2)] = + audio_switch_set_acif((unsigned int)ch->virt_base + + APBIF_AUDIOCIF_TX0_CTRL_0, cifInfo); } else { - audio_switch_set_acif((unsigned int)ch->virt_base + - APBIF_AUDIOCIF_RX0_CTRL_0, cifInfo); + ch->reg_cache[(APBIF_AUDIOCIF_RX0_CTRL_0 >> 2)] = + audio_switch_set_acif((unsigned int)ch->virt_base + + APBIF_AUDIOCIF_RX0_CTRL_0, cifInfo); } return 0; } @@ -907,4 +914,4 @@ int audio_switch_close(void) dam_close(); return 0; } -EXPORT_SYMBOL(audio_switch_close);
\ No newline at end of file +EXPORT_SYMBOL(audio_switch_close); diff --git a/arch/arm/mach-tegra/dam.c b/arch/arm/mach-tegra/dam.c index 1edc25941a83..3f335372018e 100644 --- a/arch/arm/mach-tegra/dam.c +++ b/arch/arm/mach-tegra/dam.c @@ -40,7 +40,7 @@ struct dam_context { bool ch_alloc[DAM_NUM_INPUT_CHANNELS]; bool ch_inuse[DAM_NUM_INPUT_CHANNELS]; int ch_insamplerate[DAM_NUM_INPUT_CHANNELS]; - int ctrlreg_cache[DAM_CTRL_REGINDEX]; + int ctrlreg_cache[DAM_CTRL_REGINDEX + 1]; struct clk *dam_clk; int clk_refcnt; int dma_ch[dam_ch_maxnum]; @@ -98,7 +98,9 @@ void dam_ch1_set_gain(int ifc,int gain); static inline void dam_writel(int ifc, u32 val, u32 reg) { + struct dam_context *ch = &dam_cont_info[ifc]; __raw_writel(val, dam_base[ifc] + reg); + ch->ctrlreg_cache[(reg >> 2)] = val; DAM_DEBUG_PRINT("dam write 0x%p: %08x\n", dam_base[ifc] + reg, val); } @@ -394,7 +396,6 @@ int dam_suspend(int ifc) ch = &dam_cont_info[ifc]; dam_save_ctrl_registers(ifc); - dam_disable_clock(ifc); return 0; } @@ -404,7 +405,6 @@ int dam_resume(int ifc) struct dam_context *ch; ch = &dam_cont_info[ifc]; - dam_enable_clock(ifc); dam_restore_ctrl_registers(ifc); return 0; @@ -438,6 +438,7 @@ void dam_disable_clock(int ifc) ch->clk_refcnt--; if ((ch->clk_refcnt == 0) && (ch->dam_clk)) { + dam_suspend(ifc); clk_disable(ch->dam_clk); } } @@ -463,6 +464,7 @@ int dam_enable_clock(int ifc) err = PTR_ERR(ch->dam_clk); goto fail_dam_clock; } + dam_resume(ifc); } ch->clk_refcnt++; @@ -480,20 +482,26 @@ EXPORT_SYMBOL(dam_enable_clock); int dam_set_acif(int ifc, int chtype, struct audio_cif *cifInfo) { + struct dam_context *ch; unsigned int reg_addr = (unsigned int)dam_base[ifc]; + unsigned int reg_index = 0; bool found = true; + ch = &dam_cont_info[ifc]; switch (chtype) { case dam_ch_out: reg_addr += DAM_AUDIOCIF_OUT_CTRL_0; + reg_index = (DAM_AUDIOCIF_OUT_CTRL_0 >> 2); break; case dam_ch_in0: /*always Mono channel*/ cifInfo->client_channels = AUDIO_CHANNEL_1; reg_addr += DAM_AUDIOCIF_CH0_CTRL_0; + reg_index = (DAM_AUDIOCIF_CH0_CTRL_0 >> 2); break; case dam_ch_in1: reg_addr += DAM_AUDIOCIF_CH1_CTRL_0; + reg_index = (DAM_AUDIOCIF_CH1_CTRL_0 >> 2); break; default: found = false; @@ -501,7 +509,8 @@ int dam_set_acif(int ifc, int chtype, struct audio_cif *cifInfo) } if (found == true) - audio_switch_set_acif(reg_addr, cifInfo); + ch->ctrlreg_cache[reg_index] = + audio_switch_set_acif(reg_addr, cifInfo); return 0; } diff --git a/arch/arm/mach-tegra/include/mach/audio_switch.h b/arch/arm/mach-tegra/include/mach/audio_switch.h index cedc86d3eb39..6ebdb31ac482 100644 --- a/arch/arm/mach-tegra/include/mach/audio_switch.h +++ b/arch/arm/mach-tegra/include/mach/audio_switch.h @@ -119,7 +119,7 @@ int apbif_get_channel(int regindex, int fifo_mode); 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); +u32 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); void audio_switch_clear_rx_port(int rxport); diff --git a/arch/arm/mach-tegra/tegra3_i2s.c b/arch/arm/mach-tegra/tegra3_i2s.c index 1bdfc5cd05d7..1ef9ecd8d5e5 100644 --- a/arch/arm/mach-tegra/tegra3_i2s.c +++ b/arch/arm/mach-tegra/tegra3_i2s.c @@ -74,10 +74,14 @@ static struct audio_cif audiocif; static inline void i2s_writel(int ifc, u32 val, u32 reg) { + struct i2s_controller_info *info = &i2s_cont_info[ifc]; + I2S_DEBUG_PRINT("i2s Write 0x%x : %08x\n", (unsigned int)i2s_base[ifc] + reg, val); __raw_writel(val, i2s_base[ifc] + reg); + + info->i2s_regcache[(reg >> 2)] = val; } static inline u32 i2s_readl(int ifc, u32 reg) @@ -794,8 +798,9 @@ int i2s_set_acif(int ifc, int fifo_mode, struct audio_cif *cifInfo) int apbif_ifc = i2s_get_apbif_channel(ifc, fifo_mode); if (fifo_mode == AUDIO_TX_MODE) - audio_switch_set_acif((unsigned int)i2s_base[ifc] + - I2S_AUDIOCIF_I2STX_CTRL_0, cifInfo); + info->i2s_regcache[(I2S_AUDIOCIF_I2STX_CTRL_0 >> 2)] = + audio_switch_set_acif((unsigned int)i2s_base[ifc] + + I2S_AUDIOCIF_I2STX_CTRL_0, cifInfo); else { struct audio_cif reccifInfo; memcpy(&reccifInfo, cifInfo, sizeof(struct audio_cif)); @@ -805,7 +810,8 @@ int i2s_set_acif(int ifc, int fifo_mode, struct audio_cif *cifInfo) (cifInfo->client_channels == AUDIO_CHANNEL_1)) reccifInfo.client_channels = AUDIO_CHANNEL_2; - audio_switch_set_acif((unsigned int)i2s_base[ifc] + + info->i2s_regcache[(I2S_AUDIOCIF_I2SRX_CTRL_0 >> 2)] = + audio_switch_set_acif((unsigned int)i2s_base[ifc] + I2S_AUDIOCIF_I2SRX_CTRL_0, &reccifInfo); } |