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

Commit d66be9be authored by Sudheer Papothi's avatar Sudheer Papothi
Browse files

ASoC: wcd9335: Add support in codec to reduce cold start latency



As soundwire is in wcd9335 codec, all soundwire register writes
should go through codec. To reduce the latency of register
writes during device path bringup, add bulk register write
function to write multiple soundwire registers in one
transaction.

Change-Id: I97055d20ef1e7cfb15b41e00183291a10af35b1f
Signed-off-by: default avatarSudheer Papothi <spapothi@codeaurora.org>
parent 68424872
Loading
Loading
Loading
Loading
+60 −18
Original line number Diff line number Diff line
@@ -496,6 +496,7 @@ struct wcd_swr_ctrl_platform_data {
	void *handle; /* holds codec private data */
	int (*read)(void *handle, int reg);
	int (*write)(void *handle, int reg, int val);
	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
	int (*clk)(void *handle, bool enable);
	int (*handle_irq)(void *handle,
			  irqreturn_t (*swrm_irq_handler)(int irq,
@@ -9097,7 +9098,6 @@ static int tasha_hw_params(struct snd_pcm_substream *substream,
		 dai->name, dai->id, params_rate(params),
		 params_channels(params));


	switch (substream->stream) {
	case SNDRV_PCM_STREAM_PLAYBACK:
		ret = tasha_set_interpolator_rate(dai, params_rate(params));
@@ -10819,43 +10819,84 @@ err:
	return ret;
}

static int tasha_swrm_write(void *handle, int reg, int val)
static int tasha_swrm_bulk_write(void *handle, u32 *reg, u32 *val, size_t len)
{
	struct tasha_priv *tasha;
	struct wcd9xxx *wcd9xxx;
	struct wcd9xxx_reg_val *bulk_reg;
	unsigned short swr_wr_addr_base;
	unsigned short swr_wr_data_base;
	int ret;
	int i, j, ret;

	if (!handle) {
		pr_err("%s: NULL handle\n", __func__);
		return -EINVAL;
	}
	if (len <= 0) {
		pr_err("%s: Invalid size: %zu\n", __func__, len);
		return -EINVAL;
	}
	tasha = (struct tasha_priv *)handle;
	wcd9xxx = tasha->wcd9xxx;

	dev_dbg(tasha->dev, "%s: writing soundwire register, reg: 0x%x, val: 0x%x\n",
		__func__, reg, val);
	swr_wr_addr_base = WCD9335_SWR_AHB_BRIDGE_WR_ADDR_0;
	swr_wr_data_base = WCD9335_SWR_AHB_BRIDGE_WR_DATA_0;

	bulk_reg = kzalloc((2 * len * sizeof(struct wcd9xxx_reg_val)),
			   GFP_KERNEL);
	if (!bulk_reg)
		return -ENOMEM;

	for (i = 0, j = 0; i < (len * 2); i += 2, j++) {
		bulk_reg[i].reg = swr_wr_data_base;
		bulk_reg[i].buf = (u8 *)(&val[j]);
		bulk_reg[i].bytes = 4;
		bulk_reg[i+1].reg = swr_wr_addr_base;
		bulk_reg[i+1].buf = (u8 *)(&reg[j]);
		bulk_reg[i+1].bytes = 4;
	}
	mutex_lock(&tasha->swr_write_lock);
	/* First Write the Data to registe */
	ret = wcd9xxx_bulk_write(&wcd9xxx->core_res, swr_wr_data_base, 4,
				 (u8 *)&val);
	if (ret < 0) {
		pr_err("%s: WR Data Failure\n", __func__);
		goto err;
	ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg, (len * 2), false);
	if (ret)
		dev_err(tasha->dev, "%s: swrm bulk write failed, ret: %d\n",
			__func__, ret);
	mutex_unlock(&tasha->swr_write_lock);
	kfree(bulk_reg);

	return ret;
}
	/* Next Write Address */
	ret = wcd9xxx_bulk_write(&wcd9xxx->core_res, swr_wr_addr_base, 4,
				 (u8 *)&reg);
	if (ret < 0) {
		pr_err("%s: WR Addr Failure\n", __func__);
		goto err;

static int tasha_swrm_write(void *handle, int reg, int val)
{
	struct tasha_priv *tasha;
	struct wcd9xxx *wcd9xxx;
	unsigned short swr_wr_addr_base;
	unsigned short swr_wr_data_base;
	struct wcd9xxx_reg_val bulk_reg[2];
	int ret;

	if (!handle) {
		pr_err("%s: NULL handle\n", __func__);
		return -EINVAL;
	}
	tasha = (struct tasha_priv *)handle;
	wcd9xxx = tasha->wcd9xxx;

err:
	swr_wr_addr_base = WCD9335_SWR_AHB_BRIDGE_WR_ADDR_0;
	swr_wr_data_base = WCD9335_SWR_AHB_BRIDGE_WR_DATA_0;

	/* First Write the Data to register */
	bulk_reg[0].reg = swr_wr_data_base;
	bulk_reg[0].buf = (u8 *)(&val);
	bulk_reg[0].bytes = 4;
	bulk_reg[1].reg = swr_wr_addr_base;
	bulk_reg[1].buf = (u8 *)(&reg);
	bulk_reg[1].bytes = 4;

	mutex_lock(&tasha->swr_write_lock);
	ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg, 2, false);
	if (ret < 0)
		pr_err("%s: WR Data Failure\n", __func__);
	mutex_unlock(&tasha->swr_write_lock);
	return ret;
}
@@ -11080,6 +11121,7 @@ static int tasha_probe(struct platform_device *pdev)
	tasha->swr_plat_data.handle = (void *) tasha;
	tasha->swr_plat_data.read = tasha_swrm_read;
	tasha->swr_plat_data.write = tasha_swrm_write;
	tasha->swr_plat_data.bulk_write = tasha_swrm_bulk_write;
	tasha->swr_plat_data.clk = tasha_swrm_clock;
	tasha->swr_plat_data.handle_irq = tasha_swrm_handle_irq;