diff options
author | Ravindra Lokhande <rlokhande@nvidia.com> | 2010-11-24 19:37:51 +0530 |
---|---|---|
committer | Niket Sirsi <nsirsi@nvidia.com> | 2010-11-29 19:54:21 -0800 |
commit | d432b8db509dc85b17e5d3230f6b3537da2adaa2 (patch) | |
tree | 2cd2406a7157a8016889c468bc06b98d214583c1 | |
parent | a00898a3a31d04c04ee9e1d3c500c9c8c02f29c1 (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.c | 106 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_i2s.c | 56 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_pcm_rpc.c | 152 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_soc_audio.c | 30 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_transport.c | 15 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_transport.h | 11 |
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); |