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

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

Merge "ASoC: msm: add MI2S support for apq8084 devices"

parents 62de6a43 3dc8f718
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1036,7 +1036,7 @@ Optional properties:
- pinctrl-states: the names of the pinctrl states that used by the driver to
	configure the TLMM pins. The allowed states are subset of the following
	list: pmx-pri-mi2s-active, pmx-pri-quad-mi2s-active, pmx-quad-mi2s-active,
	 pmx-pri-quad-mi2s-sleep.
	 pmx-pri-quad-mi2s-sleep, pmx-quad-mi2s-sleep.
- pinctrl-#: a list of pinctrl phandles for the different pinctrl states. Refer
	to "Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt" for the
	pinctrl handles definitions. Each pinctrl-# corresponds to the respective
+481 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@

static int slim0_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
static int hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
static int mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
static int mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;

#define SAMPLING_RATE_8KHZ 8000
#define SAMPLING_RATE_16KHZ 16000
@@ -147,11 +149,52 @@ struct msm_auxpcm_ctrl {
	u32 cnt;
};

static const struct afe_clk_cfg lpass_default = {
	AFE_API_VERSION_I2S_CONFIG,
	Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
	Q6AFE_LPASS_OSR_CLK_DISABLE,
	Q6AFE_LPASS_CLK_SRC_INTERNAL,
	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
	Q6AFE_LPASS_MODE_CLK1_VALID,
	0,
};

static const char *const mi2s_pin_states[] = {"Disable",
					      "quad_mi2s_active"};

/*
 * enum mi2s_pin_state - states for the mi2s pinctrl states
 * Note: these states are similar to the "pinctrl-names"
 * in board/target specific DTSI file.
 */
enum mi2s_pin_state {
	MI2S_STATE_DISABLE = 0,
	MI2S_STATE_QUAD_ON = 1
};

/*
 * struct msm_mi2s_pinctrl_info - manage all the pinctrl information
 *
 * @pinctrl:		TSC pinctrl state holder.
 * @disable:		pinctrl state to disable all the pins.
 * @quad_mi2s_active:	pinctrl state to activate Quaternary MI2S.
 * @curr_state:		the current state of the TLMM pins.
 */
struct msm_mi2s_pinctrl_info {
	struct pinctrl *pinctrl;
	struct pinctrl_state *disable;
	struct pinctrl_state *quad_mi2s_active;
	enum mi2s_pin_state curr_mi2s_state;
};

struct apq8084_asoc_mach_data {
	u32 mclk_freq;
	int us_euro_gpio;
	struct msm_auxpcm_ctrl *pri_auxpcm_ctrl;
	struct msm_auxpcm_ctrl *sec_auxpcm_ctrl;
	u32 quad_rx_clk_usrs;
	u32 quad_tx_clk_usrs;
	struct msm_mi2s_pinctrl_info mi2s_pinctrl_info;
};

