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

Commit 34a40bce authored by Vatsal Bucha's avatar Vatsal Bucha
Browse files

ASoC: wcd934x: Enable slim tx port auto recovery mechanism



Enable slimbus tx port auto recovery mechanism for wcd934x
audio codec to recover from slimbus underflow/overflow errors
causing audio TX mute.

CRs-Fixed: 1110511
Change-Id: Ic6f120807ec58d75b7b236e80705279a0b198d36
Signed-off-by: default avatarPhani Kumar Uppalapati <phaniu@codeaurora.org>
Signed-off-by: default avatarVatsal Bucha <vbucha@codeaurora.org>
parent bfbb1644
Loading
Loading
Loading
Loading
+47 −2
Original line number Diff line number Diff line
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -151,6 +151,7 @@ static const struct snd_kcontrol_new name##_mux = \
#define  CF_MIN_3DB_75HZ		0x1
#define  CF_MIN_3DB_150HZ		0x2

#define  SB_OF_UF_MAX_RETRY_CNT		5
#define CPE_ERR_WDOG_BITE BIT(0)
#define CPE_FATAL_IRQS CPE_ERR_WDOG_BITE

@@ -647,6 +648,7 @@ struct tavil_priv {
	int micb_load_low;
	int micb_load_high;
	u8 dmic_drv_ctl;
	unsigned short slim_tx_of_uf_cnt[WCD934X_TX_MAX][SB_PORT_ERR_MAX];
};

static const struct tavil_reg_mask_val tavil_spkr_default[] = {
@@ -1871,6 +1873,7 @@ static int tavil_codec_enable_tx(struct snd_soc_dapm_widget *w,
	struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
	struct wcd9xxx_codec_dai_data *dai;
	struct wcd9xxx *core;
	struct wcd9xxx_ch *ch;
	int ret = 0;

	dev_dbg(codec->dev,
@@ -1907,6 +1910,13 @@ static int tavil_codec_enable_tx(struct snd_soc_dapm_widget *w,
			dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
				 __func__, ret);
		}
		/* reset overflow and underflow counts */
		list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
			tavil_p->slim_tx_of_uf_cnt[ch->port][SB_PORT_ERR_OF]
									= 0;
			tavil_p->slim_tx_of_uf_cnt[ch->port][SB_PORT_ERR_UF]
									= 0;
		}
		break;
	}
	return ret;
@@ -1919,6 +1929,7 @@ static int tavil_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
	struct wcd9xxx *core = NULL;
	struct snd_soc_codec *codec = NULL;
	struct tavil_priv *tavil_p = NULL;
	struct wcd9xxx_ch *ch;
	int ret = 0;
	struct wcd9xxx_codec_dai_data *dai = NULL;

@@ -2013,6 +2024,13 @@ static int tavil_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
			dev_dbg(codec->dev, "%s: Disconnect TX port, ret = %d\n",
				__func__, ret);
		}
		/* reset over.f and under.f counts */
		list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
			tavil_p->slim_tx_of_uf_cnt[ch->port][SB_PORT_ERR_OF]
									= 0;
			tavil_p->slim_tx_of_uf_cnt[ch->port][SB_PORT_ERR_UF]
									= 0;
		}
		if (test_bit(VI_SENSE_1, &tavil_p->status_mask)) {
			/* Disable V&I sensing */
			dev_dbg(codec->dev, "%s: spkr1 disabled\n", __func__);
@@ -9686,14 +9704,40 @@ static irqreturn_t tavil_slimbus_irq(int irq, void *data)
		if (val & WCD934X_SLIM_IRQ_UNDERFLOW)
			dev_err_ratelimited(tavil->dev, "%s: underflow error on %s port %d, value %x\n",
			   __func__, (tx ? "TX" : "RX"), port_id, val);
		if (tx) {
			/* inc count */
			if (val & WCD934X_SLIM_IRQ_OVERFLOW) {
				tavil->slim_tx_of_uf_cnt[port_id]
							[SB_PORT_ERR_OF]++;
				dev_err_ratelimited(tavil->dev, "%s: tx port(%d) overflow cnt: %d\n",
					__func__, port_id,
					tavil->slim_tx_of_uf_cnt[port_id]
							[SB_PORT_ERR_OF]);
			}
			if (val & WCD934X_SLIM_IRQ_UNDERFLOW) {
				tavil->slim_tx_of_uf_cnt[port_id]
							[SB_PORT_ERR_UF]++;
				dev_err_ratelimited(tavil->dev, "%s: tx port(%d) underflow cnt: %d\n",
						__func__, port_id,
					tavil->slim_tx_of_uf_cnt[port_id]
							[SB_PORT_ERR_UF]);
			}

		}

		if ((val & WCD934X_SLIM_IRQ_OVERFLOW) ||
			(val & WCD934X_SLIM_IRQ_UNDERFLOW)) {
			if (!tx)
				reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 +
					(port_id / 8);
			else
			else if ((tavil->slim_tx_of_uf_cnt[port_id]
				[SB_PORT_ERR_OF] > SB_OF_UF_MAX_RETRY_CNT) ||
				(tavil->slim_tx_of_uf_cnt[port_id]
				[SB_PORT_ERR_UF] > SB_OF_UF_MAX_RETRY_CNT))
				reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 +
					(port_id / 8);
			else
				goto skip_port_disable;
			int_val = wcd9xxx_interface_reg_read(
				tavil->wcd9xxx, reg);
			if (int_val & (1 << (port_id % 8))) {
@@ -9702,6 +9746,7 @@ static irqreturn_t tavil_slimbus_irq(int irq, void *data)
					reg, int_val);
			}
		}
skip_port_disable:
		if (val & WCD934X_SLIM_IRQ_PORT_CLOSED) {
			/*
			 * INT SOURCE register starts from RX to TX
+8 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -95,6 +95,13 @@ enum {
	INTERP_MAX,
};

/* WCD934X slimbus slave port error status */
enum {
	SB_PORT_ERR_OF, /* SB port overflow */
	SB_PORT_ERR_UF, /* SB port underflow */
	SB_PORT_ERR_MAX,
};

/*
 * Selects compander and smart boost settings
 * for a given speaker mode