summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2010-07-06 11:00:48 +0530
committerBharat Nihalani <bnihalani@nvidia.com>2010-07-07 01:37:09 -0700
commit7847f4798e34461d09205e179a72bc55fd0ccc82 (patch)
treed58758aa0633b59a25c88d85ac69431c31f0845d /sound
parent18d889a1c53eab1ffa114eeb784a3e8c419e77ad (diff)
[tegra alsa] Fix SPDIF routing
On TOT when HDMI or BT device is connected to system we used to always route audio to SPDIF/A2dp device ignoring os driver routing policies. Fixing this issue. This fix will ensure we always route audio to the device(s) asked by os audio driver instead of taking decision at audiofx level. Making required changes in ALSA. Since ALSA do not have any routing policy implemented yet whenever it will get SPDIF or HP available notification it will set corresponding device as output device. Bug 702150 Bug 701555 Change-Id: Ic24c3325b1b016f6887631ab086d8e535cad081e Reviewed-on: http://git-master/r/3561 Tested-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-by: Stephen Holmes <sholmes@nvidia.com> Reviewed-by: Vijay Mali <vmali@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra_sndfx.h7
-rw-r--r--sound/soc/tegra/tegra_transport.c109
-rw-r--r--sound/soc/tegra/tegra_transport.h1
3 files changed, 114 insertions, 3 deletions
diff --git a/sound/soc/tegra/tegra_sndfx.h b/sound/soc/tegra/tegra_sndfx.h
index 00f58436e75e..3efcdfbe6ad7 100644
--- a/sound/soc/tegra/tegra_sndfx.h
+++ b/sound/soc/tegra/tegra_sndfx.h
@@ -102,6 +102,8 @@ typedef NvS32 NvObjectId;
#define NvAudioFxPlaybackSplitId (0x11300001)
#define NvAudioFxRecordMixId (0x11300002)
#define NvAudioFxRecordSplitId (0x11300003)
+#define NvAudioFxLoopbackMixId (0x1130000D)
+#define NvAudioFxLoopbackSplitId (0x1130000E)
#define NvAudioFxSpdifPlaybackMixId (0x11300004)
#define NvAudioFxSpdifRecordSplitId (0x11300005)
#define NvAudioFxSpdifLoopbackSplitId (0x11300006)
@@ -212,7 +214,7 @@ typedef struct NvAudioFxFormatRec
typedef NvS32 NvAudioFxMode;
#define NvAudioFxMode_Normal (0x0)
-#define NvAudioFxMode_Bluetooth (0x1)
+#define NvAudioFxMode_Bluetooth_Sco (0x1)
#define NvAudioFxMode_Ringtone (0x2)
#define NvAudioFxMode_InCall (0x4)
#define NvAudioFxMode_Radio (0x8)
@@ -311,12 +313,13 @@ typedef NvS32 NvAudioFxIoDevice;
#define NvAudioFxIoDevice_EarSpeaker (0x200)
#define NvAudioFxIoDevice_LineOut (0x400)
#define NvAudioFxIoDevice_HeadphoneOut (0x800)
+#define NvAudioFxIoDevice_Bluetooth_A2dp (0x1000)
// Both
#define NvAudioFxIoDevice_Aux (0x10000)
#define NvAudioFxIoDevice_Phone (0x20000)
#define NvAudioFxIoDevice_Radio (0x40000)
-#define NvAudioFxIoDevice_Bluetooth (0x80000)
+#define NvAudioFxIoDevice_Bluetooth_Sco (0x80000)
typedef struct NvAudioFxPeqDescriptorRec
{
diff --git a/sound/soc/tegra/tegra_transport.c b/sound/soc/tegra/tegra_transport.c
index 157c6d7c3476..c013908d1dfc 100644
--- a/sound/soc/tegra/tegra_transport.c
+++ b/sound/soc/tegra/tegra_transport.c
@@ -481,6 +481,7 @@ int tegra_audiofx_init(struct tegra_audio_data* tegra_snd_cx)
{
NvError e = NvSuccess;
int ret = 0;
+ NvAudioFxMessage message;
if (!tegra_snd_cx->mixer_handle) {
mutex_lock(&tegra_snd_cx->lock);
@@ -541,7 +542,47 @@ int tegra_audiofx_init(struct tegra_audio_data* tegra_snd_cx)
tegra_snd_cx->mroute = tegra_snd_cx->xrt_fxn.MixerCreateObject(
tegra_snd_cx->mixer_handle,
NvAudioFxSpdifId);
- tegra_snd_cx->spdif_plugin = 0;
+ tegra_snd_cx->spdif_plugin = 1;
+
+ tegra_snd_cx->mi2s1 = tegra_snd_cx->xrt_fxn.MixerCreateObject(
+ tegra_snd_cx->mixer_handle,
+ NvAudioFxI2s1Id);
+
+ memset(&message, 0, sizeof(NvAudioFxMessage));
+ message.Event = NvAudioFxEventControlChange;
+ message.hFx = (NvAudioFxHandle)tegra_snd_cx->mi2s1;
+ message.pContext = tegra_snd_cx;
+
+ e = tegra_snd_cx->xrt_fxn.SetProperty(
+ (NvAudioFxObjectHandle)tegra_snd_cx->m_FxNotifier.hNotifier,
+ NvAudioFxIoProperty_AddEvent,
+ sizeof(NvAudioFxMessage),
+ &message);
+
+ if (e != NvSuccess) {
+ snd_printk(KERN_ERR "TransportSetProperty failed\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ memset(&message, 0, sizeof(NvAudioFxMessage));
+ message.Event = NvAudioFxEventControlChange;
+ message.hFx = (NvAudioFxHandle)tegra_snd_cx->mroute;
+ message.pContext = tegra_snd_cx;
+
+ e = tegra_snd_cx->xrt_fxn.SetProperty(
+ (NvAudioFxObjectHandle)tegra_snd_cx->m_FxNotifier.hNotifier,
+ NvAudioFxIoProperty_AddEvent,
+ sizeof(NvAudioFxMessage),
+ &message);
+
+ if (e != NvSuccess) {
+ snd_printk(KERN_ERR "TransportSetProperty failed\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ tegra_snd_cx->m_FxNotifier.Event |= NvAudioFxEventControlChange;
}
return 0;
@@ -617,6 +658,72 @@ static void tegra_audiofx_notifier_thread(void *arg)
}
break;
+ case NvAudioFxEventControlChange:{
+ NvAudioFxControlChangeMessage* ccm =
+ (NvAudioFxControlChangeMessage*)message;
+
+ if (message->hFx ==
+ (NvAudioFxHandle)audio_context->mi2s1)
+ {
+ if (ccm->Property == NvAudioFxIoProperty_OutputAvailable)
+ {
+ NvAudioFxIoDeviceControlChangeMessage* iccm =
+ (NvAudioFxIoDeviceControlChangeMessage*)message;
+ NvAudioFxIoDevice device_available = iccm->IoDevice;
+ NvAudioFxIoDevice device_select = device_available;
+
+ if (device_available &
+ NvAudioFxIoDevice_HeadphoneOut)
+ {
+ device_select = NvAudioFxIoDevice_HeadphoneOut;
+ }
+ else if (device_available &
+ NvAudioFxIoDevice_BuiltInSpeaker)
+ {
+ device_select = NvAudioFxIoDevice_BuiltInSpeaker;
+ }
+
+ audio_context->xrt_fxn.SetProperty(
+ audio_context->mi2s1,
+ NvAudioFxIoProperty_OutputSelect,
+ sizeof(NvAudioFxIoDevice),
+ &device_select);
+ }
+
+ }
+ else if (message->hFx ==
+ (NvAudioFxHandle)audio_context->mroute)
+ {
+ if (ccm->Property == NvAudioFxIoProperty_OutputAvailable)
+ {
+ NvAudioFxIoDeviceControlChangeMessage* iccm =
+ (NvAudioFxIoDeviceControlChangeMessage*)message;
+ NvAudioFxIoDevice device_available = iccm->IoDevice;
+ NvAudioFxIoDevice device_select = 0;
+
+ if ((device_available &
+ NvAudioFxIoDevice_Aux) &&
+ audio_context->spdif_plugin)
+ {
+ device_select = NvAudioFxIoDevice_Aux;
+ }
+ else if ((device_available &
+ NvAudioFxIoDevice_BuiltInSpeaker) &&
+ audio_context->spdif_plugin)
+ {
+ device_select = NvAudioFxIoDevice_BuiltInSpeaker;
+ }
+
+ audio_context->xrt_fxn.SetProperty(
+ audio_context->mroute,
+ NvAudioFxIoProperty_OutputSelect,
+ sizeof(NvAudioFxIoDevice),
+ &device_select);
+ }
+ }
+ }
+ break;
+
default:
snd_printk(KERN_ERR"Unhandled event\n");
break;
diff --git a/sound/soc/tegra/tegra_transport.h b/sound/soc/tegra/tegra_transport.h
index a93188fbb560..9d3ba726c41e 100644
--- a/sound/soc/tegra/tegra_transport.h
+++ b/sound/soc/tegra/tegra_transport.h
@@ -411,6 +411,7 @@ struct tegra_audio_data {
NvAudioFxMixBufferHandle mixer_buffer[2];
NvRmMemHandle mem_handle[2];
NvAudioFxObjectHandle mvolume;
+ NvAudioFxObjectHandle mi2s1;
NvAudioFxObjectHandle mroute;
int spdif_plugin;
int i2s1volume;