[ARM] tegra_i2s_audio: add suspend/resume handlers
authorChris Fries <C.Fries@motorola.com>
Thu, 14 Oct 2010 21:31:52 +0000 (16:31 -0500)
committerIliyan Malchev <malchev@google.com>
Sun, 17 Oct 2010 03:53:07 +0000 (20:53 -0700)
The resume handler restores i2s state, which gets lost on LP0

Signed-off-by: Iliyan Malchev <malchev@google.com>
arch/arm/mach-tegra/tegra_i2s_audio.c

index 48b1bec21f67a8314515288e0bccc0f26a0d969f..47830789a74a216d72c8a6d901cfb7481635b584 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/pm_qos_params.h>
 #include <linux/delay.h>
 #include <linux/tegra_audio.h>
-
+#include <linux/pm.h>
 #include <mach/dma.h>
 #include <mach/iomap.h>
 #include <mach/i2s.h>
@@ -2380,12 +2380,59 @@ static int tegra_audio_probe(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int tegra_audio_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+       /* dev_info(&pdev->dev, "%s\n", __func__); */
+       return 0;
+}
+
+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;
+}
+#endif /* CONFIG_PM */
+
 static struct platform_driver tegra_audio_driver = {
        .driver = {
                .name = "i2s",
                .owner = THIS_MODULE,
        },
        .probe = tegra_audio_probe,
+#ifdef CONFIG_PM
+       .suspend = tegra_audio_suspend,
+       .resume = tegra_audio_resume,
+#endif
 };
 
 static int __init tegra_audio_init(void)