struct apq8084_asoc_wcd93xx_codec {
@@ -185,6 +228,7 @@ static char *msm_sec_auxpcm_gpio_name[][2] = {

void *lpaif_pri_muxsel_virt_addr;
void *lpaif_sec_muxsel_virt_addr;
void *lpaif_quad_muxsel_virt_addr;

struct apq8084_liquid_dock_dev {
	int dock_plug_gpio;
@@ -243,6 +287,12 @@ static int clk_users;
static atomic_t prim_auxpcm_rsc_ref;
static atomic_t sec_auxpcm_rsc_ref;
static bool codec_reg_done;
static int apq8084_mi2s_rx_ch = 1;
static int apq8084_mi2s_tx_ch = 1;
static atomic_t quad_mi2s_ref_count;

static const char *const mi2s_tx_ch_text[] = {"One", "Two"};
static const char *const mi2s_rx_ch_text[] = {"One", "Two"};

static int apq8084_liquid_ext_spk_power_amp_init(void)
{
@@ -1289,6 +1339,322 @@ static struct snd_soc_ops msm_sec_auxpcm_be_ops = {
	.shutdown = msm_sec_auxpcm_shutdown,
};

static int msm_quad_mi2s_set_pinctrl(struct apq8084_asoc_mach_data *pdata)
{
	struct msm_mi2s_pinctrl_info *pinctrl_info = &pdata->mi2s_pinctrl_info;
	int ret = 0;

	pr_debug("%s: curr_mi2s_state = %s\n", __func__,
		 mi2s_pin_states[pinctrl_info->curr_mi2s_state]);
	/* Enable Quaternary MI2S TLMM pins and set to appropriate state */
	switch (pinctrl_info->curr_mi2s_state) {
	case MI2S_STATE_DISABLE:
		ret = pinctrl_select_state(pinctrl_info->pinctrl,
					   pinctrl_info->quad_mi2s_active);
		if (ret) {
			pr_err("%s: pinctrl_select_state failed with %d\n",
				__func__, ret);
			ret = -EIO;
			goto err;
		}
		pinctrl_info->curr_mi2s_state = MI2S_STATE_QUAD_ON;
		break;
	case MI2S_STATE_QUAD_ON:
		pr_err("%s: MI2S TLMM pins already set\n", __func__);
		break;
	default:
		pr_err("%s: MI2S TLMM pin state is invalid\n", __func__);
		return -EINVAL;
	}

err:
	return ret;
}

static int msm_quad_mi2s_reset_pinctrl(struct apq8084_asoc_mach_data *pdata)
{
	struct msm_mi2s_pinctrl_info *pinctrl_info = &pdata->mi2s_pinctrl_info;
	int ret = 0;

	pr_debug("%s: curr_mi2s_state = %s\n", __func__,
		 mi2s_pin_states[pinctrl_info->curr_mi2s_state]);
	/* Reset Quaternary MI2S TLMM pins and set to appropriate state */
	switch (pinctrl_info->curr_mi2s_state) {
	case MI2S_STATE_QUAD_ON:
		ret = pinctrl_select_state(pinctrl_info->pinctrl,
					   pinctrl_info->disable);
		if (ret) {
			pr_err("%s: pinctrl_select_state failed with %d\n",
				__func__, ret);
			ret = -EIO;
			goto err;
		}
		pinctrl_info->curr_mi2s_state = MI2S_STATE_DISABLE;
		break;
	case MI2S_STATE_DISABLE:
		pr_err("%s: MI2S TLMM pins already disabled\n", __func__);
		break;
	default:
		pr_err("%s: MI2S TLMM pin state is invalid\n", __func__);
		return -EINVAL;
	}

err:
	return ret;
}

static int apq8084_quad_mi2s_clk_ctl(struct snd_soc_pcm_runtime *rtd,
				bool enable,
				struct snd_pcm_substream *substream)
{
	struct snd_soc_card *card = rtd->card;
	struct apq8084_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	struct afe_clk_cfg *lpass_clk = NULL;
	int ret = 0;
	u32 afe_port_id;

	if (pdata == NULL) {
		pr_err("%s:platform data is null\n", __func__);
		return -EINVAL;
	}
	lpass_clk = kzalloc(sizeof(struct afe_clk_cfg), GFP_KERNEL);
	if (lpass_clk == NULL) {
		pr_err("%s:Failed to allocate memory\n", __func__);
		return -ENOMEM;
	}
	memcpy(lpass_clk, &lpass_default, sizeof(struct afe_clk_cfg));
	pr_debug("%s: lpass clock enable = %d\n", __func__, enable);
	if (enable) {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_RX;
			if (pdata->quad_rx_clk_usrs == 0) {
				lpass_clk->clk_val1 =
					    Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
				lpass_clk->clk_set_mode =
						Q6AFE_LPASS_MODE_CLK1_VALID;
			}
			ret = afe_set_lpass_clock(afe_port_id, lpass_clk);
			if (ret < 0) {
				pr_err("%s:afe_set_lpass_clock failed with %d\n",
					__func__, ret);
				goto err;
			} else {
				pdata->quad_rx_clk_usrs++;
			}
		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX;
			if (pdata->quad_tx_clk_usrs == 0) {
				lpass_clk->clk_val1 =
					    Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
				lpass_clk->clk_set_mode =
						Q6AFE_LPASS_MODE_CLK1_VALID;
			}
			ret = afe_set_lpass_clock(afe_port_id, lpass_clk);
			if (ret < 0) {
				pr_err("%s:afe_set_lpass_clock failed with %d\n",
					__func__, ret);
				goto err;
			} else {
				pdata->quad_tx_clk_usrs++;
			}
		}
	} else {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_RX;
			if (pdata->quad_rx_clk_usrs > 0)
				pdata->quad_rx_clk_usrs--;
			if (pdata->quad_rx_clk_usrs == 0) {
				lpass_clk->clk_val1 =
						Q6AFE_LPASS_IBIT_CLK_DISABLE;
				lpass_clk->clk_set_mode =
						Q6AFE_LPASS_MODE_CLK1_VALID;
			}
			ret = afe_set_lpass_clock(afe_port_id, lpass_clk);
			if (ret < 0) {
				pr_err("%s:afe_set_lpass_clock failed with %d\n",
					__func__, ret);
				goto err;
			}
		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX;
			if (pdata->quad_tx_clk_usrs > 0)
				pdata->quad_tx_clk_usrs--;
			if (pdata->quad_tx_clk_usrs == 0) {
				lpass_clk->clk_val1 =
						Q6AFE_LPASS_IBIT_CLK_DISABLE;
				lpass_clk->clk_set_mode =
						Q6AFE_LPASS_MODE_CLK1_VALID;
			}
			ret = afe_set_lpass_clock(afe_port_id, lpass_clk);
			if (ret < 0) {
				pr_err("%s:afe_set_lpass_clock failed with %d\n",
					__func__, ret);
				goto err;
			}
		}
	}
	pr_debug("%s: clk 1 = 0x%x clk2 = 0x%x mode = 0x%x\n",
			 __func__, lpass_clk->clk_val1,
			lpass_clk->clk_val2,
			lpass_clk->clk_set_mode);
	ret = 0;
err:
	kfree(lpass_clk);
	return ret;
}

static int msm_quad_mi2s_startup(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_card *card = rtd->card;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct apq8084_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	int ret = 0;
	uint32_t pcm_sel_reg;

	pr_debug("%s(): substream = %s, quad_mi2s_ref_count = %d\n",
		 __func__, substream->name, atomic_read(&quad_mi2s_ref_count));

	if (pdata == NULL || lpaif_quad_muxsel_virt_addr == NULL) {
		pr_err("%s: Invalid parameters for Quad MI2S\n", __func__);
		ret = -EINVAL;
		goto err;
	}
	if (atomic_inc_return(&quad_mi2s_ref_count) == 1) {
		pcm_sel_reg = ioread32(lpaif_quad_muxsel_virt_addr);
		if (pcm_sel_reg & (I2S_PCM_SEL << I2S_PCM_SEL_OFFSET)) {
			iowrite32(pcm_sel_reg &
				~(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET),
				  lpaif_quad_muxsel_virt_addr);
		}

		ret = msm_quad_mi2s_set_pinctrl(pdata);
		if (ret) {
			pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
				__func__, ret);
			return ret;
		}

		ret = apq8084_quad_mi2s_clk_ctl(rtd, true, substream);
		if (ret) {
			pr_err("%s: Setting clk control failed with %d\n",
				__func__, ret);
			return ret;
		}
		/* This sets the CONFIG PARAMETER WS_SRC.
		 * SND_SOC_DAIFMT_CBS_CFS means internal clock/master mode.
		 * SND_SOC_DAIFMT_CBM_CFM means external clock/slave mode.
		 */
		ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
		if (ret)
			pr_err("%s: set fmt cpu dai failed with %d\n",
				__func__, ret);
	}
err:
	return ret;
}

static void msm_quad_mi2s_shutdown(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_card *card = rtd->card;
	struct apq8084_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	int ret;

	pr_debug("%s(): substream = %s, quad_mi2s_ref_count = %d\n",
		 __func__, substream->name, atomic_read(&quad_mi2s_ref_count));

	if (pdata == NULL) {
		pr_err("%s: Invalid platform data\n", __func__);
		return;
	}

	if (atomic_dec_return(&quad_mi2s_ref_count) == 0) {
		ret = msm_quad_mi2s_reset_pinctrl(pdata);
		if (ret)
			pr_err("%s Reset pinctrl failed with %d\n",
				__func__, ret);
		ret = apq8084_quad_mi2s_clk_ctl(rtd, false, substream);
		if (ret)
			pr_err("%s Clock disable failed with %d\n",
				__func__, ret);
	}
}

static struct snd_soc_ops apq8084_quad_mi2s_be_ops = {
	.startup = msm_quad_mi2s_startup,
	.shutdown = msm_quad_mi2s_shutdown,
};

static int apq8084_mi2s_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
					     struct snd_pcm_hw_params *params)
{
	struct snd_interval *rate = hw_param_interval(params,
						SNDRV_PCM_HW_PARAM_RATE);
	struct snd_interval *channels = hw_param_interval(params,
						SNDRV_PCM_HW_PARAM_CHANNELS);
	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
				mi2s_tx_bit_format);
	rate->min = rate->max = SAMPLING_RATE_48KHZ;
	channels->min = channels->max = apq8084_mi2s_tx_ch;
	pr_debug("%s: format = %d rate = %d, channels = %d\n",
			__func__, params_format(params), params_rate(params),
			apq8084_mi2s_tx_ch);
	return 0;
}

