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

Commit 2c011d6a authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: wcd_cpe_core: Split CPE initialization"

parents 4f0c2f63 52f3d1bd
Loading
Loading
Loading
Loading
+47 −23
Original line number Diff line number Diff line
@@ -2678,6 +2678,21 @@ static int tomtom_codec_enable_adc(struct snd_soc_dapm_widget *w,
	return 0;
}

static int tomtom_codec_ext_clk_en(struct snd_soc_codec *codec,
		int enable, bool dapm)
{
	struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);

	if (!tomtom->codec_ext_clk_en_cb) {
		dev_err(codec->dev,
			"%s: Invalid ext_clk_callback\n",
			__func__);
		return -EINVAL;
	}

	return tomtom->codec_ext_clk_en_cb(codec, enable, dapm);
}

/* tomtom_codec_internal_rco_ctrl( )
 * Make sure that BG_CLK_LOCK is not acquired. Exit if acquired to avoid
 * potential deadlock as ext_clk_en_cb() also tries to acquire the same
@@ -2687,11 +2702,21 @@ static int tomtom_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
					  bool enable)
{
	struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
	int ret = 0;

	if (mutex_is_locked(&tomtom->resmgr.codec_bg_clk_lock)) {
		dev_err(codec->dev, "%s: BG_CLK already acquired\n",
			__func__);
		return -EINVAL;
		ret = -EINVAL;
		goto done;
	}

	if (!tomtom->codec_ext_clk_en_cb) {
		dev_err(codec->dev,
			"%s: Invalid ext_clk_callback\n",
			__func__);
		ret = -EINVAL;
		goto done;
	}

	if (enable) {
@@ -2702,14 +2727,14 @@ static int tomtom_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
						     WCD9XXX_CLK_RCO);
			WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
		} else {
			tomtom->codec_ext_clk_en_cb(codec, true, false);
			tomtom_codec_ext_clk_en(codec, true, false);
			WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
			tomtom->resmgr.ext_clk_users =
					tomtom->codec_get_ext_clk_cnt();
			wcd9xxx_resmgr_get_clk_block(&tomtom->resmgr,
						     WCD9XXX_CLK_RCO);
			WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
			tomtom->codec_ext_clk_en_cb(codec, false, false);
			tomtom_codec_ext_clk_en(codec, false, false);
		}

	} else {
@@ -2719,7 +2744,8 @@ static int tomtom_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
		WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
	}

	return 0;
done:
	return ret;
}

static int tomtom_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
@@ -7832,38 +7858,29 @@ static int tomtom_codec_fll_enable(struct snd_soc_codec *codec,
	return 0;
}

static void tomtom_codec_cpe_setup_callbacks(
		struct wcd_cpe_cdc_cb *cpe_cb,
		int (*cdc_ext_clk)(struct snd_soc_codec *codec,
		int enable, bool dapm))
{
	cpe_cb->cdc_clk_en = tomtom_codec_internal_rco_ctrl;
	cpe_cb->cpe_clk_en = tomtom_codec_fll_enable;
	cpe_cb->slimtx_lab_en = tomtom_codec_enable_slimtx_mad;
	if (cdc_ext_clk == NULL)
		pr_err("%s: MCLK could not be set", __func__);
	cpe_cb->cdc_ext_clk = cdc_ext_clk;
}
static const struct wcd_cpe_cdc_cb cpe_cb = {
	.cdc_clk_en = tomtom_codec_internal_rco_ctrl,
	.cpe_clk_en = tomtom_codec_fll_enable,
	.slimtx_lab_en = tomtom_codec_enable_slimtx_mad,
	.cdc_ext_clk = tomtom_codec_ext_clk_en,
};

int tomtom_enable_cpe(struct snd_soc_codec *codec)
static int tomtom_cpe_initialize(struct snd_soc_codec *codec)
{
	struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
	struct wcd_cpe_params cpe_params;
	struct wcd_cpe_cdc_cb cpe_cdc_cb;

	tomtom_codec_cpe_setup_callbacks(&cpe_cdc_cb,
					 tomtom->codec_ext_clk_en_cb);
	memset(&cpe_params, 0,
	       sizeof(struct wcd_cpe_params));
	cpe_params.codec = codec;
	cpe_params.get_cpe_core = tomtom_codec_get_cpe_core;
	cpe_params.cdc_cb = &cpe_cdc_cb;
	cpe_params.cdc_cb = &cpe_cb;
	cpe_params.dbg_mode = cpe_debug_mode;
	cpe_params.cdc_major_ver = TOMTOM_CPE_MAJOR_VER;
	cpe_params.cdc_minor_ver = TOMTOM_CPE_MINOR_VER;
	cpe_params.cdc_id = TOMTOM_CPE_CDC_ID;

	tomtom->cpe_core = wcd_cpe_init_and_boot("cpe", codec,
	tomtom->cpe_core = wcd_cpe_init("cpe", codec,
						 &cpe_params);
	if (IS_ERR_OR_NULL(tomtom->cpe_core)) {
		dev_err(codec->dev,
@@ -7874,7 +7891,6 @@ int tomtom_enable_cpe(struct snd_soc_codec *codec)

	return 0;
}
EXPORT_SYMBOL(tomtom_enable_cpe);

int tomtom_enable_qfuse_sensing(struct snd_soc_codec *codec)
{
@@ -8052,6 +8068,14 @@ static int tomtom_codec_probe(struct snd_soc_codec *codec)
	snd_soc_dapm_sync(dapm);

	codec->ignore_pmdown_time = 1;
	ret = tomtom_cpe_initialize(codec);
	if (ret) {
		dev_info(codec->dev,
			"%s: cpe initialization failed, ret = %d\n",
			__func__, ret);
		/* Do not fail probe if CPE failed */
		ret = 0;
	}
	return ret;

