summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVinod G <vinodg@nvidia.com>2011-09-27 13:48:25 -0700
committerRohan Somvanshi <rsomvanshi@nvidia.com>2011-09-30 02:16:25 -0700
commit5d34059acad845ca7466e6774ffb126f08940177 (patch)
treee090c3ca204e3dd00f6fcac8a55c6db3e0a93d96
parent7beddf4e72024e6f140ed306e80a7e1d19d7f36b (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.c19
-rw-r--r--arch/arm/mach-tegra/dam.c17
-rw-r--r--arch/arm/mach-tegra/include/mach/audio_switch.h2
-rw-r--r--arch/arm/mach-tegra/tegra3_i2s.c12
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);
}