static int apq8084_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	pr_debug("%s: apq8084_i2s_tx_ch  = %d\n", __func__,
		 apq8084_mi2s_tx_ch);
	ucontrol->value.integer.value[0] = apq8084_mi2s_tx_ch - 1;
	return 0;
}

static int apq8084_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	apq8084_mi2s_tx_ch = ucontrol->value.integer.value[0] + 1;
	pr_debug("%s: apq8084_i2s_tx_ch = %d\n", __func__,
		 apq8084_mi2s_tx_ch);
	return 1;
}
static int apq8084_mi2s_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
					     struct snd_pcm_hw_params *params)
{
	struct snd_interval *rate = hw_param_interval(params,
						SNDRV_PCM_HW_PARAM_RATE);
	struct snd_interval *channels = hw_param_interval(params,
						SNDRV_PCM_HW_PARAM_CHANNELS);
	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
				mi2s_rx_bit_format);
	rate->min = rate->max = SAMPLING_RATE_48KHZ;
	channels->min = channels->max = apq8084_mi2s_rx_ch;
	pr_debug("%s: format = %d rate = %d, channels = %d\n",
			__func__, params_format(params), params_rate(params),
			apq8084_mi2s_rx_ch);
	return 0;
}

static int apq8084_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	pr_debug("%s: apq8084_i2s_rx_ch  = %d\n", __func__,
		 apq8084_mi2s_rx_ch);
	ucontrol->value.integer.value[0] = apq8084_mi2s_rx_ch - 1;
	return 0;
}

