|
@@ -91,8 +91,6 @@ static int wm8994_retune_mobile_base[] = {
|
|
|
WM8994_AIF2_EQ_GAINS_1,
|
|
|
};
|
|
|
|
|
|
-static void wm8958_default_micdet(u16 status, void *data);
|
|
|
-
|
|
|
static const struct wm8958_micd_rate micdet_rates[] = {
|
|
|
{ 32768, true, 1, 4 },
|
|
|
{ 32768, false, 1, 1 },
|
|
@@ -110,15 +108,12 @@ static const struct wm8958_micd_rate jackdet_rates[] = {
|
|
|
static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
|
|
|
{
|
|
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
+ struct wm8994 *control = wm8994->wm8994;
|
|
|
int best, i, sysclk, val;
|
|
|
bool idle;
|
|
|
const struct wm8958_micd_rate *rates;
|
|
|
int num_rates;
|
|
|
|
|
|
- if (!(wm8994->pdata && wm8994->pdata->micd_rates) &&
|
|
|
- wm8994->jack_cb != wm8958_default_micdet)
|
|
|
- return;
|
|
|
-
|
|
|
idle = !wm8994->jack_mic;
|
|
|
|
|
|
sysclk = snd_soc_read(codec, WM8994_CLOCKING_1);
|
|
@@ -127,9 +122,9 @@ static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
|
|
|
else
|
|
|
sysclk = wm8994->aifclk[0];
|
|
|
|
|
|
- if (wm8994->pdata && wm8994->pdata->micd_rates) {
|
|
|
- rates = wm8994->pdata->micd_rates;
|
|
|
- num_rates = wm8994->pdata->num_micd_rates;
|
|
|
+ if (control->pdata.micd_rates) {
|
|
|
+ rates = control->pdata.micd_rates;
|
|
|
+ num_rates = control->pdata.num_micd_rates;
|
|
|
} else if (wm8994->jackdet) {
|
|
|
rates = jackdet_rates;
|
|
|
num_rates = ARRAY_SIZE(jackdet_rates);
|
|
@@ -326,7 +321,8 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol,
|
|
|
static void wm8994_set_drc(struct snd_soc_codec *codec, int drc)
|
|
|
{
|
|
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
- struct wm8994_pdata *pdata = wm8994->pdata;
|
|
|
+ struct wm8994 *control = wm8994->wm8994;
|
|
|
+ struct wm8994_pdata *pdata = &control->pdata;
|
|
|
int base = wm8994_drc_base[drc];
|
|
|
int cfg = wm8994->drc_cfg[drc];
|
|
|
int save, i;
|
|
@@ -362,7 +358,8 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
|
|
|
{
|
|
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
|
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
- struct wm8994_pdata *pdata = wm8994->pdata;
|
|
|
+ struct wm8994 *control = wm8994->wm8994;
|
|
|
+ struct wm8994_pdata *pdata = &control->pdata;
|
|
|
int drc = wm8994_get_drc(kcontrol->id.name);
|
|
|
int value = ucontrol->value.integer.value[0];
|
|
|
|
|
@@ -394,7 +391,8 @@ static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol,
|
|
|
static void wm8994_set_retune_mobile(struct snd_soc_codec *codec, int block)
|
|
|
{
|
|
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
- struct wm8994_pdata *pdata = wm8994->pdata;
|
|
|
+ struct wm8994 *control = wm8994->wm8994;
|
|
|
+ struct wm8994_pdata *pdata = &control->pdata;
|
|
|
int base = wm8994_retune_mobile_base[block];
|
|
|
int iface, best, best_val, save, i, cfg;
|
|
|
|
|
@@ -465,7 +463,8 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
|
|
|
{
|
|
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
|
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
- struct wm8994_pdata *pdata = wm8994->pdata;
|
|
|
+ struct wm8994 *control = wm8994->wm8994;
|
|
|
+ struct wm8994_pdata *pdata = &control->pdata;
|
|
|
int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
|
|
|
int value = ucontrol->value.integer.value[0];
|
|
|
|
|
@@ -736,7 +735,7 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
|
|
|
{
|
|
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
|
|
|
- if (!wm8994->jackdet || !wm8994->jack_cb)
|
|
|
+ if (!wm8994->jackdet || !wm8994->micdet[0].jack)
|
|
|
return;
|
|
|
|
|
|
if (wm8994->active_refcount)
|
|
@@ -862,7 +861,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
|
|
|
WM8994_BIAS_SRC |
|
|
|
WM8994_STARTUP_BIAS_ENA |
|
|
|
WM8994_VMID_BUF_ENA |
|
|
|
- (0x3 << WM8994_VMID_RAMP_SHIFT));
|
|
|
+ (0x2 << WM8994_VMID_RAMP_SHIFT));
|
|
|
|
|
|
/* Main bias enable, VMID=2x40k */
|
|
|
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
|
|
@@ -870,7 +869,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
|
|
|
WM8994_VMID_SEL_MASK,
|
|
|
WM8994_BIAS_ENA | 0x2);
|
|
|
|
|
|
- msleep(50);
|
|
|
+ msleep(300);
|
|
|
|
|
|
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
|
|
|
WM8994_VMID_RAMP_MASK |
|
|
@@ -939,16 +938,10 @@ static void vmid_dereference(struct snd_soc_codec *codec)
|
|
|
WM8994_BIAS_SRC |
|
|
|
WM8994_VMID_DISCH);
|
|
|
|
|
|
- switch (wm8994->vmid_mode) {
|
|
|
- case WM8994_VMID_FORCE:
|
|
|
- msleep(350);
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
|
|
|
+ WM8994_VMID_SEL_MASK, 0);
|
|
|
|
|
|
- snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
|
|
|
- WM8994_VROI, WM8994_VROI);
|
|
|
+ msleep(400);
|
|
|
|
|
|
/* Active discharge */
|
|
|
snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
|
|
@@ -957,17 +950,12 @@ static void vmid_dereference(struct snd_soc_codec *codec)
|
|
|
WM8994_LINEOUT1_DISCH |
|
|
|
WM8994_LINEOUT2_DISCH);
|
|
|
|
|
|
- msleep(150);
|
|
|
-
|
|
|
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
|
|
|
WM8994_LINEOUT1N_ENA |
|
|
|
WM8994_LINEOUT1P_ENA |
|
|
|
WM8994_LINEOUT2N_ENA |
|
|
|
WM8994_LINEOUT2P_ENA, 0);
|
|
|
|
|
|
- snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
|
|
|
- WM8994_VROI, 0);
|
|
|
-
|
|
|
/* Switch off startup biases */
|
|
|
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
|
|
|
WM8994_BIAS_SRC |
|
|
@@ -976,10 +964,7 @@ static void vmid_dereference(struct snd_soc_codec *codec)
|
|
|
WM8994_VMID_RAMP_MASK, 0);
|
|
|
|
|
|
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
|
|
|
- WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
|
|
|
-
|
|
|
- snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
|
|
|
- WM8994_VMID_RAMP_MASK, 0);
|
|
|
+ WM8994_VMID_SEL_MASK, 0);
|
|
|
}
|
|
|
|
|
|
pm_runtime_put(codec->dev);
|
|
@@ -2277,6 +2262,18 @@ out:
|
|
|
|
|
|
configure_clock(codec);
|
|
|
|
|
|
+ /*
|
|
|
+ * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers
|
|
|
+ * for detection.
|
|
|
+ */
|
|
|
+ if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
|
|
|
+ dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
|
|
|
+ snd_soc_update_bits(codec, WM8994_AIF1_RATE,
|
|
|
+ WM8994_AIF1CLK_RATE_MASK, 0x1);
|
|
|
+ snd_soc_update_bits(codec, WM8994_AIF2_RATE,
|
|
|
+ WM8994_AIF2CLK_RATE_MASK, 0x1);
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -2365,6 +2362,18 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
|
|
|
|
|
|
configure_clock(codec);
|
|
|
|
|
|
+ /*
|
|
|
+ * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers
|
|
|
+ * for detection.
|
|
|
+ */
|
|
|
+ if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
|
|
|
+ dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
|
|
|
+ snd_soc_update_bits(codec, WM8994_AIF1_RATE,
|
|
|
+ WM8994_AIF1CLK_RATE_MASK, 0x1);
|
|
|
+ snd_soc_update_bits(codec, WM8994_AIF2_RATE,
|
|
|
+ WM8994_AIF2CLK_RATE_MASK, 0x1);
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -3082,7 +3091,8 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec)
|
|
|
static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
|
|
|
{
|
|
|
struct snd_soc_codec *codec = wm8994->hubs.codec;
|
|
|
- struct wm8994_pdata *pdata = wm8994->pdata;
|
|
|
+ struct wm8994 *control = wm8994->wm8994;
|
|
|
+ struct wm8994_pdata *pdata = &control->pdata;
|
|
|
struct snd_kcontrol_new controls[] = {
|
|
|
SOC_ENUM_EXT("AIF1.1 EQ Mode",
|
|
|
wm8994->retune_mobile_enum,
|
|
@@ -3149,7 +3159,8 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
|
|
|
static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
|
|
|
{
|
|
|
struct snd_soc_codec *codec = wm8994->hubs.codec;
|
|
|
- struct wm8994_pdata *pdata = wm8994->pdata;
|
|
|
+ struct wm8994 *control = wm8994->wm8994;
|
|
|
+ struct wm8994_pdata *pdata = &control->pdata;
|
|
|
int ret, i;
|
|
|
|
|
|
if (!pdata)
|
|
@@ -3389,38 +3400,80 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
-/* Default microphone detection handler for WM8958 - the user can
|
|
|
- * override this if they wish.
|
|
|
- */
|
|
|
-static void wm8958_default_micdet(u16 status, void *data)
|
|
|
+static void wm1811_micd_stop(struct snd_soc_codec *codec)
|
|
|
+{
|
|
|
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
+
|
|
|
+ if (!wm8994->jackdet)
|
|
|
+ return;
|
|
|
+
|
|
|
+ mutex_lock(&wm8994->accdet_lock);
|
|
|
+
|
|
|
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0);
|
|
|
+
|
|
|
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK);
|
|
|
+
|
|
|
+ mutex_unlock(&wm8994->accdet_lock);
|
|
|
+
|
|
|
+ if (wm8994->wm8994->pdata.jd_ext_cap)
|
|
|
+ snd_soc_dapm_disable_pin(&codec->dapm,
|
|
|
+ "MICBIAS2");
|
|
|
+}
|
|
|
+
|
|
|
+static void wm8958_button_det(struct snd_soc_codec *codec, u16 status)
|
|
|
{
|
|
|
- struct snd_soc_codec *codec = data;
|
|
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
int report;
|
|
|
|
|
|
- dev_dbg(codec->dev, "MICDET %x\n", status);
|
|
|
+ report = 0;
|
|
|
+ if (status & 0x4)
|
|
|
+ report |= SND_JACK_BTN_0;
|
|
|
+
|
|
|
+ if (status & 0x8)
|
|
|
+ report |= SND_JACK_BTN_1;
|
|
|
+
|
|
|
+ if (status & 0x10)
|
|
|
+ report |= SND_JACK_BTN_2;
|
|
|
+
|
|
|
+ if (status & 0x20)
|
|
|
+ report |= SND_JACK_BTN_3;
|
|
|
+
|
|
|
+ if (status & 0x40)
|
|
|
+ report |= SND_JACK_BTN_4;
|
|
|
+
|
|
|
+ if (status & 0x80)
|
|
|
+ report |= SND_JACK_BTN_5;
|
|
|
+
|
|
|
+ snd_soc_jack_report(wm8994->micdet[0].jack, report,
|
|
|
+ wm8994->btn_mask);
|
|
|
+}
|
|
|
+
|
|
|
+static void wm8958_mic_id(void *data, u16 status)
|
|
|
+{
|
|
|
+ struct snd_soc_codec *codec = data;
|
|
|
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
|
|
|
/* Either nothing present or just starting detection */
|
|
|
if (!(status & WM8958_MICD_STS)) {
|
|
|
- if (!wm8994->jackdet) {
|
|
|
- /* If nothing present then clear our statuses */
|
|
|
- dev_dbg(codec->dev, "Detected open circuit\n");
|
|
|
- wm8994->jack_mic = false;
|
|
|
- wm8994->mic_detecting = true;
|
|
|
+ /* If nothing present then clear our statuses */
|
|
|
+ dev_dbg(codec->dev, "Detected open circuit\n");
|
|
|
+ wm8994->jack_mic = false;
|
|
|
+ wm8994->mic_detecting = true;
|
|
|
|
|
|
- wm8958_micd_set_rate(codec);
|
|
|
+ wm1811_micd_stop(codec);
|
|
|
|
|
|
- snd_soc_jack_report(wm8994->micdet[0].jack, 0,
|
|
|
- wm8994->btn_mask |
|
|
|
- SND_JACK_HEADSET);
|
|
|
- }
|
|
|
+ wm8958_micd_set_rate(codec);
|
|
|
+
|
|
|
+ snd_soc_jack_report(wm8994->micdet[0].jack, 0,
|
|
|
+ wm8994->btn_mask |
|
|
|
+ SND_JACK_HEADSET);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
/* If the measurement is showing a high impedence we've got a
|
|
|
* microphone.
|
|
|
*/
|
|
|
- if (wm8994->mic_detecting && (status & 0x600)) {
|
|
|
+ if (status & 0x600) {
|
|
|
dev_dbg(codec->dev, "Detected microphone\n");
|
|
|
|
|
|
wm8994->mic_detecting = false;
|
|
@@ -3433,64 +3486,67 @@ static void wm8958_default_micdet(u16 status, void *data)
|
|
|
}
|
|
|
|
|
|
|
|
|
- if (wm8994->mic_detecting && status & 0xfc) {
|
|
|
+ if (status & 0xfc) {
|
|
|
dev_dbg(codec->dev, "Detected headphone\n");
|
|
|
wm8994->mic_detecting = false;
|
|
|
|
|
|
wm8958_micd_set_rate(codec);
|
|
|
|
|
|
/* If we have jackdet that will detect removal */
|
|
|
- if (wm8994->jackdet) {
|
|
|
- mutex_lock(&wm8994->accdet_lock);
|
|
|
-
|
|
|
- snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
|
|
|
- WM8958_MICD_ENA, 0);
|
|
|
-
|
|
|
- wm1811_jackdet_set_mode(codec,
|
|
|
- WM1811_JACKDET_MODE_JACK);
|
|
|
-
|
|
|
- mutex_unlock(&wm8994->accdet_lock);
|
|
|
-
|
|
|
- if (wm8994->pdata->jd_ext_cap)
|
|
|
- snd_soc_dapm_disable_pin(&codec->dapm,
|
|
|
- "MICBIAS2");
|
|
|
- }
|
|
|
+ wm1811_micd_stop(codec);
|
|
|
|
|
|
snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE,
|
|
|
SND_JACK_HEADSET);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- /* Report short circuit as a button */
|
|
|
- if (wm8994->jack_mic) {
|
|
|
- report = 0;
|
|
|
- if (status & 0x4)
|
|
|
- report |= SND_JACK_BTN_0;
|
|
|
+/* Deferred mic detection to allow for extra settling time */
|
|
|
+static void wm1811_mic_work(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct wm8994_priv *wm8994 = container_of(work, struct wm8994_priv,
|
|
|
+ mic_work.work);
|
|
|
+ struct wm8994 *control = wm8994->wm8994;
|
|
|
+ struct snd_soc_codec *codec = wm8994->hubs.codec;
|
|
|
|
|
|
- if (status & 0x8)
|
|
|
- report |= SND_JACK_BTN_1;
|
|
|
+ pm_runtime_get_sync(codec->dev);
|
|
|
|
|
|
- if (status & 0x10)
|
|
|
- report |= SND_JACK_BTN_2;
|
|
|
+ /* If required for an external cap force MICBIAS on */
|
|
|
+ if (control->pdata.jd_ext_cap) {
|
|
|
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
|
|
|
+ "MICBIAS2");
|
|
|
+ snd_soc_dapm_sync(&codec->dapm);
|
|
|
+ }
|
|
|
|
|
|
- if (status & 0x20)
|
|
|
- report |= SND_JACK_BTN_3;
|
|
|
+ mutex_lock(&wm8994->accdet_lock);
|
|
|
|
|
|
- if (status & 0x40)
|
|
|
- report |= SND_JACK_BTN_4;
|
|
|
+ dev_dbg(codec->dev, "Starting mic detection\n");
|
|
|
|
|
|
- if (status & 0x80)
|
|
|
- report |= SND_JACK_BTN_5;
|
|
|
+ /* Use a user-supplied callback if we have one */
|
|
|
+ if (wm8994->micd_cb) {
|
|
|
+ wm8994->micd_cb(wm8994->micd_cb_data);
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * Start off measument of microphone impedence to find out
|
|
|
+ * what's actually there.
|
|
|
+ */
|
|
|
+ wm8994->mic_detecting = true;
|
|
|
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
|
|
|
|
|
|
- snd_soc_jack_report(wm8994->micdet[0].jack, report,
|
|
|
- wm8994->btn_mask);
|
|
|
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
|
|
|
+ WM8958_MICD_ENA, WM8958_MICD_ENA);
|
|
|
}
|
|
|
+
|
|
|
+ mutex_unlock(&wm8994->accdet_lock);
|
|
|
+
|
|
|
+ pm_runtime_put(codec->dev);
|
|
|
}
|
|
|
|
|
|
static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
|
|
|
{
|
|
|
struct wm8994_priv *wm8994 = data;
|
|
|
+ struct wm8994 *control = wm8994->wm8994;
|
|
|
struct snd_soc_codec *codec = wm8994->hubs.codec;
|
|
|
- int reg;
|
|
|
+ int reg, delay;
|
|
|
bool present;
|
|
|
|
|
|
pm_runtime_get_sync(codec->dev);
|
|
@@ -3521,18 +3577,14 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
|
|
|
snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
|
|
|
WM1811_JACKDET_DB, 0);
|
|
|
|
|
|
- /*
|
|
|
- * Start off measument of microphone impedence to find
|
|
|
- * out what's actually there.
|
|
|
- */
|
|
|
- wm8994->mic_detecting = true;
|
|
|
- wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
|
|
|
-
|
|
|
- snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
|
|
|
- WM8958_MICD_ENA, WM8958_MICD_ENA);
|
|
|
+ delay = control->pdata.micdet_delay;
|
|
|
+ schedule_delayed_work(&wm8994->mic_work,
|
|
|
+ msecs_to_jiffies(delay));
|
|
|
} else {
|
|
|
dev_dbg(codec->dev, "Jack not detected\n");
|
|
|
|
|
|
+ cancel_delayed_work_sync(&wm8994->mic_work);
|
|
|
+
|
|
|
snd_soc_update_bits(codec, WM8958_MICBIAS2,
|
|
|
WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
|
|
|
|
|
@@ -3549,14 +3601,9 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
|
|
|
|
|
|
mutex_unlock(&wm8994->accdet_lock);
|
|
|
|
|
|
- /* If required for an external cap force MICBIAS on */
|
|
|
- if (wm8994->pdata->jd_ext_cap) {
|
|
|
- if (present)
|
|
|
- snd_soc_dapm_force_enable_pin(&codec->dapm,
|
|
|
- "MICBIAS2");
|
|
|
- else
|
|
|
- snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
|
|
|
- }
|
|
|
+ /* Turn off MICBIAS if it was on for an external cap */
|
|
|
+ if (control->pdata.jd_ext_cap && !present)
|
|
|
+ snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
|
|
|
|
|
|
if (present)
|
|
|
snd_soc_jack_report(wm8994->micdet[0].jack,
|
|
@@ -3599,7 +3646,8 @@ static void wm1811_jackdet_bootstrap(struct work_struct *work)
|
|
|
* detection algorithm.
|
|
|
*/
|
|
|
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
|
|
|
- wm8958_micdet_cb cb, void *cb_data)
|
|
|
+ wm1811_micdet_cb det_cb, void *det_cb_data,
|
|
|
+ wm1811_mic_id_cb id_cb, void *id_cb_data)
|
|
|
{
|
|
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
struct wm8994 *control = wm8994->wm8994;
|
|
@@ -3614,27 +3662,32 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
|
|
|
}
|
|
|
|
|
|
if (jack) {
|
|
|
- if (!cb) {
|
|
|
- dev_dbg(codec->dev, "Using default micdet callback\n");
|
|
|
- cb = wm8958_default_micdet;
|
|
|
- cb_data = codec;
|
|
|
- }
|
|
|
-
|
|
|
snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS");
|
|
|
snd_soc_dapm_sync(&codec->dapm);
|
|
|
|
|
|
wm8994->micdet[0].jack = jack;
|
|
|
- wm8994->jack_cb = cb;
|
|
|
- wm8994->jack_cb_data = cb_data;
|
|
|
|
|
|
- wm8994->mic_detecting = true;
|
|
|
- wm8994->jack_mic = false;
|
|
|
+ if (det_cb) {
|
|
|
+ wm8994->micd_cb = det_cb;
|
|
|
+ wm8994->micd_cb_data = det_cb_data;
|
|
|
+ } else {
|
|
|
+ wm8994->mic_detecting = true;
|
|
|
+ wm8994->jack_mic = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (id_cb) {
|
|
|
+ wm8994->mic_id_cb = id_cb;
|
|
|
+ wm8994->mic_id_cb_data = id_cb_data;
|
|
|
+ } else {
|
|
|
+ wm8994->mic_id_cb = wm8958_mic_id;
|
|
|
+ wm8994->mic_id_cb_data = codec;
|
|
|
+ }
|
|
|
|
|
|
wm8958_micd_set_rate(codec);
|
|
|
|
|
|
/* Detect microphones and short circuits by default */
|
|
|
- if (wm8994->pdata->micd_lvl_sel)
|
|
|
- micd_lvl_sel = wm8994->pdata->micd_lvl_sel;
|
|
|
+ if (control->pdata.micd_lvl_sel)
|
|
|
+ micd_lvl_sel = control->pdata.micd_lvl_sel;
|
|
|
else
|
|
|
micd_lvl_sel = 0x41;
|
|
|
|
|
@@ -3728,10 +3781,22 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
|
|
|
trace_snd_soc_jack_irq(dev_name(codec->dev));
|
|
|
#endif
|
|
|
|
|
|
- if (wm8994->jack_cb)
|
|
|
- wm8994->jack_cb(reg, wm8994->jack_cb_data);
|
|
|
+ /* Avoid a transient report when the accessory is being removed */
|
|
|
+ if (wm8994->jackdet) {
|
|
|
+ reg = snd_soc_read(codec, WM1811_JACKDET_CTRL);
|
|
|
+ if (reg < 0) {
|
|
|
+ dev_err(codec->dev, "Failed to read jack status: %d\n",
|
|
|
+ reg);
|
|
|
+ } else if (!(reg & WM1811_JACKDET_LVL)) {
|
|
|
+ dev_dbg(codec->dev, "Ignoring removed jack\n");
|
|
|
+ return IRQ_HANDLED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (wm8994->mic_detecting)
|
|
|
+ wm8994->mic_id_cb(wm8994->mic_id_cb_data, reg);
|
|
|
else
|
|
|
- dev_warn(codec->dev, "Accessory detection with no callback\n");
|
|
|
+ wm8958_button_det(codec, reg);
|
|
|
|
|
|
out:
|
|
|
pm_runtime_put(codec->dev);
|
|
@@ -3779,15 +3844,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
|
|
|
snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
|
|
|
|
|
|
mutex_init(&wm8994->accdet_lock);
|
|
|
- INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
|
|
|
INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
|
|
|
wm1811_jackdet_bootstrap);
|
|
|
|
|
|
+ switch (control->type) {
|
|
|
+ case WM8994:
|
|
|
+ INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
|
|
|
+ break;
|
|
|
+ case WM1811:
|
|
|
+ INIT_DELAYED_WORK(&wm8994->mic_work, wm1811_mic_work);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
|
|
|
init_completion(&wm8994->fll_locked[i]);
|
|
|
|
|
|
- if (wm8994->pdata && wm8994->pdata->micdet_irq)
|
|
|
- wm8994->micdet_irq = wm8994->pdata->micdet_irq;
|
|
|
+ wm8994->micdet_irq = control->pdata.micdet_irq;
|
|
|
|
|
|
pm_runtime_enable(codec->dev);
|
|
|
pm_runtime_idle(codec->dev);
|
|
@@ -3800,8 +3874,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
|
|
|
switch (control->type) {
|
|
|
case WM8994:
|
|
|
/* Single ended line outputs should have VMID on. */
|
|
|
- if (!wm8994->pdata->lineout1_diff ||
|
|
|
- !wm8994->pdata->lineout2_diff)
|
|
|
+ if (!control->pdata.lineout1_diff ||
|
|
|
+ !control->pdata.lineout2_diff)
|
|
|
codec->dapm.idle_bias_off = 0;
|
|
|
|
|
|
switch (wm8994->revision) {
|
|
@@ -3839,20 +3913,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
|
|
|
wm8994->hubs.no_cache_dac_hp_direct = true;
|
|
|
wm8994->fll_byp = true;
|
|
|
|
|
|
- switch (control->cust_id) {
|
|
|
- case 0:
|
|
|
- case 2:
|
|
|
- wm8994->hubs.dcs_codes_l = -9;
|
|
|
- wm8994->hubs.dcs_codes_r = -7;
|
|
|
- break;
|
|
|
- case 1:
|
|
|
- case 3:
|
|
|
- wm8994->hubs.dcs_codes_l = -8;
|
|
|
- wm8994->hubs.dcs_codes_r = -7;
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
+ wm8994->hubs.dcs_codes_l = -9;
|
|
|
+ wm8994->hubs.dcs_codes_r = -7;
|
|
|
|
|
|
snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1,
|
|
|
WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN);
|
|
@@ -4236,7 +4298,6 @@ static int __devinit wm8994_probe(struct platform_device *pdev)
|
|
|
platform_set_drvdata(pdev, wm8994);
|
|
|
|
|
|
wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
|
|
|
- wm8994->pdata = dev_get_platdata(pdev->dev.parent);
|
|
|
|
|
|
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
|
|
|
wm8994_dai, ARRAY_SIZE(wm8994_dai));
|
|
@@ -4266,7 +4327,7 @@ static int wm8994_resume(struct device *dev)
|
|
|
{
|
|
|
struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
|
|
|
|
|
|
- if (wm8994->jackdet && wm8994->jack_cb)
|
|
|
+ if (wm8994->jackdet && wm8994->jackdet_mode)
|
|
|
regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
|
|
|
WM1811_JACKDET_MODE_MASK,
|
|
|
WM1811_JACKDET_MODE_AUDIO);
|