Skip to content

Commit 1e7541e

Browse files
committed
sound: soc: Import Wingtech wt88047 changes
* Squashed commits from: https://github.com/LineageOS/android_kernel_wingtech_msm8916/commits/cm-14.1 Change-Id: Ie5ca2bd2c3b5f4008ab708869ea067d7ecebb44e
1 parent 7738dc2 commit 1e7541e

File tree

6 files changed

+408
-0
lines changed

6 files changed

+408
-0
lines changed

sound/soc/codecs/msm8916-wcd-irq.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ struct wcd9xxx_spmi_map {
9494
};
9595

9696
struct wcd9xxx_spmi_map map;
97+
#ifdef CONFIG_MACH_WT88047
98+
static int late_resume;
99+
#endif
97100

98101
void wcd9xxx_spmi_enable_irq(int irq)
99102
{
@@ -329,6 +332,12 @@ int wcd9xxx_spmi_resume()
329332
map.pm_state,
330333
map.wlock_holders);
331334
map.pm_state = WCD9XXX_PM_SLEEPABLE;
335+
#ifdef CONFIG_MACH_WT88047
336+
if (late_resume) {
337+
msm8x16_wcd_restart_mbhc(map.codec);
338+
late_resume = 0;
339+
}
340+
#endif
332341
} else {
333342
pr_warn("%s: system is already awake, state %d wlock %d\n",
334343
__func__, map.pm_state,
@@ -363,6 +372,9 @@ bool wcd9xxx_spmi_lock_sleep()
363372
map.wlock_holders);
364373
pr_debug("%s: map.pm_state = %d\n", __func__, map.pm_state);
365374

375+
#ifdef CONFIG_MACH_WT88047
376+
late_resume = 0;
377+
#endif
366378
if (!wait_event_timeout(map.pm_wq,
367379
((wcd9xxx_spmi_pm_cmpxchg(
368380
WCD9XXX_PM_SLEEPABLE,
@@ -379,6 +391,9 @@ bool wcd9xxx_spmi_lock_sleep()
379391
WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, map.pm_state,
380392
map.wlock_holders);
381393
wcd9xxx_spmi_unlock_sleep();
394+
#ifdef CONFIG_MACH_WT88047
395+
late_resume = 1;
396+
#endif
382397
return false;
383398
}
384399
wake_up_all(&map.pm_wq);

sound/soc/codecs/msm8x16-wcd.c

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@
3232
#include <linux/timer.h>
3333
#include <linux/workqueue.h>
3434
#include <linux/sched.h>
35+
#include <linux/switch.h>
3536
#include <sound/q6afe-v2.h>
3637
#include <sound/pcm.h>
3738
#include <sound/pcm_params.h>
3839
#include <sound/soc.h>
3940
#include <sound/soc-dapm.h>
4041
#include <sound/tlv.h>
4142
#include <sound/q6core.h>
43+
#include <sound/jack.h>
4244
#include <soc/qcom/subsystem_notif.h>
4345
#include "msm8x16-wcd.h"
4446
#include "wcd-mbhc-v2.h"
@@ -132,6 +134,12 @@ static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
132134
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
133135
static struct snd_soc_dai_driver msm8x16_wcd_i2s_dai[];
134136

137+
#ifdef CONFIG_MACH_WT88047
138+
static struct switch_dev accdet_data;
139+
static int accdet_state;
140+
static struct delayed_work analog_switch_enable;
141+
#endif
142+
135143
#define MSM8X16_WCD_ACQUIRE_LOCK(x) \
136144
mutex_lock_nested(&x, SINGLE_DEPTH_NESTING);
137145

@@ -4110,11 +4118,64 @@ static int enable_ext_spk(struct snd_soc_dapm_widget *w, bool enable)
41104118
}
41114119
#endif
41124120

4121+
#ifdef CONFIG_MACH_WT88047
4122+
static void msm8x16_analog_switch_delayed_enable(struct work_struct *work)
4123+
{
4124+
int state = 0;
4125+
4126+
state = gpio_get_value(EXT_SPK_AMP_GPIO);
4127+
pr_debug("%s: Enable analog switch, external PA state: %d\n", __func__, state);
4128+
4129+
if (!state)
4130+
gpio_direction_output(EXT_SPK_AMP_HEADSET_GPIO, true);
4131+
}
4132+
4133+
void msm8x16_wcd_codec_set_headset_state(u32 state)
4134+
{
4135+
switch_set_state((struct switch_dev *)&accdet_data, state);
4136+
accdet_state = state;
4137+
}
4138+
4139+
int msm8x16_wcd_codec_get_headset_state(void)
4140+
{
4141+
pr_debug("%s accdet_state = %d\n", __func__, accdet_state);
4142+
return accdet_state;
4143+
}
4144+
4145+
static void enable_ldo17(int enable)
4146+
{
4147+
static struct regulator *reg_l17;
4148+
static int status;
4149+
int rc = 0;
4150+
4151+
if (!!status == !!enable)
4152+
return;
4153+
4154+
if (enable)
4155+
reg_l17 = regulator_get(0, "8916_l17");
4156+
if (reg_l17 != 0) {
4157+
if (enable) {
4158+
regulator_set_optimum_mode(reg_l17, 100*1000);
4159+
regulator_set_voltage(reg_l17, 2850000, 2850000);
4160+
rc = regulator_enable(reg_l17);
4161+
} else {
4162+
rc = regulator_disable(reg_l17);
4163+
regulator_put(reg_l17);
4164+
reg_l17 = 0;
4165+
}
4166+
status = enable;
4167+
}
4168+
}
4169+
#endif
4170+
41134171
static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
41144172
struct snd_kcontrol *kcontrol, int event)
41154173
{
41164174
struct snd_soc_codec *codec = w->codec;
41174175
struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
4176+
#ifdef CONFIG_MACH_WT88047
4177+
int state = 0;
4178+
#endif
41184179

41194180
dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
41204181

@@ -4131,6 +4192,10 @@ static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
41314192
break;
41324193

41334194
case SND_SOC_DAPM_POST_PMU:
4195+
#ifdef CONFIG_MACH_WT88047
4196+
enable_ldo17(1);
4197+
state = msm8x16_wcd_codec_get_headset_state();
4198+
#endif
41344199
usleep_range(7000, 7100);
41354200
if (w->shift == 5) {
41364201
snd_soc_update_bits(codec,
@@ -4146,6 +4211,13 @@ static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
41464211
enable_ext_spk(w, true);
41474212
#endif
41484213
}
4214+
#ifdef CONFIG_MACH_WT88047
4215+
usleep_range(10000, 10100);
4216+
if (!state)
4217+
gpio_direction_output(EXT_SPK_AMP_HEADSET_GPIO, false);
4218+
else
4219+
schedule_delayed_work(&analog_switch_enable, msecs_to_jiffies(500));
4220+
#endif
41494221
break;
41504222

41514223
case SND_SOC_DAPM_PRE_PMD:
@@ -4198,6 +4270,9 @@ static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
41984270
"%s: sleep 10 ms after %s PA disable.\n", __func__,
41994271
w->name);
42004272
usleep_range(10000, 10100);
4273+
#ifdef CONFIG_MACH_WT88047
4274+
enable_ldo17(0);
4275+
#endif
42014276
break;
42024277
}
42034278
return 0;
@@ -5574,6 +5649,18 @@ static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
55745649
wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &mbhc_cb, &intr_ids,
55755650
wcd_mbhc_registers, true);
55765651

5652+
#ifdef CONFIG_MACH_WT88047
5653+
accdet_data.name = "h2w";
5654+
accdet_data.index = 0;
5655+
accdet_data.state = 0;
5656+
5657+
ret = switch_dev_register(&accdet_data);
5658+
if (ret) {
5659+
dev_err(codec->dev, "%s: Failed to register h2w\n", __func__);
5660+
return -ENOMEM;
5661+
}
5662+
#endif
5663+
55775664
msm8x16_wcd_priv->mclk_enabled = false;
55785665
msm8x16_wcd_priv->clock_active = false;
55795666
msm8x16_wcd_priv->config_mode_active = false;
@@ -5596,6 +5683,9 @@ static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
55965683
registered_codec = NULL;
55975684
return -ENOMEM;
55985685
}
5686+
#ifdef CONFIG_MACH_WT88047
5687+
INIT_DELAYED_WORK(&analog_switch_enable, msm8x16_analog_switch_delayed_enable);
5688+
#endif
55995689
return 0;
56005690
}
56015691

