Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5cd1b231 authored by Fred Oh's avatar Fred Oh
Browse files

ASoC: apq8074: register for codec up event



If subsystem restart happens, ADSP loses all the config including AFE
configs. Also codec gets reset and reenumerates on slimbus after ADSP
SSR. So after codec is up ADSP AFE config needs to be done again. But this
AFE config needs to be done after codec reenumerates on slimbus, since
ADSP AFE config expects enumeration of codec on slimbus.

Change-Id: I2fcb0f258fbe8fd089b699fdfabe9bf0e940ccce
Signed-off-by: default avatarFred Oh <fred@codeaurora.org>
parent 76ccdc74
Loading
Loading
Loading
Loading
+121 −16
Original line number Diff line number Diff line
@@ -19,17 +19,22 @@
#include <linux/mfd/pm8xxx/pm8921.h>
#include <linux/qpnp/clkdiv.h>
#include <linux/regulator/consumer.h>
#include <linux/io.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
#include <sound/jack.h>
#include <sound/q6afe-v2.h>
#include <mach/socinfo.h>
#include <sound/pcm_params.h>
#include <asm/mach-types.h>
#include <mach/subsystem_notif.h>
#include <mach/socinfo.h>

#include "qdsp6v2/msm-pcm-routing-v2.h"
#include "qdsp6v2/q6core.h"
#include "../codecs/wcd9xxx-common.h"
#include "../codecs/wcd9320.h"
#include <linux/io.h>

#define DRV_NAME "apq8074-asoc-taiko"

@@ -81,6 +86,10 @@ static int apq8074_auxpcm_rate = 8000;

#define NUM_OF_AUXPCM_GPIOS 4

static void *adsp_state_notifier;

#define ADSP_STATE_READY_TIMEOUT_MS 3000

static inline int param_is_mask(int p)
{
	return ((p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
@@ -1238,6 +1247,101 @@ static bool apq8074_swap_gnd_mic(struct snd_soc_codec *codec)
	return true;
}

static int msm_afe_set_config(struct snd_soc_codec *codec)
{
	int rc;
	void *config_data;

	pr_debug("%s: enter\n", __func__);
	config_data = taiko_get_afe_config(codec, AFE_CDC_REGISTERS_CONFIG);
	rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
	if (rc) {
		pr_err("%s: Failed to set codec registers config %d\n",
		       __func__, rc);
		return rc;
	}

	config_data = taiko_get_afe_config(codec, AFE_SLIMBUS_SLAVE_CONFIG);
	rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
	if (rc) {
		pr_err("%s: Failed to set slimbus slave config %d\n", __func__,
		       rc);
		return rc;
	}

	return 0;
}

static void msm_afe_clear_config(void)
{
	afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
	afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
}

static int  msm8974_adsp_state_callback(struct notifier_block *nb,
		unsigned long value, void *priv)
{
	if (value == SUBSYS_BEFORE_SHUTDOWN) {
		pr_debug("%s: ADSP is about to shutdown. Clearing AFE config\n",
			 __func__);
		msm_afe_clear_config();
	} else if (value == SUBSYS_AFTER_POWERUP) {
		pr_debug("%s: ADSP is up\n", __func__);
	}

	return NOTIFY_OK;
}

static struct notifier_block adsp_state_notifier_block = {
	.notifier_call = msm8974_adsp_state_callback,
	.priority = -INT_MAX,
};

static int msm8974_taiko_codec_up(struct snd_soc_codec *codec)
{
	int err;
	unsigned long timeout;
	int adsp_ready = 0;

	timeout = jiffies +
		msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);

	do {
		if (!q6core_is_adsp_ready()) {
			pr_err("%s: ADSP Audio isn't ready\n", __func__);
		} else {
			pr_debug("%s: ADSP Audio is ready\n", __func__);
			adsp_ready = 1;
			break;
		}
	} while (time_after(timeout, jiffies));

	if (!adsp_ready) {
		pr_err("%s: timed out waiting for ADSP Audio\n", __func__);
		return -ETIMEDOUT;
	}

	err = msm_afe_set_config(codec);
	if (err)
		pr_err("%s: Failed to set AFE config. err %d\n",
				__func__, err);
	return err;
}

static int apq8074_taiko_event_cb(struct snd_soc_codec *codec,
		enum wcd9xxx_codec_event codec_event)
{
	switch (codec_event) {
	case WCD9XXX_CODEC_EVENT_CODEC_UP:
		return msm8974_taiko_codec_up(codec);
		break;
	default:
		pr_err("%s: UnSupported codec event %d\n",
				__func__, codec_event);
		return -EINVAL;
	}
}

static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
	int err;
@@ -1299,19 +1403,9 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
				    tx_ch, ARRAY_SIZE(rx_ch), rx_ch);


	config_data = taiko_get_afe_config(codec, AFE_CDC_REGISTERS_CONFIG);
	err = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
	err = msm_afe_set_config(codec);
	if (err) {
		pr_err("%s: Failed to set codec registers config %d\n",
		       __func__, err);
		goto out;
	}

	config_data = taiko_get_afe_config(codec, AFE_SLIMBUS_SLAVE_CONFIG);
	err = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
	if (err) {
		pr_err("%s: Failed to set slimbus slave config %d\n", __func__,
		       err);
		pr_err("%s: Failed to set AFE config %d\n", __func__, err);
		goto out;
	}

@@ -1348,12 +1442,23 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
		err = taiko_hs_detect(codec, &mbhc_cfg);
		if (err)
			goto out;
		else
			return err;
	} else {
		err = -ENOMEM;
		goto out;
	}
	adsp_state_notifier =
	    subsys_notif_register_notifier("adsp",
					   &adsp_state_notifier_block);
	if (!adsp_state_notifier) {
		pr_err("%s: Failed to register adsp state notifier\n",
		       __func__);
		err = -EFAULT;
		taiko_hs_detect_exit(codec);
		goto out;
	}

	taiko_event_register(apq8074_taiko_event_cb, rtd->codec);
	return 0;
out:
	clk_put(codec_clk);
	return err;