static int apq8084_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	apq8084_mi2s_rx_ch = ucontrol->value.integer.value[0] + 1;
	pr_debug("%s: apq8084_i2s_rx_ch = %d\n", __func__,
		 apq8084_mi2s_tx_ch);
	return 1;
}

static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
					    struct snd_pcm_hw_params *params)
{
@@ -1504,6 +1870,8 @@ static const struct soc_enum msm_snd_enum[] = {
	SOC_ENUM_SINGLE_EXT(2, slim1_tx_ch_text),
	SOC_ENUM_SINGLE_EXT(3, slim1_rate_text),
	SOC_ENUM_SINGLE_EXT(3, slim3_rx_ch_text),
	SOC_ENUM_SINGLE_EXT(2, mi2s_rx_ch_text),
	SOC_ENUM_SINGLE_EXT(2, mi2s_tx_ch_text),
};

static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -1535,6 +1903,10 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
			msm_slim_3_rx_ch_get, msm_slim_3_rx_ch_put),
	SOC_SINGLE_EXT("Incall Rec Mode", SND_SOC_NOPM, 0, 1, 0,
		msm_incall_rec_mode_get, msm_incall_rec_mode_put),
	SOC_ENUM_EXT("QUAT_MI2S_RX Channels", msm_snd_enum[11],
			apq8084_mi2s_rx_ch_get, apq8084_mi2s_rx_ch_put),
	SOC_ENUM_EXT("QUAT_MI2S_TX Channels", msm_snd_enum[12],
			apq8084_mi2s_tx_ch_get, apq8084_mi2s_tx_ch_put),
};

static bool apq8084_swap_gnd_mic(struct snd_soc_codec *codec)
@@ -3027,6 +3399,34 @@ static struct snd_soc_dai_link apq8084_common_be_dai_links[] = {
		.ops = &apq8084_slimbus_6_be_ops,
		.ignore_suspend = 1,
	},
	/* MI2S Backend DAI Links */
	{
		.name = LPASS_BE_QUAT_MI2S_RX,
		.stream_name = "Quaternary MI2S Playback",
		.cpu_dai_name = "msm-dai-q6-mi2s.3",
		.platform_name = "msm-pcm-routing",
		.codec_name = "msm-stub-codec.1",
		.codec_dai_name = "msm-stub-rx",
		.no_pcm = 1,
		.be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
		.be_hw_params_fixup = &apq8084_mi2s_rx_be_hw_params_fixup,
		.ops = &apq8084_quad_mi2s_be_ops,
		.ignore_suspend = 1,
		.ignore_pmdown_time = 1,
	},
	{
		.name = LPASS_BE_QUAT_MI2S_TX,
		.stream_name = "Quaternary MI2S Capture",
		.cpu_dai_name = "msm-dai-q6-mi2s.3",
		.platform_name = "msm-pcm-routing",
		.codec_name = "msm-stub-codec.1",
		.codec_dai_name = "msm-stub-tx",
		.no_pcm = 1,
		.be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
		.be_hw_params_fixup = &apq8084_mi2s_tx_be_hw_params_fixup,
		.ops = &apq8084_quad_mi2s_be_ops,
		.ignore_suspend = 1,
	},
};

