summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra_i2s_audio.c
diff options
context:
space:
mode:
authorChris Fries <C.Fries@motorola.com>2010-11-03 12:45:26 -0500
committerIliyan Malchev <malchev@google.com>2010-11-03 13:05:04 -0700
commite8d9abdf7b8878740e73a13ba084c39a24967da2 (patch)
treee8fbbd4e9a968fbe78e55c4b9c683a38a2794e6c /arch/arm/mach-tegra/tegra_i2s_audio.c
parent47e55a567c42ccc20b289875e51fbc64afa578b6 (diff)
[ARM] tegra_i2s_audio: add support for master/slave switching
- Remove duplicate code between probe() and resume(), make new function i2s_configure() - When master, pass the sample rate from the board info - Clean up some checkpatch.pl complaints. Change-Id: I0169d9a70c02eaf2173b1f1941a545792c01bc6b Signed-off-by: Iliyan Malchev <malchev@google.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra_i2s_audio.c')
-rw-r--r--arch/arm/mach-tegra/tegra_i2s_audio.c120
1 files changed, 68 insertions, 52 deletions
diff --git a/arch/arm/mach-tegra/tegra_i2s_audio.c b/arch/arm/mach-tegra/tegra_i2s_audio.c
index a1bcc90b7519..e5c0436d5f1b 100644
--- a/arch/arm/mach-tegra/tegra_i2s_audio.c
+++ b/arch/arm/mach-tegra/tegra_i2s_audio.c
@@ -386,13 +386,15 @@ static int i2s_set_dsp_mode(unsigned long base, unsigned int mode)
if (mode != TEGRA_AUDIO_DSP_PCM) {
/* Disable PCM mode */
val = i2s_readl(base, I2S_I2S_PCM_CTRL_0);
- val &= ~(I2S_I2S_PCM_CTRL_TRM_MODE|I2S_I2S_PCM_CTRL_RCV_MODE);
+ val &= ~(I2S_I2S_PCM_CTRL_TRM_MODE |
+ I2S_I2S_PCM_CTRL_RCV_MODE);
i2s_writel(base, val, I2S_I2S_PCM_CTRL_0);
}
if (mode != TEGRA_AUDIO_DSP_NETWORK) {
/* Disable Network mode */
val = i2s_readl(base, I2S_I2S_NW_CTRL_0);
- val &= ~(I2S_I2S_NW_CTRL_TRM_TLPHY_MODE|I2S_I2S_NW_CTRL_RCV_TLPHY_MODE);
+ val &= ~(I2S_I2S_NW_CTRL_TRM_TLPHY_MODE |
+ I2S_I2S_NW_CTRL_RCV_TLPHY_MODE);
i2s_writel(base, val, I2S_I2S_NW_CTRL_0);
}
@@ -401,13 +403,15 @@ static int i2s_set_dsp_mode(unsigned long base, unsigned int mode)
case TEGRA_AUDIO_DSP_NETWORK:
/* Set DSP Network (Telephony) Mode */
val = i2s_readl(base, I2S_I2S_NW_CTRL_0);
- val |= I2S_I2S_NW_CTRL_TRM_TLPHY_MODE|I2S_I2S_NW_CTRL_RCV_TLPHY_MODE;
+ val |= I2S_I2S_NW_CTRL_TRM_TLPHY_MODE |
+ I2S_I2S_NW_CTRL_RCV_TLPHY_MODE;
i2s_writel(base, val, I2S_I2S_NW_CTRL_0);
break;
case TEGRA_AUDIO_DSP_PCM:
/* Set DSP PCM Mode */
val = i2s_readl(base, I2S_I2S_PCM_CTRL_0);
- val |= I2S_I2S_PCM_CTRL_TRM_MODE|I2S_I2S_PCM_CTRL_RCV_MODE;
+ val |= I2S_I2S_PCM_CTRL_TRM_MODE |
+ I2S_I2S_PCM_CTRL_RCV_MODE;
i2s_writel(base, val, I2S_I2S_PCM_CTRL_0);
break;
}
@@ -558,6 +562,58 @@ static inline u32 i2s_get_fifo_full_empty_count(unsigned long base, int fifo)
return val & I2S_I2S_FIFO_SCR_FIFO_FULL_EMPTY_COUNT_MASK;
}
+static int i2s_configure(struct platform_device *pdev)
+{
+ struct tegra_audio_platform_data *pdata = pdev->dev.platform_data;
+ struct audio_driver_state *state = pdata->driver_data;
+ bool master;
+ struct clk *i2s_clk;
+ int master_clk;
+
+ /* dev_info(&pdev->dev, "%s\n", __func__); */
+
+ if (!state)
+ return -ENOMEM;
+
+ /* disable interrupts from I2S */
+ i2s_enable_fifos(state->i2s_base, 0);
+ i2s_fifo_clear(state->i2s_base, I2S_FIFO_TX);
+ i2s_fifo_clear(state->i2s_base, I2S_FIFO_RX);
+ i2s_set_left_right_control_polarity(state->i2s_base, 0); /* default */
+
+ i2s_clk = clk_get(&pdev->dev, NULL);
+ if (!i2s_clk) {
+ dev_err(&pdev->dev, "%s: could not get i2s clock\n",
+ __func__);
+ return -EIO;
+ }
+
+ master = state->bit_format == TEGRA_AUDIO_BIT_FORMAT_DSP ?
+ state->pdata->dsp_master : state->pdata->i2s_master;
+
+
+ master_clk = state->bit_format == TEGRA_AUDIO_BIT_FORMAT_DSP ?
+ state->pdata->dsp_master_clk :
+ state->pdata->i2s_master_clk;
+#define I2S_CLK_FUDGE_FACTOR 2 /* Todo, fix this! */
+ if (master)
+ i2s_set_channel_bit_count(state->i2s_base, master_clk,
+ clk_get_rate(i2s_clk)*I2S_CLK_FUDGE_FACTOR);
+ i2s_set_master(state->i2s_base, master);
+
+ i2s_set_fifo_mode(state->i2s_base, I2S_FIFO_TX, 1);
+ i2s_set_fifo_mode(state->i2s_base, I2S_FIFO_RX, 0);
+
+ if (state->bit_format == TEGRA_AUDIO_BIT_FORMAT_DSP)
+ i2s_set_bit_format(state->i2s_base, I2S_BIT_FORMAT_DSP);
+ else
+ i2s_set_bit_format(state->i2s_base, state->pdata->mode);
+ i2s_set_bit_size(state->i2s_base, state->pdata->bit_size);
+ i2s_set_fifo_format(state->i2s_base, state->pdata->fifo_fmt);
+
+ return 0;
+}
+
static int init_stream_buffer(struct audio_stream *,
struct tegra_audio_buf_config *cfg, unsigned);
@@ -1489,6 +1545,7 @@ static long tegra_audio_ioctl(struct file *file,
goto done;
}
sound_ops->tear_down(ads);
+ i2s_configure(ads->pdev);
sound_ops->setup(ads);
}
@@ -1562,7 +1619,7 @@ static long tegra_audio_in_ioctl(struct file *file,
break;
}
#endif
- if(cfg.stereo && !ads->pdata->stereo_capture) {
+ if (cfg.stereo && !ads->pdata->stereo_capture) {
pr_err("%s: not capable of stereo capture.",
__func__);
rc = -EINVAL;
@@ -2341,14 +2398,14 @@ static int tegra_audio_probe(struct platform_device *pdev)
i2s_clk = clk_get(&pdev->dev, NULL);
if (!i2s_clk) {
- dev_err(&pdev->dev, "%s: could not get i2s1 clock\n",
+ dev_err(&pdev->dev, "%s: could not get i2s clock\n",
__func__);
return -EIO;
}
clk_set_rate(i2s_clk, state->pdata->i2s_clk_rate);
if (clk_enable(i2s_clk)) {
- dev_err(&pdev->dev, "%s: failed to enable i2s1 clock\n",
+ dev_err(&pdev->dev, "%s: failed to enable i2s clock\n",
__func__);
return -EIO;
}
@@ -2370,20 +2427,9 @@ static int tegra_audio_probe(struct platform_device *pdev)
}
clk_enable(audio_sync_clk);
- i2s_enable_fifos(state->i2s_base, 0);
- /* disable interrupts from I2S */
- i2s_fifo_clear(state->i2s_base, I2S_FIFO_TX);
- i2s_fifo_clear(state->i2s_base, I2S_FIFO_RX);
- i2s_set_left_right_control_polarity(state->i2s_base, 0); /* default */
- if (state->pdata->master)
- i2s_set_channel_bit_count(state->i2s_base, 44100,
- clk_get_rate(i2s_clk));
- i2s_set_master(state->i2s_base, state->pdata->master);
- i2s_set_fifo_mode(state->i2s_base, I2S_FIFO_TX, 1);
- i2s_set_fifo_mode(state->i2s_base, I2S_FIFO_RX, 0);
- i2s_set_bit_format(state->i2s_base, state->pdata->mode);
- i2s_set_bit_size(state->i2s_base, state->pdata->bit_size);
- i2s_set_fifo_format(state->i2s_base, state->pdata->fifo_fmt);
+ rc = i2s_configure(pdev);
+ if (rc < 0)
+ return rc;
if ((state->pdata->mask & TEGRA_AUDIO_ENABLE_TX)) {
state->out.opened = 0;
@@ -2515,37 +2561,7 @@ static int tegra_audio_suspend(struct platform_device *pdev, pm_message_t mesg)
static int tegra_audio_resume(struct platform_device *pdev)
{
- struct tegra_audio_platform_data *pdata = pdev->dev.platform_data;
- struct audio_driver_state *state = pdata->driver_data;
-
- /* dev_info(&pdev->dev, "%s\n", __func__); */
-
- if (!state)
- return -ENOMEM;
-
- /* disable interrupts from I2S */
- i2s_fifo_clear(state->i2s_base, I2S_FIFO_TX);
- i2s_fifo_clear(state->i2s_base, I2S_FIFO_RX);
- i2s_enable_fifos(state->i2s_base, 0);
-
- i2s_set_left_right_control_polarity(state->i2s_base, 0); /* default */
-
- if (state->pdata->master)
- i2s_set_channel_bit_count(state->i2s_base, 44100,
- state->pdata->i2s_clk_rate);
- i2s_set_master(state->i2s_base, state->pdata->master);
-
- i2s_set_fifo_mode(state->i2s_base, I2S_FIFO_TX, 1);
- i2s_set_fifo_mode(state->i2s_base, I2S_FIFO_RX, 0);
-
- if (state->bit_format == TEGRA_AUDIO_BIT_FORMAT_DSP)
- i2s_set_bit_format(state->i2s_base, I2S_BIT_FORMAT_DSP);
- else
- i2s_set_bit_format(state->i2s_base, state->pdata->mode);
- i2s_set_bit_size(state->i2s_base, state->pdata->bit_size);
- i2s_set_fifo_format(state->i2s_base, state->pdata->fifo_fmt);
-
- return 0;
+ return i2s_configure(pdev);
}
#endif /* CONFIG_PM */