summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRavindra Lokhande <rlokhande@nvidia.com>2010-11-24 19:37:51 +0530
committerNiket Sirsi <nsirsi@nvidia.com>2010-11-29 19:54:21 -0800
commitd432b8db509dc85b17e5d3230f6b3537da2adaa2 (patch)
tree2cd2406a7157a8016889c468bc06b98d214583c1
parenta00898a3a31d04c04ee9e1d3c500c9c8c02f29c1 (diff)
[tegra ALSA] create two devices for audio
Created two devices for alsa audio. Device 0 is connected to codec. Device 1 is connected to bt. Fixes bug 738770 Change-Id: I60c580bd4d792a41a109e458553f6295a21822e7 Reviewed-on: http://git-master/r/11603 Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com> Tested-by: Ravindra Lokhande <rlokhande@nvidia.com> Reviewed-by: Vijay Mali <vmali@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r--sound/soc/tegra/tegra_codec_rpc.c106
-rw-r--r--sound/soc/tegra/tegra_i2s.c56
-rw-r--r--sound/soc/tegra/tegra_pcm_rpc.c152
-rw-r--r--sound/soc/tegra/tegra_soc_audio.c30
-rw-r--r--sound/soc/tegra/tegra_transport.c15
-rw-r--r--sound/soc/tegra/tegra_transport.h11
6 files changed, 232 insertions, 138 deletions
diff --git a/sound/soc/tegra/tegra_codec_rpc.c b/sound/soc/tegra/tegra_codec_rpc.c
index 916dc06f8c87..6ee42c067093 100644
--- a/sound/soc/tegra/tegra_codec_rpc.c
+++ b/sound/soc/tegra/tegra_codec_rpc.c
@@ -28,7 +28,7 @@
#include "tegra_transport.h"
-extern struct tegra_audio_data* tegra_snd_cx;
+extern struct tegra_audio_data* tegra_snd_cx[];
static int tegra_master_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
@@ -45,11 +45,12 @@ static int tegra_master_volume_get(struct snd_kcontrol *kcontrol,
{
int rval = NvAudioFxVolumeDefault;
int lval = NvAudioFxVolumeDefault;
+ struct tegra_audio_data *ptscx = tegra_snd_cx[I2S1];
- if (tegra_snd_cx) {
- if (!tegra_audiofx_init(tegra_snd_cx)) {
- rval = tegra_snd_cx->i2s1volume;
- lval = tegra_snd_cx->i2s1volume;
+ if (ptscx) {
+ if (!tegra_audiofx_init(ptscx)) {
+ rval = ptscx->i2s1volume;
+ lval = ptscx->i2s1volume;
}
}
ucontrol->value.integer.value[0] = rval;
@@ -62,6 +63,8 @@ static int tegra_master_volume_put(struct snd_kcontrol *kcontrol,
{
int change = 0, val;
NvAudioFxVolumeDescriptor vd;
+ struct tegra_audio_data *ptscx = tegra_snd_cx[I2S1];
+
val = ucontrol->value.integer.value[0] & 0xffff;
vd.LeftVolume = val;
vd.RightVolume = val;
@@ -72,12 +75,12 @@ static int tegra_master_volume_put(struct snd_kcontrol *kcontrol,
vd.Mute = 1;
}
- if (tegra_snd_cx) {
- if (!tegra_audiofx_init(tegra_snd_cx)) {
- if(tegra_snd_cx->i2s1volume != val) {
- tegra_snd_cx->i2s1volume = val;
- tegra_snd_cx->xrt_fxn.SetProperty(
- tegra_snd_cx->mvolume,
+ if (ptscx) {
+ if (!tegra_audiofx_init(ptscx)) {
+ if(ptscx->i2s1volume != val) {
+ ptscx->i2s1volume = val;
+ ptscx->xrt_fxn.SetProperty(
+ ptscx->mvolume,
NvAudioFxVolumeProperty_Volume,
sizeof(NvAudioFxVolumeDescriptor),
&vd);
@@ -113,11 +116,13 @@ static int tegra_master_route_info(struct snd_kcontrol *kcontrol,
static int tegra_master_route_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
+ struct tegra_audio_data *ptscx = tegra_snd_cx[I2S1];
+
ucontrol->value.integer.value[0] = 0;
- if (tegra_snd_cx) {
- if (!tegra_audiofx_init(tegra_snd_cx)) {
+ if (ptscx) {
+ if (!tegra_audiofx_init(ptscx)) {
ucontrol->value.integer.value[0] =
- tegra_snd_cx->spdif_plugin;
+ ptscx->spdif_plugin;
}
}
return 0;
@@ -127,12 +132,14 @@ static int tegra_master_route_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int change = 0, val;
+ struct tegra_audio_data *ptscx = tegra_snd_cx[I2S1];
+
val = ucontrol->value.integer.value[0] & 0xffff;
- if (tegra_snd_cx) {
- if (!tegra_audiofx_init(tegra_snd_cx)) {
- tegra_snd_cx->spdif_plugin = val;
- tegra_audiofx_route(tegra_snd_cx);
+ if (ptscx) {
+ if (!tegra_audiofx_init(ptscx)) {
+ ptscx->spdif_plugin = val;
+ tegra_audiofx_route(ptscx);
change = 1;
}
}
@@ -195,34 +202,56 @@ static struct snd_soc_dai_ops dit_stub_ops = {
.set_sysclk = tegra_generic_codec_set_dai_sysclk,
};
-struct snd_soc_dai tegra_generic_codec_dai = {
- .name = "tegra-codec-rpc",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = TEGRA_SAMPLE_RATES,
- .formats = TEGRA_SAMPLE_FORMATS,
+struct snd_soc_dai tegra_generic_codec_dai[] = {
+ {
+ .name = "tegra-codec-rpc",
+ .id = 0,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TEGRA_SAMPLE_RATES,
+ .formats = TEGRA_SAMPLE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TEGRA_SAMPLE_RATES,
+ .formats = TEGRA_SAMPLE_FORMATS,
+ },
+ .ops = &dit_stub_ops,
},
- .capture = {
- .stream_name = "Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = TEGRA_SAMPLE_RATES,
- .formats = TEGRA_SAMPLE_FORMATS,
- },
- .ops = &dit_stub_ops,
+ {
+ .name = "tegra-codec-bluetooth",
+ .id = 1,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TEGRA_SAMPLE_RATES,
+ .formats = TEGRA_SAMPLE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TEGRA_SAMPLE_RATES,
+ .formats = TEGRA_SAMPLE_FORMATS,
+ },
+ .ops = &dit_stub_ops,
+ }
};
EXPORT_SYMBOL_GPL(tegra_generic_codec_dai);
static int __init dit_modinit(void)
{
- return snd_soc_register_dai(&tegra_generic_codec_dai);
+ return snd_soc_register_dais(tegra_generic_codec_dai, ARRAY_SIZE(tegra_generic_codec_dai));
}
static void __exit dit_exit(void)
{
- snd_soc_unregister_dai(&tegra_generic_codec_dai);
+ snd_soc_unregister_dais(tegra_generic_codec_dai, ARRAY_SIZE(tegra_generic_codec_dai));
}
module_init(dit_modinit);
@@ -243,12 +272,13 @@ static int codec_soc_probe(struct platform_device *pdev)
codec->name = "tegra-generic-codec";
codec->owner = THIS_MODULE;
- codec->dai = &tegra_generic_codec_dai;
- codec->num_dai = 1;
+ codec->dai = tegra_generic_codec_dai;
+ codec->num_dai = ARRAY_SIZE(tegra_generic_codec_dai);
codec->write = NULL;
codec->read = NULL;
INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths);
+
/* Register PCMs. */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) {
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
index 2edb1033a399..ea0f597c91cf 100644
--- a/sound/soc/tegra/tegra_i2s.c
+++ b/sound/soc/tegra/tegra_i2s.c
@@ -39,8 +39,6 @@
#include "nvassert.h"
#include "tegra_transport.h"
-extern struct snd_soc_dai tegra_i2s_rpc_dai;
-
static int tegra_i2s_rpc_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -72,35 +70,55 @@ static struct snd_soc_dai_ops tegra_dai_ops = {
.hw_params = tegra_i2s_rpc_hw_params,
};
-struct snd_soc_dai tegra_i2s_rpc_dai = {
- .name = "tegra-i2s-rpc",
- .id = 0,
- .probe = tegra_i2s_rpc_probe,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = TEGRA_SAMPLE_RATES,
- .formats = TEGRA_SAMPLE_FORMATS,
+struct snd_soc_dai tegra_i2s_rpc_dai[] = {
+ {
+ .name = "tegra-i2s-rpc",
+ .id = 0,
+ .probe = tegra_i2s_rpc_probe,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TEGRA_SAMPLE_RATES,
+ .formats = TEGRA_SAMPLE_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TEGRA_SAMPLE_RATES,
+ .formats = TEGRA_SAMPLE_FORMATS,
+ },
+ .ops = &tegra_dai_ops,
},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = TEGRA_SAMPLE_RATES,
- .formats = TEGRA_SAMPLE_FORMATS,
+ {
+ .name = "tegra-i2s-rpc",
+ .id = 1,
+ .probe = tegra_i2s_rpc_probe,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TEGRA_SAMPLE_RATES,
+ .formats = TEGRA_SAMPLE_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TEGRA_SAMPLE_RATES,
+ .formats = TEGRA_SAMPLE_FORMATS,
+ },
+ .ops = &tegra_dai_ops,
},
- .ops = &tegra_dai_ops,
};
EXPORT_SYMBOL_GPL(tegra_i2s_rpc_dai);
static int __init tegra_i2s_rpc_init(void)
{
- return snd_soc_register_dai(&tegra_i2s_rpc_dai);
+ return snd_soc_register_dais(tegra_i2s_rpc_dai, ARRAY_SIZE(tegra_i2s_rpc_dai));
}
module_init(tegra_i2s_rpc_init);
static void __exit tegra_i2s_rpc_exit(void)
{
- snd_soc_unregister_dai(&tegra_i2s_rpc_dai);
+ snd_soc_unregister_dais(tegra_i2s_rpc_dai, ARRAY_SIZE(tegra_i2s_rpc_dai));
}
module_exit(tegra_i2s_rpc_exit);
diff --git a/sound/soc/tegra/tegra_pcm_rpc.c b/sound/soc/tegra/tegra_pcm_rpc.c
index b15244018f29..fd1c8cb55ee3 100644
--- a/sound/soc/tegra/tegra_pcm_rpc.c
+++ b/sound/soc/tegra/tegra_pcm_rpc.c
@@ -22,7 +22,7 @@
#include "tegra_transport.h"
-struct tegra_audio_data* tegra_snd_cx = NULL;
+struct tegra_audio_data* tegra_snd_cx[2];
static const struct snd_pcm_hardware tegra_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE |\
@@ -40,7 +40,6 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
.fifo_size = 8,
};
-
static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -59,7 +58,8 @@ static int tegra_pcm_prepare(struct snd_pcm_substream *substream)
return 0;
}
-static inline NvAudioFxState play_state(struct pcm_runtime_data *prtd,
+static inline NvAudioFxState play_state(struct tegra_audio_data *ptscx,
+ struct pcm_runtime_data *prtd,
NvAudioFxState cur_state)
{
NvAudioFxState state = cur_state;
@@ -68,7 +68,7 @@ static inline NvAudioFxState play_state(struct pcm_runtime_data *prtd,
case SNDRV_PCM_TRIGGER_START:
if (state != NvAudioFxState_Run) {
state = NvAudioFxState_Run;
- tegra_snd_cx->xrt_fxn.SetProperty(
+ ptscx->xrt_fxn.SetProperty(
prtd->stdoutpath->Stream,
NvAudioFxProperty_State,
sizeof(NvAudioFxState),
@@ -78,7 +78,7 @@ static inline NvAudioFxState play_state(struct pcm_runtime_data *prtd,
case SNDRV_PCM_TRIGGER_STOP:
if (state != NvAudioFxState_Stop) {
state = NvAudioFxState_Stop;
- tegra_snd_cx->xrt_fxn.SetProperty(
+ ptscx->xrt_fxn.SetProperty(
prtd->stdoutpath->Stream,
NvAudioFxProperty_State,
sizeof(NvAudioFxState),
@@ -98,6 +98,8 @@ static inline int queue_next_buffer(void *arg, int cur_offset)
struct snd_pcm_substream *substream = (struct snd_pcm_substream *)arg;
struct snd_pcm_runtime *runtime = substream->runtime;
struct pcm_runtime_data *prtd = substream->runtime->private_data;
+ struct snd_pcm *pcm = substream->pcm;
+ struct tegra_audio_data *ptscx = tegra_snd_cx[pcm->device];
int offset = cur_offset;
int size, rtbuffersize;
NvAudioFxBufferDescriptor abd;
@@ -119,7 +121,7 @@ static inline int queue_next_buffer(void *arg, int cur_offset)
abd.Format.ChannelMask = 0;
abd.Format.ValidBitsPerSample = 0;
- tegra_snd_cx->xrt_fxn.StreamAddBuffer(
+ ptscx->xrt_fxn.StreamAddBuffer(
(NvAudioFxStreamHandle)prtd->stdoutpath->Stream,
&abd);
@@ -174,6 +176,8 @@ static int play_thread( void *arg)
struct snd_pcm_substream *substream = (struct snd_pcm_substream *)arg;
struct snd_pcm_runtime *runtime = substream->runtime;
struct pcm_runtime_data *prtd = substream->runtime->private_data;
+ struct snd_pcm *pcm = substream->pcm;
+ struct tegra_audio_data *ptscx = tegra_snd_cx[pcm->device];
int offset = 0;
int rtbuffersize = 0;
int buffer_to_prime = 0, buffer_in_queue = 0;
@@ -185,7 +189,7 @@ static int play_thread( void *arg)
if (runtime->control->appl_ptr)
for (;;) {
- state = play_state(prtd, state);
+ state = play_state(ptscx, prtd, state);
if (state == SNDRV_PCM_TRIGGER_STOP)
buffer_in_queue = 0;
if (kthread_should_stop())
@@ -210,7 +214,7 @@ static int play_thread( void *arg)
}
for (;;) {
- state = play_state(prtd, state);
+ state = play_state(ptscx, prtd, state);
if (state == SNDRV_PCM_TRIGGER_STOP)
buffer_in_queue = 0;
if (kthread_should_stop())
@@ -250,6 +254,8 @@ static int rec_thread( void *arg )
NvAudioFxBufferDescriptor abd;
NvAudioFxState state = NVALSA_INVALID_STATE;
NvAudioFxPinFormatDescriptor pin_format;
+ struct snd_pcm *pcm = substream->pcm;
+ struct tegra_audio_data *ptscx = tegra_snd_cx[pcm->device];
wait_for_completion(&prtd->thread_comp);
rtbuffersize = frames_to_bytes(runtime, runtime->buffer_size);
@@ -267,7 +273,7 @@ static int rec_thread( void *arg )
pin_format.Format.ValidBitsPerSample = 0;
pin_format.Pin = NvAudioFxSourcePin;
- e = tegra_snd_cx->xrt_fxn.SetProperty(
+ e = ptscx->xrt_fxn.SetProperty(
prtd->stdinpath->Convert,
NvAudioFxPinProperty_Format,
sizeof(NvAudioFxPinFormatDescriptor),
@@ -276,7 +282,7 @@ static int rec_thread( void *arg )
snd_printk(KERN_ERR"set_property failed!\n");
}
- e = tegra_snd_cx->xrt_fxn.SetProperty(
+ e = ptscx->xrt_fxn.SetProperty(
prtd->stdinpath->Src,
NvAudioFxProperty_SampleRate,
sizeof(NvS32),
@@ -286,7 +292,7 @@ static int rec_thread( void *arg )
}
state = NvAudioFxState_Run;
- tegra_snd_cx->xrt_fxn.SetProperty(
+ ptscx->xrt_fxn.SetProperty(
prtd->stdinpath->Stream,
NvAudioFxProperty_State,
sizeof(NvAudioFxState),
@@ -296,7 +302,7 @@ static int rec_thread( void *arg )
case SNDRV_PCM_TRIGGER_STOP:
if (state != NvAudioFxState_Stop) {
state = NvAudioFxState_Stop;
- tegra_snd_cx->xrt_fxn.SetProperty(
+ ptscx->xrt_fxn.SetProperty(
prtd->stdinpath->Stream,
NvAudioFxProperty_State,
sizeof(NvAudioFxState),
@@ -327,7 +333,7 @@ static int rec_thread( void *arg )
abd.Format.Channels = runtime->channels;
abd.Format.ChannelMask = 0;
- e = tegra_snd_cx->xrt_fxn.StreamAddBuffer(
+ e = ptscx->xrt_fxn.StreamAddBuffer(
(NvAudioFxStreamHandle)prtd->stdinpath->Stream, &abd);
buffer_in_queue++;
offset += size;
@@ -443,6 +449,8 @@ static int pcm_common_close(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct pcm_runtime_data *prtd = runtime->private_data;
+ struct snd_pcm *pcm = substream->pcm;
+ struct tegra_audio_data *ptscx = tegra_snd_cx[pcm->device];
NvAudioFxMessage message;
NvError e;
@@ -462,7 +470,7 @@ static int pcm_common_close(struct snd_pcm_substream *substream)
if (prtd->rec_thread)
kthread_stop(prtd->rec_thread);
- if (tegra_snd_cx->m_FxNotifier.Event) {
+ if (ptscx->m_FxNotifier.Event) {
memset(&message, 0, sizeof(NvAudioFxMessage));
message.Event = NvAudioFxEventAll;
@@ -472,13 +480,13 @@ static int pcm_common_close(struct snd_pcm_substream *substream)
else
message.hFx = (NvAudioFxHandle)prtd->stdinpath->Stream;
- e = tegra_snd_cx->xrt_fxn.SetProperty(
- (NvAudioFxObjectHandle)tegra_snd_cx->m_FxNotifier.hNotifier,
+ e = ptscx->xrt_fxn.SetProperty(
+ (NvAudioFxObjectHandle)ptscx->m_FxNotifier.hNotifier,
NvAudioFxIoProperty_RemoveEvent,
sizeof(NvAudioFxMessage),
&message);
- tegra_snd_cx->m_FxNotifier.Event &= ~NvAudioFxEventAll;
+ ptscx->m_FxNotifier.Event &= ~NvAudioFxEventAll;
}
if (prtd->stdoutpath) {
@@ -500,10 +508,13 @@ static int pcm_common_close(struct snd_pcm_substream *substream)
static int tegra_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm *pcm = substream->pcm;
struct pcm_runtime_data *prtd;
int ret = 0;
NvError e = NvSuccess;
NvAudioFxMessage message;
+ NvAudioFxObjectHandle hSource = 0;
+ struct tegra_audio_data *ptscx = tegra_snd_cx[pcm->device];
prtd = kzalloc(sizeof(struct pcm_runtime_data), GFP_KERNEL);
if (prtd == NULL)
@@ -518,8 +529,8 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
prtd->state = NVALSA_INVALID_STATE;
prtd->stream = substream->stream;
- if (!tegra_snd_cx->mixer_handle) {
- ret = tegra_audiofx_init(tegra_snd_cx);
+ if (!ptscx->mixer_handle) {
+ ret = tegra_audiofx_init(ptscx);
if (ret)
goto fail;
}
@@ -529,8 +540,11 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
sema_init(&prtd->buf_done_sem, 0);
sema_init(&prtd->stop_done_sem, 0);
+ if (pcm->device == I2S2)
+ hSource = ptscx->mi2s2;
+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
- prtd->mixer_buffer = tegra_snd_cx->mixer_buffer[0];
+ prtd->mixer_buffer = ptscx->mixer_buffer[0];
prtd->stdoutpath = (StandardPath*)kzalloc(sizeof(StandardPath),
GFP_KERNEL);
if (prtd->stdoutpath == NULL) {
@@ -539,9 +553,10 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
goto fail;
}
- e = tegra_audiofx_create_output(tegra_snd_cx->m_hRm,
- tegra_snd_cx->mixer_handle,
- prtd->stdoutpath);
+ e = tegra_audiofx_create_output(ptscx->m_hRm,
+ ptscx->mixer_handle,
+ prtd->stdoutpath,
+ hSource);
if (e != NvSuccess) {
snd_printk(KERN_ERR "audiofx_create_output failed \n");
ret = -EFAULT;
@@ -554,8 +569,8 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
message.hFx = (NvAudioFxHandle)prtd->stdoutpath->Stream;
message.pContext = prtd;
- e = tegra_snd_cx->xrt_fxn.SetProperty(
- (NvAudioFxObjectHandle)tegra_snd_cx->m_FxNotifier.hNotifier,
+ e = ptscx->xrt_fxn.SetProperty(
+ (NvAudioFxObjectHandle)ptscx->m_FxNotifier.hNotifier,
NvAudioFxIoProperty_AddEvent,
sizeof(NvAudioFxMessage),
&message);
@@ -566,7 +581,7 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
goto fail;
}
- tegra_snd_cx->m_FxNotifier.Event |= (NvAudioFxEventBufferDone |
+ ptscx->m_FxNotifier.Event |= (NvAudioFxEventBufferDone |
NvAudioFxEventStateChange);
prtd->play_thread = kthread_run(play_thread,
@@ -579,7 +594,7 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
goto fail;
}
} else {
- prtd->mixer_buffer = tegra_snd_cx->mixer_buffer[1];
+ prtd->mixer_buffer = ptscx->mixer_buffer[1];
prtd->stdinpath = (StandardPath*)kzalloc(sizeof(StandardPath),
GFP_KERNEL);
if (prtd->stdinpath == NULL) {
@@ -587,10 +602,11 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
ret = -ENOMEM;
goto fail;
}
- e = tegra_audiofx_create_input(tegra_snd_cx->m_hRm,
- tegra_snd_cx->mixer_handle,
+ e = tegra_audiofx_create_input(ptscx->m_hRm,
+ ptscx->mixer_handle,
prtd->stdinpath,
- NvAudioInputSelect_Record);
+ NvAudioInputSelect_Record,
+ hSource);
if (e != NvSuccess) {
snd_printk(KERN_ERR "audiofx_create_input failed \n");
ret = -EFAULT;
@@ -603,8 +619,8 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
message.hFx = (NvAudioFxHandle)prtd->stdinpath->Stream;
message.pContext = prtd;
- e = tegra_snd_cx->xrt_fxn.SetProperty(
- (NvAudioFxObjectHandle)tegra_snd_cx->m_FxNotifier.hNotifier,
+ e = ptscx->xrt_fxn.SetProperty(
+ (NvAudioFxObjectHandle)ptscx->m_FxNotifier.hNotifier,
NvAudioFxIoProperty_AddEvent,
sizeof(NvAudioFxMessage),
&message);
@@ -613,7 +629,7 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
ret = -EFAULT;
goto fail;
}
- tegra_snd_cx->m_FxNotifier.Event |= (NvAudioFxEventBufferDone |
+ ptscx->m_FxNotifier.Event |= (NvAudioFxEventBufferDone |
NvAudioFxEventStateChange);
prtd->rec_thread = kthread_run(rec_thread,
@@ -696,43 +712,45 @@ static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
size_t size = tegra_pcm_hardware.buffer_bytes_max;
void *virt_buf_ptr = NULL;
NvRmPhysAddr phy_address;
+ struct tegra_audio_data *ptscx = tegra_snd_cx[pcm->device];
int ret = 0;
NvError e;
- e = NvRmMemHandleCreate(tegra_snd_cx->m_hRm,
- &tegra_snd_cx->mem_handle[stream],
+
+ e = NvRmMemHandleCreate(ptscx->m_hRm,
+ &ptscx->mem_handle[stream],
size);
if (e == NvSuccess) {
- e = NvRmMemAlloc(tegra_snd_cx->mem_handle[stream],
- NULL,
- 0,
- PAGE_SIZE,
- NvOsMemAttribute_Uncached);
+ e = NvRmMemAlloc(ptscx->mem_handle[stream],
+ NULL,
+ 0,
+ PAGE_SIZE,
+ NvOsMemAttribute_Uncached);
}
if (e == NvSuccess) {
- phy_address = (NvU32)(NvRmMemPin(tegra_snd_cx->mem_handle[stream]));
+ phy_address = (NvU32)(NvRmMemPin(ptscx->mem_handle[stream]));
}
if (e != NvSuccess) {
- NvRmMemHandleFree(tegra_snd_cx->mem_handle[stream]);
+ NvRmMemHandleFree(ptscx->mem_handle[stream]);
ret = -ENOMEM;
goto end;
}
- e = NvRmMemMap(tegra_snd_cx->mem_handle[stream],
- 0,
- size,
- NVOS_MEM_READ_WRITE,
- (void**)&virt_buf_ptr);
+ e = NvRmMemMap(ptscx->mem_handle[stream],
+ 0,
+ size,
+ NVOS_MEM_READ_WRITE,
+ (void**)&virt_buf_ptr);
if (e != NvSuccess) {
- NvRmMemHandleFree(tegra_snd_cx->mem_handle[stream]);
+ NvRmMemHandleFree(ptscx->mem_handle[stream]);
ret = -ENOMEM;
goto end;
}
- tegra_snd_cx->mapped_buf_size = size;
+ ptscx->mapped_buf_size = size;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev;
@@ -756,13 +774,14 @@ static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
{
struct snd_pcm_substream *substream = pcm->streams[stream].substream;
struct snd_dma_buffer *buf = &substream->dma_buffer;
+ struct tegra_audio_data *ptscx = tegra_snd_cx[pcm->device];
- if (tegra_snd_cx->mixer_buffer[stream])
- tegra_snd_cx->xrt_fxn.MixerUnmapBuffer(
- tegra_snd_cx->mixer_buffer[stream]);
+ if (ptscx->mixer_buffer[stream])
+ ptscx->xrt_fxn.MixerUnmapBuffer(
+ ptscx->mixer_buffer[stream]);
- NvRmMemUnmap(tegra_snd_cx->mem_handle[stream],buf->area,buf->bytes);
- DestroyMemoryHandle(tegra_snd_cx->mem_handle[stream]);
+ NvRmMemUnmap(ptscx->mem_handle[stream],buf->area,buf->bytes);
+ DestroyMemoryHandle(ptscx->mem_handle[stream]);
}
static void tegra_pcm_free_dma_buffers(struct snd_pcm *pcm)
@@ -780,20 +799,23 @@ static void tegra_pcm_free_dma_buffers(struct snd_pcm *pcm)
}
}
-
static int tegra_pcm_new(struct snd_card *card,
struct snd_soc_dai *dai,
struct snd_pcm *pcm)
{
+ struct tegra_audio_data *ptscx;
int ret = 0;
- tegra_snd_cx = kzalloc(sizeof(struct tegra_audio_data),
- GFP_KERNEL);
- if (tegra_snd_cx == NULL)
+ ptscx = kzalloc(sizeof(struct tegra_audio_data),
+ GFP_KERNEL);
+ if (ptscx == NULL)
return -ENOMEM;
- tegra_snd_cx->m_hRm = s_hRmGlobal;
- mutex_init(&tegra_snd_cx->lock);
+ ptscx->m_hRm = s_hRmGlobal;
+ ptscx->device_id = pcm->device;
+ mutex_init(&ptscx->lock);
+
+ tegra_snd_cx[pcm->device] = ptscx;
if (dai->playback.channels_min) {
ret = tegra_pcm_preallocate_dma_buffer(pcm,
@@ -812,8 +834,8 @@ static int tegra_pcm_new(struct snd_card *card,
return 0;
out:
- if (tegra_snd_cx)
- kfree(tegra_snd_cx);
+ if (ptscx)
+ kfree(ptscx);
snd_printk(KERN_ERR "pcm_new failed\n");
return ret;
}
@@ -825,8 +847,10 @@ static int tegra_pcm_probe(struct platform_device *pdev)
static int tegra_pcm_remove(struct platform_device *pdev)
{
- if (tegra_snd_cx)
- kfree(tegra_snd_cx);
+ if (tegra_snd_cx[I2S1])
+ kfree(tegra_snd_cx[I2S1]);
+ if (tegra_snd_cx[I2S2])
+ kfree(tegra_snd_cx[I2S2]);
return 0;
}
diff --git a/sound/soc/tegra/tegra_soc_audio.c b/sound/soc/tegra/tegra_soc_audio.c
index 262d8760902e..fa4a8db62534 100644
--- a/sound/soc/tegra/tegra_soc_audio.c
+++ b/sound/soc/tegra/tegra_soc_audio.c
@@ -48,7 +48,7 @@ struct codec_setup_data {
};
extern struct snd_soc_codec_device soc_codec_dev_tegra_generic_codec;
-extern struct snd_soc_dai tegra_generic_codec_dai;
+extern struct snd_soc_dai tegra_generic_codec_dai[];
static struct platform_device *tegra_snd_device;
NvU64 codec_guid;
@@ -110,20 +110,30 @@ static int tegra_codec_init(struct snd_soc_codec *codec)
extern struct snd_soc_dai tegra_i2s_rpc_dai;
extern struct snd_soc_platform tegra_soc_platform;
-static struct snd_soc_dai_link tegra_board_dai = {
- .name = "tegra-generic-codec",
- .stream_name = "tegra-codec-rpc",
- .cpu_dai = &tegra_i2s_rpc_dai,
- .codec_dai = &tegra_generic_codec_dai,
- .init = tegra_codec_init,
- .ops = &tegra_hifi_ops,
+static struct snd_soc_dai_link tegra_board_dai[] = {
+ {
+ .name = "tegra-generic-codec",
+ .stream_name = "tegra-codec-rpc",
+ .cpu_dai = &tegra_i2s_rpc_dai,
+ .codec_dai = &tegra_generic_codec_dai[I2S1],
+ .init = tegra_codec_init,
+ .ops = &tegra_hifi_ops,
+ },
+ {
+ .name = "tegra-bluetooth",
+ .stream_name = "tegra-codec-bluetooth",
+ .cpu_dai = &tegra_i2s_rpc_dai,
+ .codec_dai = &tegra_generic_codec_dai[I2S2],
+ .init = tegra_codec_init,
+ .ops = &tegra_hifi_ops,
+ }
};
static struct snd_soc_card tegra_board = {
.name = "tegra",
.platform = &tegra_soc_platform,
- .dai_link = &tegra_board_dai,
- .num_links = 1,
+ .dai_link = tegra_board_dai,
+ .num_links = ARRAY_SIZE(tegra_board_dai),
};
static struct snd_soc_device tegra_board_snd_devdata = {
diff --git a/sound/soc/tegra/tegra_transport.c b/sound/soc/tegra/tegra_transport.c
index 679408d6ee88..cdf2de2cc3f1 100644
--- a/sound/soc/tegra/tegra_transport.c
+++ b/sound/soc/tegra/tegra_transport.c
@@ -550,6 +550,10 @@ int tegra_audiofx_init(struct tegra_audio_data* tegra_snd_cx)
NvAudioFxI2s1Id);
tegra_snd_cx->mi2s1_device_available = NvAudioFxIoDevice_Default;
+ tegra_snd_cx->mi2s2 = tegra_snd_cx->xrt_fxn.MixerCreateObject(
+ tegra_snd_cx->mixer_handle,
+ NvAudioFxI2s2Id);
+
memset(&message, 0, sizeof(NvAudioFxMessage));
message.Event = NvAudioFxEventControlChange;
message.hFx = (NvAudioFxHandle)tegra_snd_cx->mi2s1;
@@ -872,7 +876,8 @@ void tegra_audiofx_destroyfx(struct tegra_audio_data *audio_context)
NvError tegra_audiofx_create_output(NvRmDeviceHandle hRmDevice,
NvAudioFxMixerHandle hMixer,
- StandardPath* pPath)
+ StandardPath* pPath,
+ NvAudioFxObjectHandle hSource)
{
NvError e = NvSuccess;
NvAudioFxConnectionDescriptor connection;
@@ -896,7 +901,7 @@ NvError tegra_audiofx_create_output(NvRmDeviceHandle hRmDevice,
connection.hSource = (NvAudioFxHandle)pPath->Volume;
connection.SourcePin = NvAudioFxSourcePin;
- connection.hSink = 0;
+ connection.hSink = (NvAudioFxHandle)hSource;
connection.SinkPin = NvAudioFxSinkPin;
e = tegra_transport_set_property(pPath->Volume,
NvAudioFxProperty_Attach,
@@ -951,7 +956,8 @@ NvError tegra_audiofx_destroy_output(StandardPath* pPath)
NvError tegra_audiofx_create_input(NvRmDeviceHandle hRmDevice,
NvAudioFxMixerHandle hMixer,
StandardPath* pInput,
- InputSelection InputSelect)
+ InputSelection InputSelect,
+ NvAudioFxObjectHandle hSource)
{
NvError e = NvSuccess;
NvAudioFxConnectionDescriptor connection;
@@ -994,12 +1000,11 @@ NvError tegra_audiofx_create_input(NvRmDeviceHandle hRmDevice,
audiofx_path_connect(pInput->Src, pInput->Convert);
/* Wire 5 */
- connection.hSource = 0;
connection.SourcePin = (InputSelect == NvAudioInputSelect_Record) ?
NvAudioFxSourcePin : NvAudioFxLoopbackPin;
connection.hSink = (NvAudioFxHandle)pInput->Src;
connection.SinkPin = NvAudioFxSinkPin;
- e = tegra_transport_set_property(0,
+ e = tegra_transport_set_property(hSource,
NvAudioFxProperty_Attach,
sizeof(NvAudioFxConnectionDescriptor),
&connection);
diff --git a/sound/soc/tegra/tegra_transport.h b/sound/soc/tegra/tegra_transport.h
index 824d95f94393..49eee47b1373 100644
--- a/sound/soc/tegra/tegra_transport.h
+++ b/sound/soc/tegra/tegra_transport.h
@@ -43,6 +43,9 @@
#include "tegra_sndfx.h"
+#define I2S1 0
+#define I2S2 1
+
#define INIT_TIMEOUT 5000
#define PLAY_TIMEOUT 5000
#define REC_TIMEOUT 5000
@@ -412,11 +415,13 @@ struct tegra_audio_data {
NvRmMemHandle mem_handle[2];
NvAudioFxObjectHandle mvolume;
NvAudioFxObjectHandle mi2s1;
+ NvAudioFxObjectHandle mi2s2;
NvAudioFxObjectHandle mroute;
NvAudioFxIoDevice mi2s1_device_available;
NvAudioFxIoDevice mspdif_device_available;
int spdif_plugin;
int i2s1volume;
+ int device_id;
struct mutex lock;
};
@@ -425,12 +430,14 @@ NvError tegra_audiofx_createfx(struct tegra_audio_data *audio_context);
void tegra_audiofx_destroyfx(struct tegra_audio_data *audio_context);
NvError tegra_audiofx_create_output(NvRmDeviceHandle,
NvAudioFxMixerHandle,
- StandardPath*);
+ StandardPath*,
+ NvAudioFxObjectHandle hSource);
NvError tegra_audiofx_destroy_output(StandardPath* pPath);
NvError tegra_audiofx_create_input(NvRmDeviceHandle hRmDevice,
NvAudioFxMixerHandle hMixer,
StandardPath* pPath,
- InputSelection InputSelect);
+ InputSelection InputSelect,
+ NvAudioFxObjectHandle hSource);
NvError tegra_audiofx_destroy_input(StandardPath* pPath);
NvError tegra_audiofx_route(struct tegra_audio_data* tegra_snd_cx);
NvError tegra_transport_init(NvddkAudioFxFxnTable* FxTransportFxFxnTable);