summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/audio_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/audio_manager.c')
-rw-r--r--arch/arm/mach-tegra/audio_manager.c409
1 files changed, 409 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/audio_manager.c b/arch/arm/mach-tegra/audio_manager.c
index 21ba3f16544e..ac517b6c5002 100644
--- a/arch/arm/mach-tegra/audio_manager.c
+++ b/arch/arm/mach-tegra/audio_manager.c
@@ -34,6 +34,232 @@
#include <mach/iomap.h>
#include <mach/pinmux.h>
#include <mach/tegra_das.h>
+#include <mach/tegra_i2s.h>
+#include <mach/spdif.h>
+#include <mach/audio_manager.h>
+
+
+static struct am_dev_fns init_am_dev_fns[] = {
+[AUDIO_I2S_DEVICE] = {
+ .aud_dev_suspend = i2s_suspend,
+ .aud_dev_resume = i2s_resume,
+ .aud_dev_set_stream_state = i2s_fifo_enable,
+ .aud_dev_get_dma_requestor = i2s_get_dma_requestor,
+ .aud_dev_free_dma_requestor = i2s_free_dma_requestor,
+ .aud_dev_get_fifo_phy_base = i2s_get_fifo_phy_base,
+ .aud_dev_set_fifo_attention = i2s_set_fifo_attention,
+ .aud_dev_get_status = i2s_get_status,
+ .aud_dev_clock_disable = i2s_clock_disable,
+ .aud_dev_clock_enable = i2s_clock_enable,
+ .aud_dev_clock_set_parent = i2s_clock_set_parent,
+ .aud_dev_clock_set_rate = i2s_clock_set_rate,
+ .aud_dev_deinit = i2s_close,
+ },
+
+[AUDIO_SPDIF_DEVICE] = {
+ .aud_dev_suspend = spdif_suspend,
+ .aud_dev_resume = spdif_resume,
+ .aud_dev_set_stream_state = spdif_fifo_enable,
+ .aud_dev_get_dma_requestor = spdif_get_dma_requestor,
+ .aud_dev_free_dma_requestor = spdif_free_dma_requestor,
+ .aud_dev_get_fifo_phy_base = spdif_get_fifo_phy_base,
+ .aud_dev_set_fifo_attention = spdif_set_fifo_attention,
+ .aud_dev_get_status = spdif_get_status,
+ .aud_dev_clock_disable = spdif_clock_disable,
+ .aud_dev_clock_enable = spdif_clock_enable,
+ .aud_dev_clock_set_parent = spdif_clock_set_parent,
+ .aud_dev_clock_set_rate = spdif_clock_set_rate,
+ .aud_dev_deinit = spdif_close,
+ },
+
+};
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+
+int am_suspend(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_suspend(devinfo->dev_id);
+}
+
+int am_resume(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_resume(devinfo->dev_id);
+}
+
+int am_set_stream_state(aud_dev_info* devinfo, bool enable)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_set_stream_state(
+ devinfo->dev_id,
+ devinfo->fifo_mode,
+ ((enable)? 1 : 0));
+}
+
+int am_get_dma_requestor(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_get_dma_requestor(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+int am_free_dma_requestor(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_free_dma_requestor(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+phys_addr_t am_get_fifo_phy_base(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_get_fifo_phy_base(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+int am_set_fifo_attention(aud_dev_info* devinfo, int buffersize)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_set_fifo_attention(
+ devinfo->dev_id,
+ buffersize,
+ devinfo->fifo_mode);
+}
+
+u32 am_get_status(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_get_status(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+int am_clock_disable(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_clock_disable(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+int am_clock_enable(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_clock_enable(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+int am_clock_set_parent(aud_dev_info* devinfo, int parent)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_clock_set_parent(
+ devinfo->dev_id,
+ devinfo->fifo_mode,
+ parent);
+}
+
+int am_clock_set_rate(aud_dev_info* devinfo, int rate)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_clock_set_rate(
+ devinfo->dev_id,
+ devinfo->fifo_mode,
+ rate);
+}
+
+int am_device_deinit(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_deinit(devinfo->dev_id);
+}
+
+int am_set_stream_format(aud_dev_info* devinfo, am_stream_format_info *format)
+{
+ if (devinfo->dev_type == AUDIO_I2S_DEVICE) {
+ i2s_set_bit_size(devinfo->dev_id, format->bitsize);
+ i2s_set_samplerate(devinfo->dev_id, format->samplerate);
+ i2s_set_channels(devinfo->dev_id, format->channels);
+ i2s_set_fifo_attention(devinfo->dev_id,
+ devinfo->fifo_mode, format->buffersize);
+
+ } else if (devinfo->dev_type == AUDIO_SPDIF_DEVICE) {
+ spdif_set_bit_mode(devinfo->dev_id, format->bitsize);
+ /* fixme - move to appropriate locn later */
+ spdif_set_fifo_packed(devinfo->dev_id, 1);
+
+ spdif_set_sample_rate(devinfo->dev_id,
+ devinfo->fifo_mode, format->samplerate);
+ spdif_set_fifo_attention(devinfo->dev_id,
+ devinfo->fifo_mode, format->buffersize);
+ }
+ return 0;
+}
+
+int am_set_device_format(aud_dev_info* devinfo, am_dev_format_info *format)
+{
+ if (devinfo->dev_type == AUDIO_I2S_DEVICE) {
+ i2s_set_loopback(devinfo->dev_id, format->loopmode);
+ i2s_set_master(devinfo->dev_id, format->mastermode);
+ i2s_set_bit_format(devinfo->dev_id, format->audiomode);
+ i2s_set_left_right_control_polarity(
+ devinfo->dev_id,
+ format->polarity);
+
+ } else if (devinfo->dev_type == AUDIO_SPDIF_DEVICE) {
+
+ }
+ return 0;
+}
+
+int am_device_init(aud_dev_info* devinfo, void *dev_fmt, void *strm_fmt)
+{
+ am_stream_format_info *sfmt = (am_stream_format_info*)strm_fmt;
+ am_dev_format_info *dfmt = (am_dev_format_info*)dev_fmt;
+
+ if (devinfo->dev_type == AUDIO_I2S_DEVICE) {
+ struct tegra_i2s_property i2sprop;
+
+
+ memset(&i2sprop, 0, sizeof(i2sprop));
+
+ if (sfmt) {
+ i2sprop.bit_size = sfmt->bitsize;
+ i2sprop.sample_rate = sfmt->samplerate;
+ }
+
+ if (dfmt) {
+ i2sprop.master_mode = dfmt->mastermode;
+ i2sprop.audio_mode = dfmt->audiomode;
+ i2sprop.clk_rate = dfmt->clkrate;
+ i2sprop.fifo_fmt = dfmt->fifofmt;
+ }
+
+ return i2s_init(devinfo->dev_id, &i2sprop);
+
+ } else if (devinfo->dev_type == AUDIO_SPDIF_DEVICE) {
+
+ struct tegra_spdif_property spdifprop;
+ memset(&spdifprop, 0, sizeof(spdifprop));
+
+ if (dfmt) {
+ spdifprop.clk_rate = dfmt->clkrate;
+
+ return spdif_init(
+ devinfo->base,
+ devinfo->phy_base,
+ devinfo->fifo_mode,
+ &spdifprop);
+ }
+ }
+ return 0;
+}
+
+#else
struct audio_manager_context {
struct clk *mclk;
@@ -45,6 +271,188 @@ struct audio_manager_context {
struct audio_manager_context *aud_manager;
+int am_suspend(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_suspend(devinfo->dev_id);
+}
+
+int am_resume(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_resume(devinfo->dev_id);
+}
+
+int am_set_stream_state(aud_dev_info* devinfo, bool enable)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_set_stream_state(
+ devinfo->dev_id,
+ devinfo->fifo_mode,
+ ((enable)? 1 : 0));
+}
+
+int am_get_dma_requestor(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_get_dma_requestor(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+int am_free_dma_requestor(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_free_dma_requestor(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+phys_addr_t am_get_fifo_phy_base(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_get_fifo_phy_base(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+int am_set_fifo_attention(aud_dev_info* devinfo, int buffersize)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_set_fifo_attention(
+ devinfo->dev_id,
+ buffersize,
+ devinfo->fifo_mode);
+}
+
+u32 am_get_status(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_get_status(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+int am_clock_disable(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_clock_disable(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+int am_clock_enable(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_clock_enable(
+ devinfo->dev_id,
+ devinfo->fifo_mode);
+}
+
+int am_clock_set_parent(aud_dev_info* devinfo, int parent)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_clock_set_parent(
+ devinfo->dev_id,
+ devinfo->fifo_mode,
+ parent);
+}
+
+int am_clock_set_rate(aud_dev_info* devinfo, int rate)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_clock_set_rate(
+ devinfo->dev_id,
+ devinfo->fifo_mode,
+ rate);
+}
+
+int am_device_deinit(aud_dev_info* devinfo)
+{
+ struct am_dev_fns* am_fn = &init_am_dev_fns[devinfo->dev_type];
+ return am_fn->aud_dev_deinit(devinfo->dev_id);
+}
+
+int am_set_stream_format(aud_dev_info* devinfo, am_stream_format_info *format)
+{
+ if (devinfo->dev_type == AUDIO_I2S_DEVICE) {
+ i2s_set_bit_size(devinfo->dev_id, format->bitsize);
+ i2s_set_samplerate(devinfo->dev_id, format->samplerate);
+ i2s_set_channels(devinfo->dev_id, format->channels);
+ i2s_set_fifo_attention(devinfo->dev_id,
+ devinfo->fifo_mode, format->buffersize);
+
+ } else if (devinfo->dev_type == AUDIO_SPDIF_DEVICE) {
+ spdif_set_bit_mode(devinfo->dev_id, format->bitsize);
+ spdif_set_sample_rate(
+ devinfo->dev_id,
+ devinfo->fifo_mode,
+ format->samplerate);
+ spdif_set_fifo_attention(devinfo->dev_id,
+ devinfo->fifo_mode, format->buffersize);
+ }
+ return 0;
+}
+
+int am_set_device_format(aud_dev_info* devinfo, am_dev_format_info *format)
+{
+ if (devinfo->dev_type == AUDIO_I2S_DEVICE) {
+ i2s_set_loopback(devinfo->dev_id, format->loopmode);
+ i2s_set_master(devinfo->dev_id, format->mastermode);
+ i2s_set_bit_format(devinfo->dev_id, format->audiomode);
+ i2s_set_left_right_control_polarity(
+ devinfo->dev_id,
+ format->polarity);
+
+ } else if (devinfo->dev_type == AUDIO_SPDIF_DEVICE) {
+
+ }
+ return 0;
+}
+
+int am_device_init(aud_dev_info* devinfo, void *dev_fmt, void *strm_fmt)
+{
+ am_stream_format_info *sfmt = (am_stream_format_info*)strm_fmt;
+ am_dev_format_info *dfmt = (am_dev_format_info*)dev_fmt;
+
+ if (devinfo->dev_type == AUDIO_I2S_DEVICE) {
+
+ struct tegra_i2s_property i2sprop;
+ memset(&i2sprop, 0, sizeof(i2sprop));
+
+ if (sfmt) {
+ i2sprop.bit_size = sfmt->bitsize;
+ i2sprop.sample_rate = sfmt->samplerate;
+ }
+
+ if (dfmt) {
+ i2sprop.master_mode = dfmt->mastermode;
+ i2sprop.audio_mode = dfmt->audiomode;
+ i2sprop.clk_rate = dfmt->clkrate;
+ i2sprop.fifo_fmt = dfmt->fifofmt;
+ }
+
+ return i2s_init(devinfo->dev_id, &i2sprop);
+
+ } else if (devinfo->dev_type == AUDIO_SPDIF_DEVICE) {
+
+ struct tegra_spdif_property spdifprop;
+ memset(&spdifprop, 0, sizeof(spdifprop));
+
+ if (dfmt) {
+ spdifprop.clk_rate = dfmt->clkrate;
+
+ return spdif_init(
+ devinfo->base,
+ devinfo->phy_base,
+ devinfo->fifo_mode,
+ &spdifprop);
+ }
+ }
+
+ return 0;
+}
+
int tegra_das_set_connection(enum tegra_das_port_con_id new_con_id)
{
return 0;
@@ -200,3 +608,4 @@ int tegra_das_get_mclk_rate(void)
EXPORT_SYMBOL_GPL(tegra_das_get_mclk_rate);
MODULE_LICENSE("GPL");
+#endif