err_pdata:
+0 −1
Original line number Diff line number Diff line
@@ -125,6 +125,5 @@ extern void tomtom_register_ext_clk_cb(
				int enable, bool dapm),
	int (*get_ext_clk_cnt) (void),
	struct snd_soc_codec *codec);
extern int tomtom_enable_cpe(struct snd_soc_codec *codec);
extern int tomtom_enable_qfuse_sensing(struct snd_soc_codec *codec);
#endif
+164 −39
Original line number Diff line number Diff line
@@ -98,6 +98,32 @@ static void wcd_cpe_svc_event_cb(const struct cpe_svc_notification *param);
static int wcd_cpe_setup_irqs(struct wcd_cpe_core *core);
static void wcd_cpe_cleanup_irqs(struct wcd_cpe_core *core);

struct cpe_load_priv {
	void *cdc_handle;
	int cpe_load;
	struct kobject *cpe_load_kobj;
	struct attribute_group *attr_group;
};

static ssize_t wcd_cpe_load_store(struct kobject *kobj,
	struct kobj_attribute *attr,
	const char *buf,
	size_t count);

static struct kobj_attribute cpe_load_attr =
	__ATTR(load, 0600, NULL, wcd_cpe_load_store);

static struct attribute *attrs[] = {
	&cpe_load_attr.attr,
	NULL,
};

static struct attribute_group attr_grp = {
	.attrs = attrs,
};

static struct cpe_load_priv cpe_priv;

/* wcd_cpe_lsm_session_active: check if any session is active
 * return true if any session is active.
 */
