aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/wm8994_herring.c19
-rwxr-xr-xsound/soc/codecs/wm8994_samsung.c98
-rwxr-xr-xsound/soc/codecs/wm8994_samsung.h15
3 files changed, 88 insertions, 44 deletions
diff --git a/sound/soc/codecs/wm8994_herring.c b/sound/soc/codecs/wm8994_herring.c
index 27637a5..18df501 100644
--- a/sound/soc/codecs/wm8994_herring.c
+++ b/sound/soc/codecs/wm8994_herring.c
@@ -487,6 +487,20 @@ void audio_ctrl_mic_bias_gpio(struct wm8994_platform_data *pdata, int enable)
}
}
+static int wm8994_earsel_control(struct wm8994_platform_data *pdata, int en)
+{
+
+ if (!pdata) {
+ pr_err("failed to control wm8994 ear selection\n");
+ return -EINVAL;
+ }
+
+ gpio_set_value(pdata->ear_sel, en);
+
+ return 0;
+
+}
+
/* Audio Routing routines for the universal board..wm8994 codec*/
void wm8994_disable_playback_path(struct snd_soc_codec *codec,
enum audio_path path)
@@ -1108,6 +1122,8 @@ void wm8994_set_playback_headset(struct snd_soc_codec *codec)
DEBUG_LOG("");
+ wm8994_earsel_control(wm8994->pdata, 0);
+
/* Enable the Timeslot0 to DAC1L */
val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK);
@@ -1394,6 +1410,8 @@ void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec)
u8 nservo4low = 0;
u8 nservo4high = 0;
+ wm8994_earsel_control(wm8994->pdata, 0);
+
/* Enable the Timeslot0 to DAC1L */
val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK);
@@ -1813,6 +1831,7 @@ void wm8994_set_voicecall_headset(struct snd_soc_codec *codec)
DEBUG_LOG("");
audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
+ wm8994_earsel_control(wm8994->pdata, 1);
wm8994_set_voicecall_common_setting(codec);
diff --git a/sound/soc/codecs/wm8994_samsung.c b/sound/soc/codecs/wm8994_samsung.c
index 6bea596..b098165 100755
--- a/sound/soc/codecs/wm8994_samsung.c
+++ b/sound/soc/codecs/wm8994_samsung.c
@@ -294,6 +294,8 @@ static int wm8994_set_mic_path(struct snd_kcontrol *kcontrol,
DEBUG_LOG("");
+ wm8994->codec_state |= CAPTURE_ACTIVE;
+
if (ucontrol->value.integer.value[0] == 0)
wm8994->rec_path = MAIN;
else if (ucontrol->value.integer.value[0] == 1)
@@ -327,7 +329,7 @@ static int wm8994_set_path(struct snd_kcontrol *kcontrol,
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = codec->drvdata;
struct soc_enum *mc = (struct soc_enum *)kcontrol->private_value;
-
+ int val;
int path_num = ucontrol->value.integer.value[0];
if (strcmp(mc->texts[path_num], playback_path[path_num])) {
@@ -350,17 +352,17 @@ static int wm8994_set_path(struct snd_kcontrol *kcontrol,
case SPK_HP:
case BT:
DEBUG_LOG("routing to %s\n", mc->texts[path_num]);
- wm8994->ringtone_active = DEACTIVE;
+ wm8994->ringtone_active = RING_OFF;
break;
case RING_SPK:
case RING_HP:
DEBUG_LOG("routing to %s\n", mc->texts[path_num]);
- wm8994->ringtone_active = ACTIVE;
+ wm8994->ringtone_active = RING_ON;
path_num -= 4;
break;
case RING_SPK_HP:
DEBUG_LOG("routing to %s\n", mc->texts[path_num]);
- wm8994->ringtone_active = ACTIVE;
+ wm8994->ringtone_active = RING_ON;
path_num -= 3;
break;
default:
@@ -369,8 +371,17 @@ static int wm8994_set_path(struct snd_kcontrol *kcontrol,
break;
}
+ wm8994->codec_state |= PLAYBACK_ACTIVE;
+
+ if (wm8994->codec_state & CALL_ACTIVE) {
+ wm8994->codec_state &= ~(CALL_ACTIVE);
+
+ val = wm8994_read(codec, WM8994_CLOCKING_1);
+ val &= ~(WM8994_DSP_FS2CLK_ENA_MASK | WM8994_SYSCLK_SRC_MASK);
+ wm8994_write(codec, WM8994_CLOCKING_1, val);
+ }
+
wm8994->cur_path = path_num;
- wm8994->call_state = DISCONNECT;
wm8994->universal_playback_path[wm8994->cur_path] (codec);
return 0;
@@ -417,9 +428,10 @@ static int wm8994_set_voice_path(struct snd_kcontrol *kcontrol,
break;
}
- if (wm8994->cur_path != path_num || wm8994->call_state == DISCONNECT) {
+ if (wm8994->cur_path != path_num ||
+ !(wm8994->codec_state & CALL_ACTIVE)) {
+ wm8994->codec_state |= CALL_ACTIVE;
wm8994->cur_path = path_num;
- wm8994->call_state = CONNECT;
wm8994->universal_voicecall_path[wm8994->cur_path] (codec);
} else {
int val;
@@ -578,6 +590,11 @@ static int configure_clock(struct snd_soc_codec *codec)
DEBUG_LOG("");
+ if (wm8994->codec_state != DEACTIVE) {
+ DEBUG_LOG("Codec is already actvied. Skip clock setting.");
+ return 0;
+ }
+
reg = wm8994_read(codec, WM8994_AIF1_CLOCKING_1);
reg &= ~WM8994_AIF1CLK_ENA;
reg &= ~WM8994_AIF1CLK_SRC_MASK;
@@ -1077,9 +1094,10 @@ static int wm8994_startup(struct snd_pcm_substream *substream,
struct wm8994_priv *wm8994 = codec->drvdata;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- wm8994->play_en_dis = 1;
+ wm8994->stream_state |= PCM_STREAM_PLAYBACK;
else
- wm8994->rec_en_dis = 1;
+ wm8994->stream_state |= PCM_STREAM_CAPTURE;
+
if (wm8994->power_state == CODEC_OFF) {
wm8994->power_state = CODEC_ON;
@@ -1105,49 +1123,45 @@ static void wm8994_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = codec_dai->codec;
struct wm8994_priv *wm8994 = codec->drvdata;
- DEBUG_LOG("%s.., wm8994->call_state = %d, current path = %d",
- __func__, wm8994->call_state, wm8994->cur_path);
+ DEBUG_LOG("Stream_state = [0x%X], Codec State = [0x%X]",
+ wm8994->stream_state, wm8994->codec_state);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- wm8994->play_en_dis = 0;
- DEBUG_LOG("..inside..%s..for PLAYBACK_STREAM!!", __func__);
- if (wm8994->cur_path != OFF)
- wm8994->cur_path = OFF;
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ wm8994->stream_state &= ~(PCM_STREAM_CAPTURE);
+ wm8994->codec_state &= ~(CAPTURE_ACTIVE);
} else {
- wm8994->rec_en_dis = 0;
- DEBUG_LOG("..inside..%s..for CAPTURE_STREAM!!", __func__);
- if (wm8994->mic_state == MIC_NO_USE && \
- wm8994->rec_path != MIC_OFF)
- wm8994->rec_path = MIC_OFF;
+ wm8994->codec_state &= ~(PLAYBACK_ACTIVE);
+ wm8994->stream_state &= ~(PCM_STREAM_PLAYBACK);
}
- if (wm8994->call_state == DISCONNECT) {
- if (!wm8994->play_en_dis && !wm8994->rec_en_dis) {
- DEBUG_LOG("Turn off Codec!!");
- wm8994->pdata->set_mic_bias(false);
- wm8994->power_state = CODEC_OFF;
- wm8994_write(codec, WM8994_SOFTWARE_RESET, 0x0000);
+ if ((wm8994->codec_state == DEACTIVE) &&
+ (wm8994->stream_state == PCM_STREAM_DEACTIVE)) {
+ DEBUG_LOG("Turn off Codec!!");
+ wm8994->pdata->set_mic_bias(false);
+ wm8994->power_state = CODEC_OFF;
+ wm8994->cur_path = OFF;
+ wm8994->rec_path = MIC_OFF;
+ wm8994->ringtone_active = RING_OFF;
+ wm8994_write(codec, WM8994_SOFTWARE_RESET, 0x0000);
return;
- }
}
- DEBUG_LOG("Preserve codec state for call[%d].",
- wm8994->call_state);
+ DEBUG_LOG("Preserve codec state = [0x%X], Stream State = [0x%X]",
+ wm8994->codec_state, wm8994->stream_state);
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- wm8994->universal_mic_path[MIC_OFF] (codec);
+ wm8994_disable_rec_path(codec);
+ wm8994->codec_state &= ~(CAPTURE_ACTIVE);
} else {
- if (wm8994->call_state == CONNECT) {
+ if (wm8994->codec_state & CALL_ACTIVE) {
int val;
+
val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
val &= ~(WM8994_AIF1DAC1_MUTE_MASK);
val |= (WM8994_AIF1DAC1_MUTE);
wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
}
}
-
- DEBUG_LOG("exiting ...%s...", __func__);
-
}
static struct snd_soc_device *wm8994_socdev;
@@ -1217,13 +1231,13 @@ static int wm8994_init(struct wm8994_priv *wm8994_private,
wm8994->universal_voicecall_path = universal_wm8994_voicecall_paths;
wm8994->universal_mic_path = universal_wm8994_mic_paths;
wm8994->universal_clock_control = universal_clock_controls;
+ wm8994->stream_state = PCM_STREAM_DEACTIVE;
wm8994->cur_path = OFF;
wm8994->rec_path = MIC_OFF;
- wm8994->call_state = DISCONNECT;
wm8994->power_state = CODEC_OFF;
+ wm8994->recognition_active = REC_OFF;
+ wm8994->ringtone_active = RING_OFF;
wm8994->mic_state = MIC_NO_USE;
- wm8994->play_en_dis = 0;
- wm8994->rec_en_dis = 0;
wm8994->pdata = pdata;
wm8994->universal_clock_control(codec, CODEC_ON);
@@ -1456,9 +1470,11 @@ static int wm8994_suspend(struct platform_device *pdev, pm_message_t msg)
struct snd_soc_codec *codec = wm8994_codec;
struct wm8994_priv *wm8994 = codec->drvdata;
- DEBUG_LOG("%s..", __func__);
+ DEBUG_LOG("Codec State = [0x%X], Stream State = [0x%X]",
+ wm8994->codec_state, wm8994->stream_state);
- if (wm8994->call_state == DISCONNECT && wm8994->cur_path == OFF) {
+ if (wm8994->codec_state == DEACTIVE &&
+ wm8994->stream_state == PCM_STREAM_DEACTIVE) {
wm8994->power_state = OFF;
wm8994_write(codec, WM8994_SOFTWARE_RESET, 0x0000);
wm8994_ldo_control(wm8994->pdata, 0);
@@ -1477,7 +1493,7 @@ static int wm8994_resume(struct platform_device *pdev)
DEBUG_LOG_ERR("------WM8994 Revision = [%d]-------",
wm8994->hw_version);
- if (wm8994->call_state == DISCONNECT && wm8994->cur_path == OFF) {
+ if (wm8994->power_state == CODEC_OFF) {
/* Turn on sequence by recommend Wolfson.*/
wm8994_ldo_control(wm8994->pdata, 1);
wm8994->universal_clock_control(codec, CODEC_ON);
diff --git a/sound/soc/codecs/wm8994_samsung.h b/sound/soc/codecs/wm8994_samsung.h
index 37ca0b0..caf1f9c 100755
--- a/sound/soc/codecs/wm8994_samsung.h
+++ b/sound/soc/codecs/wm8994_samsung.h
@@ -34,6 +34,15 @@ extern struct snd_soc_dai wm8994_dai;
#define AUDIO_COMMON_DEBUG 0
+#define DEACTIVE 0x00
+#define PLAYBACK_ACTIVE 0x01
+#define CAPTURE_ACTIVE 0x02
+#define CALL_ACTIVE 0x04
+
+#define PCM_STREAM_DEACTIVE 0x00
+#define PCM_STREAM_PLAYBACK 0x01
+#define PCM_STREAM_CAPTURE 0x02
+
/* Codec Output Path BIT */
#define PLAYBACK_MODE 0x01
#define VOICECALL_MODE (0x01 << 1)
@@ -77,7 +86,7 @@ enum mic_path {MAIN, SUB, BT_REC, MIC_OFF};
enum call_state {DISCONNECT, CONNECT};
enum power_state {CODEC_OFF, CODEC_ON };
enum mic_state {MIC_NO_USE, MIC_USE};
-enum ringtone_state {DEACTIVE, ACTIVE};
+enum ringtone_state {RING_OFF, RING_ON};
enum recognition {REC_OFF, REC_ON};
typedef void (*select_route)(struct snd_soc_codec *);
@@ -99,6 +108,8 @@ struct wm8994_priv {
unsigned int fs;
unsigned int bclk;
unsigned int hw_version;
+ unsigned int codec_state;
+ unsigned int stream_state;
enum audio_path cur_path;
enum mic_path rec_path;
enum call_state call_state;
@@ -110,8 +121,6 @@ struct wm8994_priv {
select_route *universal_voicecall_path;
select_mic_route *universal_mic_path;
select_clock_control universal_clock_control;
- bool play_en_dis;
- bool rec_en_dis;
struct wm8994_platform_data *pdata;
struct clk *codec_clk;
};