summaryrefslogtreecommitdiff
path: root/sound/soc/tegra/tegra30_dam.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/tegra/tegra30_dam.c')
-rw-r--r--sound/soc/tegra/tegra30_dam.c47
1 files changed, 39 insertions, 8 deletions
diff --git a/sound/soc/tegra/tegra30_dam.c b/sound/soc/tegra/tegra30_dam.c
index d308179110c9..8460266d0d66 100644
--- a/sound/soc/tegra/tegra30_dam.c
+++ b/sound/soc/tegra/tegra30_dam.c
@@ -3,6 +3,7 @@
*
* Author: Nikesh Oswal <noswal@nvidia.com>
* Copyright (C) 2011 - NVIDIA, Inc.
+ * Copyright (C) 2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -27,6 +28,7 @@
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <linux/io.h>
#include <sound/soc.h>
#include "tegra30_dam.h"
@@ -455,6 +457,8 @@ int tegra30_dam_set_acif(int ifc, int chid, unsigned int audio_channels,
void tegra30_dam_enable(int ifc, int on, int chid)
{
u32 old_val, val, enreg;
+ u32 old_val_dam, val_dam;
+ int dcnt = 10;
struct tegra30_dam_context *dam = dams_cont_info[ifc];
if (ifc >= TEGRA30_NR_DAM_IFC)
@@ -476,19 +480,46 @@ void tegra30_dam_enable(int ifc, int on, int chid)
val &= ~TEGRA30_DAM_CH0_CTRL_EN;
}
- if (val != old_val)
- tegra30_dam_writel(dam, val, enreg);
-
- old_val = val = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
+ old_val_dam = val_dam = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
if (dam->ch_enable_refcnt[dam_ch_in0] ||
dam->ch_enable_refcnt[dam_ch_in1])
- val |= TEGRA30_DAM_CTRL_DAM_EN;
+ val_dam |= TEGRA30_DAM_CTRL_DAM_EN;
else
- val &= ~TEGRA30_DAM_CTRL_DAM_EN;
+ val_dam &= ~TEGRA30_DAM_CTRL_DAM_EN;
+
+ if (val != old_val) {
+ tegra30_dam_writel(dam, val, enreg);
+
+ if (!on) {
+ if (chid == dam_ch_in0) {
+ while (tegra30_ahub_dam_ch0_is_enabled(ifc)
+ && dcnt--)
+ udelay(100);
+
+ dcnt = 10;
+ }
+ else {
+ while (tegra30_ahub_dam_ch1_is_enabled(ifc)
+ && dcnt--)
+ udelay(100);
+
+ dcnt = 10;
+ }
+ }
+ }
+
+ if (old_val_dam != val_dam) {
+ tegra30_dam_writel(dam, val_dam, TEGRA30_DAM_CTRL);
+
+ if (!on) {
+ while (tegra30_ahub_dam_tx_is_enabled(ifc) && dcnt--)
+ udelay(100);
- if (old_val != val)
- tegra30_dam_writel(dam, val, TEGRA30_DAM_CTRL);
+ dcnt = 10;
+ }
+
+ }
}
void tegra30_dam_ch0_set_datasync(struct tegra30_dam_context *dam, int datasync)