@@ -6014,6 +6104,43 @@ static void msm8x16_wcd_device_exit(struct msm8x16_wcd *msm8x16)
60146104
kfree(msm8x16);
60156105
}
60166106

6107+
#ifdef CONFIG_MACH_WT88047
6108+
int msm8x16_wcd_restart_mbhc(struct snd_soc_codec *codec)
6109+
{
6110+
struct msm8x16_wcd_priv *msm8x16_wcd_priv =
6111+
snd_soc_codec_get_drvdata(codec);
6112+
int ret = 0;
6113+
bool detection_type;
6114+
u32 jack_mask = SND_JACK_HEADSET | SND_JACK_OC_HPHL |
6115+
SND_JACK_OC_HPHR | SND_JACK_LINEOUT |
6116+
SND_JACK_UNSUPPORTED;
6117+
/* Read mbhc reg if set for insert or remove and
6118+
set to corresponding detection type on restart */
6119+
detection_type = (snd_soc_read(codec,
6120+
MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1)) & 0x20;
6121+
if (!detection_type)
6122+
snd_soc_jack_report_no_dapm(
6123+
&msm8x16_wcd_priv->mbhc.headset_jack,
6124+
0, jack_mask);
6125+
wcd_mbhc_stop(&msm8x16_wcd_priv->mbhc);
6126+
wcd_mbhc_deinit(&msm8x16_wcd_priv->mbhc);
6127+
ret = wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &mbhc_cb, &intr_ids,
6128+
wcd_mbhc_registers, true);
6129+
6130+
if (ret)
6131+
dev_err(codec->dev, "%s: mbhc initialization failed\n",
6132+
__func__);
6133+
else
6134+
wcd_mbhc_start(&msm8x16_wcd_priv->mbhc,
6135+
msm8x16_wcd_priv->mbhc.mbhc_cfg);
6136+
/* Set the detection type appropriately */
6137+
snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1,
6138+
0x20, (!detection_type << 5));
6139+
return 0;
6140+
}
6141+
EXPORT_SYMBOL(msm8x16_wcd_restart_mbhc);
6142+
#endif
6143+
60176144
static int msm8x16_wcd_spmi_remove(struct spmi_device *spmi)
60186145
{
60196146
struct msm8x16_wcd *msm8x16 = dev_get_drvdata(&spmi->dev);

sound/soc/codecs/msm8x16-wcd.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@
3636
#define MSM8X16_TOMBAK_LPASS_DIGCODEC_CBCR 0x0181C0B0
3737
#define MSM8X16_TOMBAK_LPASS_DIGCODEC_AHB_CBCR 0x0181C0B4
3838

39+
#ifdef CONFIG_MACH_WT88047
40+
#define EXT_SPK_AMP_GPIO (902+117)
41+
#define EXT_SPK_AMP_HEADSET_GPIO (902+8)
42+
#endif
43+
3944
#define MSM8X16_CODEC_NAME "msm8x16_wcd_codec"
4045

4146
#define MSM8X16_WCD_IS_DIGITAL_REG(reg) \
@@ -317,6 +322,10 @@ extern int msm8x16_wcd_hs_detect(struct snd_soc_codec *codec,
317322

318323
extern void msm8x16_wcd_hs_detect_exit(struct snd_soc_codec *codec);
319324

325+
#ifdef CONFIG_MACH_WT88047
326+
extern int msm8x16_wcd_restart_mbhc(struct snd_soc_codec *codec);
327+
#endif
328+
320329
extern void msm8x16_wcd_spk_ext_pa_cb(
321330
int (*codec_spk_ext_pa)(struct snd_soc_codec *codec,
322331
int enable), struct snd_soc_codec *codec);

0 commit comments

Comments
 (0)