@@ -245,21 +271,21 @@ static int wcd_cpe_enable_cpe_clks(struct wcd_cpe_core *core, bool enable)
{
	int ret = 0;

	if (!core || !core->cpe_cdc_cb.cdc_clk_en ||
	    !core->cpe_cdc_cb.cpe_clk_en) {
	if (!core || !core->cpe_cdc_cb ||
	    !core->cpe_cdc_cb->cpe_clk_en) {
		pr_err("%s: invalid handle\n",
			__func__);
		return -EINVAL;
	}

	ret = core->cpe_cdc_cb.cdc_clk_en(core->codec, enable);
	ret = core->cpe_cdc_cb->cdc_clk_en(core->codec, enable);
	if (ret) {
		dev_err(core->dev, "%s: Failed to enable RCO\n",
			__func__);
		return ret;
	}

	ret = core->cpe_cdc_cb.cpe_clk_en(core->codec, enable);
	ret = core->cpe_cdc_cb->cpe_clk_en(core->codec, enable);
	if (ret) {
		dev_err(core->dev,
			"%s: cpe_clk_en() failed, err = %d\n",
@@ -730,6 +756,17 @@ int wcd_cpe_ssr_event(void *core_handle,
		return -EINVAL;
	}

	/*
	 * If CPE is not even enabled, the SSR event for
	 * CPE needs to be ignored
	 */
	if (core->ssr_type == WCD_CPE_INITIALIZED) {
		dev_info(core->dev,
			"%s: CPE initialized but not enabled, skip CPE ssr\n",
			 __func__);
		return 0;
	}

	dev_dbg(core->dev,
		"%s: Schedule ssr work, event = %d\n",
		__func__, core->ssr_type);
@@ -1052,16 +1089,99 @@ fail_engine_irq:
}

/*
 * wcd_cpe_init_and_boot: Initialize and bootup CPE hardware block
 * wcd_cpe_enable: setup the cpe interrupts and schedule
 *	the work to download image and bootup the CPE.
 * core: handle to cpe core structure
 */
static int wcd_cpe_enable(struct wcd_cpe_core *core)
{
	int ret = 0;

	if (!core) {
		pr_err("%s: Invalid handle to core\n",
			__func__);
		ret = -EINVAL;
		goto done;
	}

	if (core->ssr_type != WCD_CPE_INITIALIZED) {
		dev_err(core->dev,
			"%s: CPE not initialized, state = 0x%x\n",
			__func__, core->ssr_type);
		ret = -EINVAL;
		goto done;
	}

	ret = wcd_cpe_setup_irqs(core);
	if (ret) {
		dev_err(core->dev,
			"%s: CPE IRQs setup failed, error = %d\n",
			__func__, ret);
		goto done;
	}

	core->ssr_type = WCD_CPE_ENABLED;
	schedule_work(&core->load_fw_work);

done:
	return ret;
}

/*
 * wcd_cpe_load_store: Function invoked with sysfs property
 *	is written to. Enable CPE if value of the cpe_load
 *	property is non-zero.
 * kobj: Kobject associated with the sysfs property
 * attr: The attribute that is written to
 * buf: holds the data that is written
 * count: number of data bytes in the buffer
 */
static ssize_t wcd_cpe_load_store(struct kobject *kobj,
	struct kobj_attribute *attr,
	const char *buf,
	size_t count)
{
	struct wcd_cpe_core *core;
	int ret = 0;

	if (cpe_priv.cpe_load) {
		pr_err("%s: CPE already loaded\n",
			__func__);
		goto done;
	}

	core = wcd_cpe_get_core_handle(cpe_priv.cdc_handle);
	if (!core) {
		pr_err("%s: Invalid core handle\n",
			__func__);
		goto done;
	}

	sscanf(buf, "%du", &cpe_priv.cpe_load);

	if (cpe_priv.cpe_load) {
		ret = wcd_cpe_enable(core);
		if (IS_ERR_VALUE(ret))
			cpe_priv.cpe_load = 0;
		else
			pr_info("%s: CPE enabled for tomtom_codec\n",
				__func__);
	}

done:
	return count;
}

/*
 * wcd_cpe_init: Initialize CPE related structures
 * @img_fname: filename for firmware image
 * @codec: handle to codec requesting for image download
 * @params: parameter structure passed from caller
 *
 * This API will initialize the cpe core and schedule work
 * to perform firmware image download to CPE and bootup
 * CPE. Will also request for CPE related interrupts.
 * This API will initialize the cpe core but will not
 * download the image or boot the cpe core.
 */
struct wcd_cpe_core *wcd_cpe_init_and_boot(const char *img_fname,
struct wcd_cpe_core *wcd_cpe_init(const char *img_fname,
	struct snd_soc_codec *codec,
	struct wcd_cpe_params *params)
{
@@ -1114,10 +1234,7 @@ struct wcd_cpe_core *wcd_cpe_init_and_boot(const char *img_fname,
	core->cdc_info.minor_version = params->cdc_minor_ver;
	core->cdc_info.id = params->cdc_id;

	core->cpe_cdc_cb.cdc_clk_en = params->cdc_cb->cdc_clk_en;
	core->cpe_cdc_cb.cpe_clk_en = params->cdc_cb->cpe_clk_en;
	core->cpe_cdc_cb.cdc_ext_clk   = params->cdc_cb->cdc_ext_clk;
	core->cpe_cdc_cb.slimtx_lab_en = params->cdc_cb->slimtx_lab_en;
	core->cpe_cdc_cb = params->cdc_cb;

	INIT_WORK(&core->load_fw_work, wcd_cpe_load_fw_image);
	INIT_WORK(&core->ssr_work, wcd_cpe_ssr_work);
@@ -1154,13 +1271,6 @@ struct wcd_cpe_core *wcd_cpe_init_and_boot(const char *img_fname,
		goto fail_cpe_register;
	}

	ret = wcd_cpe_setup_irqs(core);
	if (ret) {
		dev_err(core->dev,
			"%s: CPE IRQs setup failed, error = %d\n",
			__func__, ret);
		goto fail_setup_irq;
	}

	card = codec->card->snd_card;
	snprintf(proc_name, (sizeof("cpe") + sizeof("_state") +
@@ -1192,11 +1302,24 @@ struct wcd_cpe_core *wcd_cpe_init_and_boot(const char *img_fname,
		 */
	}

	schedule_work(&core->load_fw_work);
	return core;
	cpe_priv.cdc_handle = codec;
	cpe_priv.attr_group = &attr_grp;
	cpe_priv.cpe_load_kobj = kobject_create_and_add("wcd_cpe",
					       kernel_kobj);
	if (!cpe_priv.cpe_load_kobj) {
		pr_err("%s: cpe_load: sysfs create_add failed\n",
			__func__);
		goto fail_cpe_register;
	} else if (sysfs_create_group(cpe_priv.cpe_load_kobj,
				      cpe_priv.attr_group)) {
		pr_err("%s: sysfs_create_group failed\n", __func__);
		kobject_del(cpe_priv.cpe_load_kobj);
		goto fail_cpe_register;
	}

	core->ssr_type = WCD_CPE_INITIALIZED;

fail_setup_irq:
	cpe_svc_deregister(core->cpe_handle, core->cpe_reg_handle);
	return core;

fail_cpe_register:
	cpe_svc_deinitialize(core->cpe_handle);
@@ -1205,7 +1328,7 @@ fail_cpe_initialize:
	kfree(core);
	return NULL;
}
EXPORT_SYMBOL(wcd_cpe_init_and_boot);
EXPORT_SYMBOL(wcd_cpe_init);

/*
 * wcd_cpe_cmi_lsm_callback: callback called from cpe services
@@ -2415,17 +2538,19 @@ static int slim_master_read_enable(void *core_handle,
	lsm_params = &lab_s->hw_params;
	/* The sequence should be maintained strictly */
	WCD_CPE_GRAB_LOCK(&session->lsm_lock, "lsm");
	if (core->cpe_cdc_cb.cdc_ext_clk)
		core->cpe_cdc_cb.cdc_ext_clk(codec, true, false);
	if (core->cpe_cdc_cb->cdc_ext_clk)
		core->cpe_cdc_cb->cdc_ext_clk(codec, true, false);
	else {
		pr_err("%s: MCLK cannot be enabled NULL\n", __func__);
		pr_err("%s: Invalid callback for codec ext clk\n",
			__func__);
		rc = -EINVAL;
		goto exit;
	}
	if (core->cpe_cdc_cb.slimtx_lab_en)
		core->cpe_cdc_cb.slimtx_lab_en(codec, 1);

	if (core->cpe_cdc_cb->slimtx_lab_en)
		core->cpe_cdc_cb->slimtx_lab_en(codec, 1);
	else {
		pr_err("%s: Err slim slave cannot be enabled\n",
		pr_err("%s: Failed to enable codec slave port\n",
			__func__);
		rc = -EINVAL;
		goto fail_mclk;
@@ -2459,9 +2584,9 @@ static int slim_master_read_enable(void *core_handle,
	return 0;

fail_slim_open:
	core->cpe_cdc_cb.slimtx_lab_en(codec, 0);
	core->cpe_cdc_cb->slimtx_lab_en(codec, 0);
fail_mclk:
	core->cpe_cdc_cb.cdc_ext_clk(codec, false, false);
	core->cpe_cdc_cb->cdc_ext_clk(codec, false, false);
exit:
	WCD_CPE_REL_LOCK(&session->lsm_lock, "lsm");
	return rc;
@@ -2514,10 +2639,10 @@ static int wcd_cpe_lsm_stop_lab(void *core_handle,
	lab_s = &session->lab;
	WCD_CPE_GRAB_LOCK(&session->lsm_lock, "lsm");
	/* This seqeunce should be followed strictly for closing sequence */
	if (core->cpe_cdc_cb.slimtx_lab_en)
		core->cpe_cdc_cb.slimtx_lab_en(codec, 0);
	if (core->cpe_cdc_cb->slimtx_lab_en)
		core->cpe_cdc_cb->slimtx_lab_en(codec, 0);
	else
		pr_err("%s: Err slim slave cannot be enabled\n",
		pr_err("%s: Failed to disable codec slave port\n",
			__func__);

	rc = wcd9xxx_slim_ch_master_close(wcd9xxx, &lab_s->slim_handle);
@@ -2541,10 +2666,10 @@ static int wcd_cpe_lsm_stop_lab(void *core_handle,
	lab_s->thread_status = MSM_LSM_LAB_THREAD_STOP;
	atomic_set(&lab_s->in_count, 0);
	lab_s->dma_write = 0;
	if (core->cpe_cdc_cb.cdc_ext_clk)
		core->cpe_cdc_cb.cdc_ext_clk(codec, false, false);
	if (core->cpe_cdc_cb->cdc_ext_clk)
		core->cpe_cdc_cb->cdc_ext_clk(codec, false, false);
	else
		pr_err("%s: MCLK cannot be disable NULL\n",
		pr_err("%s: Failed to disable cdc ext clk\n",
			__func__);
	WCD_CPE_REL_LOCK(&session->lsm_lock, "lsm");
	return rc;
+8 −4
Original line number Diff line number Diff line
@@ -38,8 +38,12 @@ struct wcd_cpe_cdc_cb {
};

enum wcd_cpe_ssr_state_event {
	/* Indicates CPE is initialized */
	WCD_CPE_INITIALIZED = 0,
	/* Indicates CPE is enabled */
	WCD_CPE_ENABLED,
	/* Indicates that CPE is currently active */
	WCD_CPE_ACTIVE = 0,
	WCD_CPE_ACTIVE,
	/* Event from underlying bus notifying bus is down */
	WCD_CPE_BUS_DOWN_EVENT,
	/* Event from CPE block, notifying CPE is down */
@@ -84,7 +88,7 @@ struct wcd_cpe_core {
	int cpe_debug_mode;

	/* callbacks for codec specific implementation */
	struct wcd_cpe_cdc_cb cpe_cdc_cb;
	const struct wcd_cpe_cdc_cb *cpe_cdc_cb;

	/* work to handle CPE SSR*/
	struct work_struct ssr_work;
@@ -118,7 +122,7 @@ struct wcd_cpe_params {
	struct snd_soc_codec *codec;
	struct wcd_cpe_core * (*get_cpe_core) (
				struct snd_soc_codec *);
	struct wcd_cpe_cdc_cb *cdc_cb;
	const struct wcd_cpe_cdc_cb *cdc_cb;
	int dbg_mode;
	u16 cdc_major_ver;
	u16 cdc_minor_ver;
@@ -127,5 +131,5 @@ struct wcd_cpe_params {

int wcd_cpe_ssr_event(void *core_handle,
		      enum wcd_cpe_ssr_state_event event);
struct wcd_cpe_core *wcd_cpe_init_and_boot(const char *,
struct wcd_cpe_core *wcd_cpe_init(const char *,
struct snd_soc_codec *, struct wcd_cpe_params *params);
+0 −77
Original line number Diff line number Diff line
@@ -88,33 +88,6 @@ static void *adsp_state_notifier;

#define ADSP_STATE_READY_TIMEOUT_MS 3000

struct cpe_load_priv {
	void *cdc_handle;
	struct kobject *cpe_load_kobj;
	struct attribute_group *attr_group;
};

static int cpe_load;

static ssize_t cpe_load_store(struct kobject *kobj,
	struct kobj_attribute *attr,
	const char *buf,
	size_t count);

static struct kobj_attribute cpe_load_attr =
	__ATTR(cpe_load, 0600, NULL, cpe_load_store);

static struct attribute *attrs[] = {
	&cpe_load_attr.attr,
	NULL,
};

static struct attribute_group attr_grp = {
	.attrs = attrs,
};

static struct cpe_load_priv cpe_priv;

static inline int param_is_mask(int p)
{
	return ((p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
@@ -2111,44 +2084,6 @@ static int msm_snd_get_ext_clk_cnt(void)
	return clk_users;
}

static int apq8084_tomtom_cpe_enable(struct snd_soc_codec *codec)
{
	int ret = 0;

	ret = tomtom_enable_cpe(codec);
	if (IS_ERR_VALUE(ret))
		pr_err("%s: CPE enable failed, err (0x%x)\n",
			__func__, ret);
	return ret;
}

static ssize_t cpe_load_store(struct kobject *kobj,
	struct kobj_attribute *attr,
	const char *buf,
	size_t count)
{
	int ret = 0;

	if (cpe_load) {
		pr_err("%s: CPE already loaded\n",
			__func__);
		return count;
	}

	sscanf(buf, "%du", &cpe_load);

	if (cpe_load) {
		ret = apq8084_tomtom_cpe_enable(cpe_priv.cdc_handle);
		if (IS_ERR_VALUE(ret))
			cpe_load = 0;
		else
			pr_info("%s: CPE enabled for tomtom_codec\n",
				__func__);
	}

	return count;
}

static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
	int err;
@@ -2326,18 +2261,6 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
		tomtom_register_ext_clk_cb(msm_snd_enable_codec_ext_clk,
					   msm_snd_get_ext_clk_cnt,
					   rtd->codec);
		cpe_priv.cdc_handle = codec;
		cpe_priv.attr_group = &attr_grp;
		cpe_priv.cpe_load_kobj = kobject_create_and_add("snd_apq8084",
						       kernel_kobj);
		if (!cpe_priv.cpe_load_kobj) {
			pr_err("%s: cpe_load: sysfs create_add failed\n",
				__func__);
		} else if (sysfs_create_group(cpe_priv.cpe_load_kobj,
					      cpe_priv.attr_group)) {
			pr_err("%s: sysfs_create_group failed\n", __func__);
			kobject_del(cpe_priv.cpe_load_kobj);
		}

		err = msm_snd_enable_codec_ext_clk(rtd->codec, 1, false);
		if (IS_ERR_VALUE(err)) {