summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra_generic_codec.c2
-rw-r--r--sound/soc/tegra/tegra_pcm.c68
-rw-r--r--sound/soc/tegra/tegra_soc.h10
-rw-r--r--sound/soc/tegra/tegra_soc_max98088.c132
4 files changed, 54 insertions, 158 deletions
diff --git a/sound/soc/tegra/tegra_generic_codec.c b/sound/soc/tegra/tegra_generic_codec.c
index 758f046516fd..142a1fba8dec 100644
--- a/sound/soc/tegra/tegra_generic_codec.c
+++ b/sound/soc/tegra/tegra_generic_codec.c
@@ -100,7 +100,7 @@ struct snd_soc_dai tegra_generic_codec_dai[] = {
TEGRA_CREATE_GENERIC_CODEC_DAI("tegra_generic_spdif_codec",
0, 2, 2, TEGRA_SAMPLE_RATES),
TEGRA_CREATE_GENERIC_CODEC_DAI("tegra_generic_BB_codec",
- 1, 1, 1, TEGRA_VOICE_SAMPLE_RATES),
+ 1, 1, 2, TEGRA_SAMPLE_RATES),
TEGRA_CREATE_GENERIC_CODEC_DAI("tegra_generic_BT_codec",
2, 1, 1, TEGRA_VOICE_SAMPLE_RATES),
TEGRA_CREATE_GENERIC_CODEC_DAI("tegra_generic_tdm_codec",
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 860267e6ebe6..66465aa22d56 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -67,7 +67,7 @@ static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd)
struct snd_dma_buffer *buf = &substream->dma_buffer;
struct tegra_dma_req *dma_req;
- if (runtime->dma_addr) {
+ if (runtime->dma_addr && prtd->dma_chan) {
prtd->size = frames_to_bytes(runtime, runtime->period_size);
if (prtd->dma_state != STATE_ABORT) {
@@ -161,14 +161,14 @@ static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
prtd->dma_state = STATE_ABORT;
- tegra_dma_cancel(prtd->dma_chan);
if (prtd->dma_chan) {
+ tegra_dma_cancel(prtd->dma_chan);
for (i = 0; i < DMA_REQ_QCOUNT; i++)
tegra_dma_dequeue_req(prtd->dma_chan,
&prtd->dma_req[i]);
- prtd->dma_head_idx = 0;
- prtd->dma_tail_idx = DMA_REQ_QCOUNT - 1;
+ prtd->dma_head_idx = 0;
+ prtd->dma_tail_idx = DMA_REQ_QCOUNT - 1;
}
#ifdef CONFIG_HAS_WAKELOCK
wake_unlock(&prtd->wake_lock);
@@ -186,10 +186,10 @@ static snd_pcm_uframes_t tegra_pcm_pointer(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct tegra_runtime_data *prtd = runtime->private_data;
- int size;
+ int size = prtd->period_index * runtime->period_size;
- size = (prtd->period_index * runtime->period_size) +
- bytes_to_frames(runtime,
+ if (prtd->dma_chan)
+ size += bytes_to_frames(runtime,
tegra_dma_get_transfer_count(
prtd->dma_chan,
&prtd->dma_req[prtd->dma_head_idx],
@@ -205,13 +205,15 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct tegra_runtime_data *prtd = 0;
struct tegra_i2s_info *info = cpu_dai->private_data;
- int i, ret=0;
+ int i, ret = 0;
int dma_mode;
+ int need_dma_ch = 0;
- pr_debug("%s: Device %d, Stream %s, substream_name %s\n", __func__, \
- substream->pcm->device, \
- (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)?"Playback": \
- "Capture", substream->name);
+ pr_debug("%s: cpu_dai %s, codec_dai %s, Device %d, Stream %s\n",
+ __func__, cpu_dai->name, rtd->dai->codec_dai->name,
+ substream->pcm->device,
+ (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ "Playback" : "Capture");
/* Ensure period size is multiple of minimum DMA step size */
ret = snd_pcm_hw_constraint_step(runtime, 0,
@@ -240,7 +242,7 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
prtd->dma_state = STATE_INVALID;
- if (strcmp(cpu_dai->name, "tegra-spdif") == 0)
+ if (!strcmp(cpu_dai->name, "tegra-spdif"))
{
for (i = 0; i < DMA_REQ_QCOUNT; i++) {
setup_spdif_dma_request(substream,
@@ -248,27 +250,30 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
dma_complete_callback,
prtd);
}
- }
- else
- {
+ need_dma_ch = 1;
+ } else if (strstr(cpu_dai->name, "tegra-i2s")) {
for (i = 0; i < DMA_REQ_QCOUNT; i++) {
setup_i2s_dma_request(substream,
&prtd->dma_req[i],
dma_complete_callback,
prtd);
}
+ need_dma_ch = 1;
}
- dma_mode = info->pdata->tdm_enable ? TEGRA_DMA_MODE_CONTINUOUS_DOUBLE :
- TEGRA_DMA_MODE_CONTINUOUS_SINGLE;
+ if (need_dma_ch) {
+ if (info && info->pdata->tdm_enable)
+ dma_mode = TEGRA_DMA_MODE_CONTINUOUS_DOUBLE;
+ else
+ dma_mode = TEGRA_DMA_MODE_CONTINUOUS_SINGLE;
- prtd->dma_chan = tegra_dma_allocate_channel(
- dma_mode, "pcm");
- if (prtd->dma_chan == NULL) {
- pr_err("%s: could not allocate DMA channel for PCM:\n",
+ prtd->dma_chan = tegra_dma_allocate_channel(dma_mode, "pcm");
+ if (prtd->dma_chan == NULL) {
+ pr_err("%s: could not allocate DMA channel for PCM:\n",
__func__);
- ret = -ENOMEM;
- goto fail;
+ ret = -ENOMEM;
+ goto fail;
+ }
}
#ifdef CONFIG_HAS_WAKELOCK
@@ -281,11 +286,11 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
#endif
/* Set HW params now that initialization is complete */
- if (!info->pdata->tdm_enable)
- snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
- else
+ if (info && info->pdata->tdm_enable)
snd_soc_set_runtime_hwparams(substream,
- &tegra_pcm_tdm_hardware);
+ &tegra_pcm_tdm_hardware);
+ else
+ snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
goto end;
@@ -296,6 +301,7 @@ fail:
if (prtd->dma_chan) {
tegra_dma_flush(prtd->dma_chan);
tegra_dma_free_channel(prtd->dma_chan);
+ prtd->dma_chan = NULL;
}
kfree(prtd);
}
@@ -312,6 +318,12 @@ static int tegra_pcm_close(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ pr_debug("%s: cpu_dai %s, codec_dai %s, Device %d, Stream %s\n",
+ __func__, cpu_dai->name, rtd->dai->codec_dai->name,
+ substream->pcm->device,
+ (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ "Playback" : "Capture");
+
if (!prtd) {
printk(KERN_ERR "tegra_pcm_close called with prtd == NULL\n");
return 0;
diff --git a/sound/soc/tegra/tegra_soc.h b/sound/soc/tegra/tegra_soc.h
index a2ff63f3d511..b9e72a66c1aa 100644
--- a/sound/soc/tegra/tegra_soc.h
+++ b/sound/soc/tegra/tegra_soc.h
@@ -78,13 +78,13 @@
#define TEGRA_SAMPLE_RATES (SNDRV_PCM_RATE_8000_96000)
#define TEGRA_VOICE_SAMPLE_RATES SNDRV_PCM_RATE_8000
-#define DMA_STEP_SIZE_MIN 8
-#define DMA_REQ_QCOUNT 2
+#define DMA_STEP_SIZE_MIN 8
+#define DMA_REQ_QCOUNT 2
#define TEGRA_AUDIO_OFF 0x0
#define TEGRA_HEADPHONE 0x1
#define TEGRA_LINEOUT 0x2
-#define TEGRA_SPK 0x4
+#define TEGRA_SPK 0x4
#define TEGRA_EAR_SPK 0x8
#define TEGRA_INT_MIC 0x10
#define TEGRA_EXT_MIC 0x20
@@ -92,6 +92,10 @@
#define TEGRA_HEADSET_OUT 0x80
#define TEGRA_HEADSET_IN 0x100
+#define TEGRA_BT_CODEC_ID 0
+#define TEGRA_BB_CODEC_ID 1
+#define TEGRA_SPDIF_CODEC_ID 2
+
struct tegra_dma_channel;
struct tegra_runtime_data {
diff --git a/sound/soc/tegra/tegra_soc_max98088.c b/sound/soc/tegra/tegra_soc_max98088.c
index e5886893e45c..b19f709b1dc9 100644
--- a/sound/soc/tegra/tegra_soc_max98088.c
+++ b/sound/soc/tegra/tegra_soc_max98088.c
@@ -133,61 +133,6 @@ static int tegra_hifi_hw_params(struct snd_pcm_substream *substream,
static int tegra_voice_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int dai_flag = 0, sys_clk;
- int err;
- enum dac_dap_data_format data_fmt;
- struct audio_dev_property dev_prop;
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (tegra_das_is_port_master(tegra_audio_codec_type_bluetooth))
-#else
- if(tegra_das_is_device_master(tegra_audio_codec_type_bluetooth))
-#endif
- dai_flag |= SND_SOC_DAIFMT_CBM_CFM;
- else
- dai_flag |= SND_SOC_DAIFMT_CBS_CFS;
-
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_bluetooth);
-#else
- tegra_das_get_device_property(tegra_audio_codec_type_bluetooth,&dev_prop);
- data_fmt = dev_prop.dac_dap_data_comm_format;
-#endif
- /* We are supporting DSP and I2s format for now */
- if (data_fmt & dac_dap_data_format_i2s)
- dai_flag |= SND_SOC_DAIFMT_I2S;
- else
- dai_flag |= SND_SOC_DAIFMT_DSP_A;
-
- err = snd_soc_dai_set_fmt(codec_dai, dai_flag);
- if (err < 0) {
- pr_err("codec_dai fmt not set\n");
- return err;
- }
-
- err = snd_soc_dai_set_fmt(cpu_dai, dai_flag);
- if (err < 0) {
- pr_err("cpu_dai fmt not set\n");
- return err;
- }
-
- sys_clk = tegra_das_get_mclk_rate();
- err = snd_soc_dai_set_sysclk(codec_dai, 0, sys_clk, SND_SOC_CLOCK_IN);
- if (err < 0) {
- pr_err("cpu_dai clock not set\n");
- return err;
- }
-
- err = snd_soc_dai_set_sysclk(cpu_dai, 0, sys_clk, SND_SOC_CLOCK_IN);
- if (err < 0) {
- pr_err("cpu_dai clock not set\n");
- return err;
- }
-
return 0;
}
@@ -296,16 +241,6 @@ void tegra_ext_control(struct snd_soc_codec *codec, int new_con)
else
snd_soc_dapm_disable_pin(codec, "Int Mic");
- if (new_con & TEGRA_EXT_MIC)
- snd_soc_dapm_enable_pin(codec, "Ext Mic");
- else
- snd_soc_dapm_disable_pin(codec, "Ext Mic");
-
- if (new_con & TEGRA_LINEIN)
- snd_soc_dapm_enable_pin(codec, "Linein");
- else
- snd_soc_dapm_disable_pin(codec, "Linein");
-
if (new_con & TEGRA_HEADSET_OUT)
snd_soc_dapm_enable_pin(codec, "Headset Out");
else
@@ -323,67 +258,13 @@ void tegra_ext_control(struct snd_soc_codec *codec, int new_con)
}
-static int tegra_dapm_event_int_spk(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *k, int event)
-{
- if (tegra_wired_jack_conf.en_spkr != -1) {
- if (tegra_wired_jack_conf.amp_reg) {
- if (SND_SOC_DAPM_EVENT_ON(event) &&
- !tegra_wired_jack_conf.amp_reg_enabled) {
- regulator_enable(tegra_wired_jack_conf.amp_reg);
- tegra_wired_jack_conf.amp_reg_enabled = 1;
- } else if (!SND_SOC_DAPM_EVENT_ON(event) &&
- tegra_wired_jack_conf.amp_reg_enabled) {
- regulator_disable(tegra_wired_jack_conf.amp_reg);
- tegra_wired_jack_conf.amp_reg_enabled = 0;
- }
- }
-
- gpio_set_value_cansleep(tegra_wired_jack_conf.en_spkr,
- SND_SOC_DAPM_EVENT_ON(event) ? 1 : 0);
- }
-
- return 0;
-}
-
-static int tegra_dapm_event_int_mic(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *k, int event)
-{
- if (tegra_wired_jack_conf.en_mic_int != -1)
- gpio_set_value_cansleep(tegra_wired_jack_conf.en_mic_int,
- SND_SOC_DAPM_EVENT_ON(event) ? 1 : 0);
-
- if (tegra_wired_jack_conf.en_mic_ext != -1)
- gpio_set_value_cansleep(tegra_wired_jack_conf.en_mic_ext,
- SND_SOC_DAPM_EVENT_ON(event) ? 0 : 1);
-
- return 0;
-}
-
-static int tegra_dapm_event_ext_mic(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *k, int event)
-{
- if (tegra_wired_jack_conf.en_mic_ext != -1)
- gpio_set_value_cansleep(tegra_wired_jack_conf.en_mic_ext,
- SND_SOC_DAPM_EVENT_ON(event) ? 1 : 0);
-
- if (tegra_wired_jack_conf.en_mic_int != -1)
- gpio_set_value_cansleep(tegra_wired_jack_conf.en_mic_int,
- SND_SOC_DAPM_EVENT_ON(event) ? 0 : 1);
-
- return 0;
-}
-
/*tegra machine dapm widgets */
static const struct snd_soc_dapm_widget tegra_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_HP("Headset Out", NULL),
SND_SOC_DAPM_MIC("Headset In", NULL),
- SND_SOC_DAPM_SPK("Lineout", NULL),
SND_SOC_DAPM_SPK("Int Spk", NULL),
- SND_SOC_DAPM_MIC("Ext Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
- SND_SOC_DAPM_LINE("Linein", NULL),
};
static const struct snd_soc_dapm_route audio_map[] = {
@@ -513,15 +394,14 @@ static struct snd_soc_dai_link tegra_soc_dai[] = {
&tegra_i2s_dai[1], &tegra_generic_codec_dai[2],
&tegra_voice_ops),
#else
- /*
- TEGRA_CREATE_SOC_DAI_LINK("Tegra-generic-0", "Tegra BB Voice",
- &tegra_i2s_dai[1], &tegra_generic_codec_dai[1],
- &tegra_voice_ops),
- TEGRA_CREATE_SOC_DAI_LINK("Tegra-generic-1", "Tegra BT Voice",
- &tegra_i2s_dai[2], &tegra_generic_codec_dai[2],
+ TEGRA_CREATE_SOC_DAI_LINK("Tegra-generic", "Tegra Generic Voice",
+ &tegra_i2s_dai[0], &max98088_dai[0],
&tegra_voice_ops),
- */
+ TEGRA_CREATE_SOC_DAI_LINK("Tegra-voice-call",
+ "Tegra Voice Call Max HiFi",
+ &tegra_generic_codec_dai[1],
+ &max98088_dai[0], &tegra_voice_ops),
#endif
TEGRA_CREATE_SOC_DAI_LINK("Tegra-spdif", "Tegra Spdif",