static struct snd_soc_dai_link apq8084_tomtom_be_dai_links[] = {
@@ -3345,6 +3745,65 @@ err:
	return ret;
}

/**
 * msm_mi2s_get_pinctrl() - Get the MI2S pinctrl definitions.
 *
 * @pdev:	A pointer to the Audio platform device.
 *
 * Get the pinctrl states' handles from the device tree. The function doesn't
 * enforce wrong pinctrl definitions, i.e. it's the client's responsibility to
 * define all the necessary states for the board being used.
 *
 * Return 0 on success, error value otherwise.
 */
static int msm_mi2s_get_pinctrl(struct platform_device *pdev)
{
	struct snd_soc_card *card = platform_get_drvdata(pdev);
	struct apq8084_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	struct msm_mi2s_pinctrl_info *pinctrl_info = &pdata->mi2s_pinctrl_info;
	struct pinctrl *pinctrl;
	int ret;

	pinctrl = devm_pinctrl_get(&pdev->dev);
	if (IS_ERR_OR_NULL(pinctrl)) {
		pr_err("%s: Unable to get pinctrl handle\n", __func__);
		return -EINVAL;
	}
	pinctrl_info->pinctrl = pinctrl;

	/* get all the states handles from Device Tree*/
	pinctrl_info->disable = pinctrl_lookup_state(pinctrl,
						"pmx-quad-mi2s-sleep");
	if (IS_ERR(pinctrl_info->disable)) {
		pr_err("%s: could not get disable pinstate\n", __func__);
		goto err;
	}

	pinctrl_info->quad_mi2s_active = pinctrl_lookup_state(pinctrl,
						"pmx-quad-mi2s-active");
	if (IS_ERR(pinctrl_info->quad_mi2s_active)) {
		pr_err("%s: could not get quad_mi2s_active pinstate\n",
			__func__);
		goto err;
	}

	/* Reset the MI2S TLMM pins to a default state */
	ret = pinctrl_select_state(pinctrl_info->pinctrl,
					pinctrl_info->disable);
	if (ret != 0) {
		pr_err("%s: Disable MI2S TLMM pins failed with %d\n",
			__func__, ret);
		return -EIO;
	}
	pinctrl_info->curr_mi2s_state = MI2S_STATE_DISABLE;
	return 0;

err:
	devm_pinctrl_put(pinctrl);
	pinctrl_info->pinctrl = NULL;
	return -EINVAL;
}

static int apq8084_prepare_us_euro(struct snd_soc_card *card)
{
	struct apq8084_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
@@ -3537,6 +3996,24 @@ static int apq8084_asoc_machine_probe(struct platform_device *pdev)
		goto err;
	}

	/* Parse pinctrl info for MI2S ports, if defined */
	ret = msm_mi2s_get_pinctrl(pdev);
	if (!ret) {
		pr_debug("%s: MI2S pinctrl parsing successful\n", __func__);
		lpaif_quad_muxsel_virt_addr =
				ioremap(LPAIF_QUAD_MODE_MUXSEL, 4);
		if (lpaif_quad_muxsel_virt_addr == NULL) {
			pr_err("%s Quad MI2S mux virt addr is null\n",
				__func__);
			ret = -EINVAL;
			goto err;
		}
	} else {
		dev_info(&pdev->dev,
			"%s: Parsing pinctrl failed with %d. Cannot use MI2S Ports\n",
			__func__, ret);
	}

	pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
				"qcom,us-euro-gpios", 0);
	if (pdata->us_euro_gpio < 0) {
@@ -3586,6 +4063,10 @@ static int apq8084_asoc_machine_probe(struct platform_device *pdev)
	return 0;

err:
	if (pdata->mi2s_pinctrl_info.pinctrl) {
		dev_dbg(&pdev->dev, "%s: freeing MI2S pinctrl\n", __func__);
		devm_pinctrl_put(pdata->mi2s_pinctrl_info.pinctrl);
	}
	if (pdata->us_euro_gpio > 0) {
		dev_dbg(&pdev->dev, "%s free us_euro gpio %d\n",
			__func__, pdata->us_euro_gpio);