summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorVijay Mali <vmali@nvidia.com>2010-06-25 11:44:05 +0530
committerBharat Nihalani <bnihalani@nvidia.com>2010-06-25 04:17:01 -0700
commit5e252bf65a356d960e650f61ab9d446bac8f5872 (patch)
tree7d4752fbba45ecb9794e7bd52b64ecf11a1abcf5 /sound
parentcceed926fb99e3034443b43e14cfe66fa850acec (diff)
[tegra ALSA] Adding ALSA Control for audio routing
Added switch control in ALSA SoC to route audio to SPDIF. Verified using the amixer application. Renamed init_mixer function to tegra_audiofx_init. Moved this function to tegra transport source file. Fix for bug 678749 Change-Id: I892ebd98d276a60e50ef047d31ad7c0e7c8185cc Reviewed-on: http://git-master/r/3175 Tested-by: Vijay Mali <vmali@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra_codec_rpc.c108
-rw-r--r--sound/soc/tegra/tegra_pcm_rpc.c84
-rw-r--r--sound/soc/tegra/tegra_sndfx.h77
-rw-r--r--sound/soc/tegra/tegra_transport.c85
-rw-r--r--sound/soc/tegra/tegra_transport.h4
5 files changed, 225 insertions, 133 deletions
diff --git a/sound/soc/tegra/tegra_codec_rpc.c b/sound/soc/tegra/tegra_codec_rpc.c
index 3e22d670f2d8..6868f76afeda 100644
--- a/sound/soc/tegra/tegra_codec_rpc.c
+++ b/sound/soc/tegra/tegra_codec_rpc.c
@@ -43,15 +43,17 @@ static int tegra_master_volume_info(struct snd_kcontrol *kcontrol,
static int tegra_master_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
+ int rval = NvAudioFxVolumeDefault;
+ int lval = NvAudioFxVolumeDefault;
+
if (tegra_snd_cx) {
- ucontrol->value.integer.value[0] = tegra_snd_cx->i2s1volume;
- ucontrol->value.integer.value[1] = tegra_snd_cx->i2s1volume;
- }
- else {
- ucontrol->value.integer.value[0] = NvAudioFxVolumeDefault;
- ucontrol->value.integer.value[1] = NvAudioFxVolumeDefault;
+ if (!tegra_audiofx_init(tegra_snd_cx)) {
+ rval = tegra_snd_cx->i2s1volume;
+ lval = tegra_snd_cx->i2s1volume;
+ }
}
-
+ ucontrol->value.integer.value[0] = rval;
+ ucontrol->value.integer.value[1] = lval;
return 0;
}
@@ -70,23 +72,24 @@ static int tegra_master_volume_put(struct snd_kcontrol *kcontrol,
vd.Mute = 1;
}
- if (tegra_snd_cx && tegra_snd_cx->mixer_handle) {
- if(tegra_snd_cx->i2s1volume != val) {
- tegra_snd_cx->i2s1volume = val;
- tegra_snd_cx->xrt_fxn.SetProperty(
- tegra_snd_cx->mvolume,
- NvAudioFxVolumeProperty_Volume,
- sizeof(NvAudioFxVolumeDescriptor),
- &vd);
- change = 1;
- snd_printk(KERN_ERR "Put Volume Change = 1\n");
+ 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,
+ NvAudioFxVolumeProperty_Volume,
+ sizeof(NvAudioFxVolumeDescriptor),
+ &vd);
+ change = 1;
+ }
}
}
return change;
}
-static struct snd_kcontrol_new tegra_codec_control =
+static struct snd_kcontrol_new tegra_codec_ctrl_volume =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -97,6 +100,64 @@ static struct snd_kcontrol_new tegra_codec_control =
.put = tegra_master_volume_put
};
+static int tegra_master_route_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int tegra_master_route_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = 0;
+ if (tegra_snd_cx) {
+ if (!tegra_audiofx_init(tegra_snd_cx)) {
+ ucontrol->value.integer.value[0] =
+ tegra_snd_cx->spdif_plugin;
+ }
+ }
+ return 0;
+}
+
+static int tegra_master_route_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int change = 0, val;
+ NvAudioFxIoDevice ioDevice = 0;
+ val = ucontrol->value.integer.value[0] & 0xffff;
+ if (val) {
+ ioDevice = NvAudioFxIoDevice_BuiltInSpeaker;
+ }
+
+ if (tegra_snd_cx) {
+ if (!tegra_audiofx_init(tegra_snd_cx)) {
+ tegra_snd_cx->spdif_plugin = val;
+ tegra_snd_cx->xrt_fxn.SetProperty(
+ tegra_snd_cx->mroute,
+ NvAudioFxIoProperty_OutputSelect,
+ sizeof(NvAudioFxIoDevice),
+ &ioDevice);
+ change = 1;
+ }
+ }
+ return change;
+}
+
+static struct snd_kcontrol_new tegra_codec_ctrl_route =
+{
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "SPDIF Playback Switch",
+ .private_value = 0xffff,
+ .info = tegra_master_route_info,
+ .get = tegra_master_route_get,
+ .put = tegra_master_route_put
+};
+
static int tegra_generic_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -208,9 +269,16 @@ static int codec_soc_probe(struct platform_device *pdev)
printk(KERN_ERR "codec: failed to register card\n");
goto card_err;
}
-
+ /* Add volume control */
+ ret = snd_ctl_add(codec->card,
+ snd_ctl_new1(&tegra_codec_ctrl_volume, codec));
+ if (ret < 0) {
+ printk(KERN_ERR "codec: failed to add control\n");
+ goto card_err;
+ }
+ /* Add route control */
return snd_ctl_add(codec->card,
- snd_ctl_new1(&tegra_codec_control, codec));
+ snd_ctl_new1(&tegra_codec_ctrl_route, codec));
card_err:
snd_soc_free_pcms(socdev);
diff --git a/sound/soc/tegra/tegra_pcm_rpc.c b/sound/soc/tegra/tegra_pcm_rpc.c
index c64d5a2f8d62..b1f78ab6e208 100644
--- a/sound/soc/tegra/tegra_pcm_rpc.c
+++ b/sound/soc/tegra/tegra_pcm_rpc.c
@@ -388,82 +388,6 @@ tegra_pcm_pointer(struct snd_pcm_substream *substream)
return (size);
}
-static int init_mixer(struct snd_pcm_substream *substream)
-{
- NvError e = NvSuccess;
- int ret = 0;
-
- if (!tegra_snd_cx->mixer_handle) {
- mutex_lock(&tegra_snd_cx->lock);
- e = tegra_transport_init(&tegra_snd_cx->xrt_fxn);
- mutex_unlock(&tegra_snd_cx->lock);
-
- if (e != NvSuccess) {
- snd_printk(KERN_ERR "tegra_transport_init failed \n");
- return -EFAULT;
- }
-
- tegra_snd_cx->mixer_handle =
- tegra_snd_cx->xrt_fxn.MixerOpen();
-
- if (!tegra_snd_cx->mixer_handle) {
- ret = -EFAULT;
- goto fail;
- }
-
- e = tegra_audiofx_createfx(tegra_snd_cx);
- if (e != NvSuccess) {
- snd_printk(KERN_ERR "tegra_audiofx_createfx failed \n");
- ret = -EFAULT;
- goto fail;
- }
-
- tegra_snd_cx->mixer_buffer[0] =
- tegra_snd_cx->xrt_fxn.MixerMapBuffer(
- tegra_snd_cx->mixer_handle,
- NvRmMemGetId(tegra_snd_cx->mem_handle[0]),
- 0,
- tegra_snd_cx->mapped_buf_size);
-
- if (!tegra_snd_cx->mixer_buffer[0]) {
- snd_printk(KERN_ERR"TransportMixerMapBuffer failed!\n");
- }
-
- tegra_snd_cx->mixer_buffer[1] =
- tegra_snd_cx->xrt_fxn.MixerMapBuffer(
- tegra_snd_cx->mixer_handle,
- NvRmMemGetId(tegra_snd_cx->mem_handle[1]),
- 0,
- tegra_snd_cx->mapped_buf_size);
-
- if (!tegra_snd_cx->mixer_buffer[1]) {
- snd_printk(KERN_ERR"TransportMixerMapBuffer failed!\n");
- }
-
- tegra_snd_cx->mvolume = tegra_snd_cx->xrt_fxn.MixerCreateObject(
- tegra_snd_cx->mixer_handle,
- NvAudioFxI2s1VolumeId);
- tegra_snd_cx->i2s1volume = NvAudioFxVolumeDefault;
- }
-
- return 0;
-fail:
- snd_printk(KERN_ERR "init mixer failed \n");
- if (tegra_snd_cx->mixer_handle) {
- tegra_audiofx_destroyfx(tegra_snd_cx);
-
- if (tegra_snd_cx->mixer_handle) {
- tegra_snd_cx->xrt_fxn.MixerClose(
- tegra_snd_cx->mixer_handle);
- }
- }
- mutex_lock(&tegra_snd_cx->lock);
- tegra_transport_deinit();
- mutex_unlock(&tegra_snd_cx->lock);
-
- return ret;
-}
-
static int pcm_common_close(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -543,9 +467,11 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
prtd->state = NVALSA_INVALID_STATE;
prtd->stream = substream->stream;
- ret = init_mixer(substream);
- if (ret)
- goto fail;
+ if (!tegra_snd_cx->mixer_handle) {
+ ret = tegra_audiofx_init(tegra_snd_cx);
+ if (ret)
+ goto fail;
+ }
init_completion(&prtd->thread_comp);
init_waitqueue_head(&prtd->buf_wait);
diff --git a/sound/soc/tegra/tegra_sndfx.h b/sound/soc/tegra/tegra_sndfx.h
index 2cc38e557290..00f58436e75e 100644
--- a/sound/soc/tegra/tegra_sndfx.h
+++ b/sound/soc/tegra/tegra_sndfx.h
@@ -40,6 +40,7 @@ extern "C"
#endif
#include "nvrm_module.h"
+#include "nvrm_memmgr.h"
#include "nvrm_transport.h"
#include "nvrm_init.h"
@@ -154,16 +155,17 @@ typedef NvS32 NvAudioFxProperty;
#define NvAudioFxPinProperty_Format (0x2000)
#define NvAudioFxDrcProperty_Drc (0x3000)
#define NvAudioFxEqProperty_Eq (0x4000)
-#define NvAudioFxI2sProperty_AllocChannel (0x4a01)
-#define NvAudioFxI2sProperty_InputAvailable (0x4a02)
-#define NvAudioFxI2sProperty_InputDisable (0x4a04)
-#define NvAudioFxI2sProperty_InputEnable (0x4a03)
-#define NvAudioFxI2sProperty_InputSelect (0x4a05)
-#define NvAudioFxI2sProperty_OutputAvailable (0x4a06)
-#define NvAudioFxI2sProperty_OutputDisable (0x4a08)
-#define NvAudioFxI2sProperty_OutputEnable (0x4a07)
-#define NvAudioFxI2sProperty_OutputSelect (0x4a09)
-#define NvAudioFxI2sProperty_IoDeviceVolume (0x4a0a)
+#define NvAudioFxIoProperty_AllocChannel (0x4a01)
+#define NvAudioFxIoProperty_InputAvailable (0x4a02)
+#define NvAudioFxIoProperty_InputEnable (0x4a03)
+#define NvAudioFxIoProperty_InputDisable (0x4a04)
+#define NvAudioFxIoProperty_InputSelect (0x4a05)
+#define NvAudioFxIoProperty_OutputAvailable (0x4a06)
+#define NvAudioFxIoProperty_OutputEnable (0x4a07)
+#define NvAudioFxIoProperty_OutputDisable (0x4a08)
+#define NvAudioFxIoProperty_OutputSelect (0x4a09)
+#define NvAudioFxIoProperty_IoDeviceVolume (0x4a0a)
+#define NvAudioFxIoProperty_GenericOdmConfig (0x4a0b)
#define NvAudioFxIoProperty_AddEvent (0x5000)
#define NvAudioFxIoProperty_Position (0x5010)
#define NvAudioFxIoProperty_RemoveEvent (0x5020)
@@ -281,29 +283,6 @@ typedef struct NvAudioFxSpreaderDescriptorRec
NvU32 SpeakerWidth;
} NvAudioFxSpreaderDescriptor;
-// I2S inputs.
-
-typedef NvS32 NvAudioFxI2sInputSelect;
-
-// Default is configurable based on the device.
-#define NvAudioFxI2sInputSelect_Default (0x0)
-#define NvAudioFxI2sInputSelect_Bluetooth (0x1)
-#define NvAudioFxI2sInputSelect_BuiltinMic (0x2)
-#define NvAudioFxI2sInputSelect_LineIn (0x3)
-#define NvAudioFxI2sInputSelect_Mic (0x4)
-#define NvAudioFxI2sInputSelect_Phone (0x5)
-#define NvAudioFxI2sInputSelect_Radio (0x6)
-
-// Description of the NvAudioFxI2sProperty_AllocChannel property.
-
-typedef struct NvAudioFxI2sChannelDescriptorRec
-{
- NvAudioFxPin Pin;
- NvU32 Id;
-} NvAudioFxI2sChannelDescriptor;
-
-// Parameteric EQ Filter types.
-
typedef enum
{
NvAudioFxIirFilter_Undefined,
@@ -418,6 +397,31 @@ typedef struct NvAudioFxNotifierConnectionDescriptorRec
NvU8 PortName[16];
} NvAudioFxNotifierConnectionDescriptor;
+// Description of the NvAudioFxI2sProperty_AllocChannel property.
+
+typedef struct NvAudioFxIoChannelDescriptorRec
+{
+ NvAudioFxPin Pin;
+ NvU32 Id;
+} NvAudioFxIoChannelDescriptor;
+
+// Buffer has a header of type NvAudioFxOdmConfigHeader followed by the data buffer.
+
+typedef struct NvAudioFxOdmConfigHeaderRec
+{
+ NvU32 Size;
+ NvError Result;
+} NvAudioFxOdmConfigHeader;
+
+// Description of the NvAudioFxIoProperty_GenericOdmConfig property.
+
+typedef struct NvAudioFxOdmConfigDescriptorRec
+{
+ NvU32 hRmMemId;
+ NvU32 Size;
+ void* hSemaphore;
+} NvAudioFxOdmConfigDescriptor;
+
// Description of the NvAudioFxProperty_AddEvent and
// NvAudioFxProperty_RemoveEvent properties.
@@ -429,6 +433,7 @@ typedef NvS32 NvAudioFxEvent;
#define NvAudioFxEventPowerStateChange (0x10)
#define NvAudioFxEventIoChange (0x20)
#define NvAudioFxEventControlChange (0x40)
+#define NvAudioFxEventControlQuery (0x80)
#define NvAudioFxEventAll (0xffffffff)
typedef struct NvAudioFxMessageRec
@@ -462,6 +467,12 @@ typedef struct NvAudioFxIoDeviceVolumeControlChangeMessageRec
NvAudioFxIoDeviceVolumeDescriptor idv;
} NvAudioFxIoDeviceVolumeControlChangeMessage;
+typedef struct NvAudioFxOdmConfigChangeMessageRec
+{
+ NvAudioFxControlChangeMessage m;
+ NvAudioFxOdmConfigDescriptor OdmConfig;
+} NvAudioFxOdmConfigChangeMessage;
+
typedef struct NvAudioFxModeControlChangeMessageRec
{
NvAudioFxControlChangeMessage m;
diff --git a/sound/soc/tegra/tegra_transport.c b/sound/soc/tegra/tegra_transport.c
index 161ed15f1e0b..157c6d7c3476 100644
--- a/sound/soc/tegra/tegra_transport.c
+++ b/sound/soc/tegra/tegra_transport.c
@@ -477,6 +477,91 @@ EXIT:
return;
}
+int tegra_audiofx_init(struct tegra_audio_data* tegra_snd_cx)
+{
+ NvError e = NvSuccess;
+ int ret = 0;
+
+ if (!tegra_snd_cx->mixer_handle) {
+ mutex_lock(&tegra_snd_cx->lock);
+ e = tegra_transport_init(&tegra_snd_cx->xrt_fxn);
+ mutex_unlock(&tegra_snd_cx->lock);
+
+ if (e != NvSuccess) {
+ snd_printk(KERN_ERR "tegra_transport_init failed \n");
+ return -EFAULT;
+ }
+
+ tegra_snd_cx->mixer_handle =
+ tegra_snd_cx->xrt_fxn.MixerOpen();
+
+ if (!tegra_snd_cx->mixer_handle) {
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ e = tegra_audiofx_createfx(tegra_snd_cx);
+ if (e != NvSuccess) {
+ snd_printk(KERN_ERR "tegra_audiofx_createfx failed \n");
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ tegra_snd_cx->mixer_buffer[0] =
+ tegra_snd_cx->xrt_fxn.MixerMapBuffer(
+ tegra_snd_cx->mixer_handle,
+ NvRmMemGetId(tegra_snd_cx->mem_handle[0]),
+ 0,
+ tegra_snd_cx->mapped_buf_size);
+
+ if (!tegra_snd_cx->mixer_buffer[0]) {
+ snd_printk(KERN_ERR"TransportMixerMapBuffer failed!\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ tegra_snd_cx->mixer_buffer[1] =
+ tegra_snd_cx->xrt_fxn.MixerMapBuffer(
+ tegra_snd_cx->mixer_handle,
+ NvRmMemGetId(tegra_snd_cx->mem_handle[1]),
+ 0,
+ tegra_snd_cx->mapped_buf_size);
+
+ if (!tegra_snd_cx->mixer_buffer[1]) {
+ snd_printk(KERN_ERR"TransportMixerMapBuffer failed!\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ tegra_snd_cx->mvolume = tegra_snd_cx->xrt_fxn.MixerCreateObject(
+ tegra_snd_cx->mixer_handle,
+ NvAudioFxI2s1VolumeId);
+ tegra_snd_cx->i2s1volume = NvAudioFxVolumeDefault;
+
+ tegra_snd_cx->mroute = tegra_snd_cx->xrt_fxn.MixerCreateObject(
+ tegra_snd_cx->mixer_handle,
+ NvAudioFxSpdifId);
+ tegra_snd_cx->spdif_plugin = 0;
+ }
+
+ return 0;
+fail:
+ snd_printk(KERN_ERR "tegra_audiofx_init failed \n");
+ if (tegra_snd_cx->mixer_handle) {
+ tegra_audiofx_destroyfx(tegra_snd_cx);
+
+ if (tegra_snd_cx->mixer_handle) {
+ tegra_snd_cx->xrt_fxn.MixerClose(
+ tegra_snd_cx->mixer_handle);
+ }
+ }
+ mutex_lock(&tegra_snd_cx->lock);
+ tegra_transport_deinit();
+ mutex_unlock(&tegra_snd_cx->lock);
+
+ return ret;
+}
+
static void tegra_audiofx_notifier_thread(void *arg)
{
struct tegra_audio_data *audio_context = (struct tegra_audio_data *)arg;
diff --git a/sound/soc/tegra/tegra_transport.h b/sound/soc/tegra/tegra_transport.h
index 40e4c9eaa11d..a93188fbb560 100644
--- a/sound/soc/tegra/tegra_transport.h
+++ b/sound/soc/tegra/tegra_transport.h
@@ -411,11 +411,13 @@ struct tegra_audio_data {
NvAudioFxMixBufferHandle mixer_buffer[2];
NvRmMemHandle mem_handle[2];
NvAudioFxObjectHandle mvolume;
+ NvAudioFxObjectHandle mroute;
+ int spdif_plugin;
int i2s1volume;
struct mutex lock;
};
-
+int tegra_audiofx_init(struct tegra_audio_data* tegra_snd_cx);
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,