diff options
| -rw-r--r-- | Documentation/devicetree/bindings/sound/ak4613.txt | 17 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/sound/ak4642.txt | 22 | ||||
| -rw-r--r-- | drivers/spi/spi-atmel.c | 21 | ||||
| -rw-r--r-- | include/sound/soc.h | 12 | ||||
| -rw-r--r-- | sound/soc/atmel/atmel_wm8904.c | 1 | ||||
| -rw-r--r-- | sound/soc/au1x/db1000.c | 10 | ||||
| -rw-r--r-- | sound/soc/au1x/db1200.c | 10 | ||||
| -rw-r--r-- | sound/soc/codecs/Kconfig | 5 | ||||
| -rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/ak4613.c | 497 | ||||
| -rw-r--r-- | sound/soc/codecs/ak4642.c | 153 | ||||
| -rw-r--r-- | sound/soc/codecs/arizona.c | 16 | ||||
| -rw-r--r-- | sound/soc/codecs/arizona.h | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/wm5110.c | 187 | 
14 files changed, 844 insertions, 111 deletions
| diff --git a/Documentation/devicetree/bindings/sound/ak4613.txt b/Documentation/devicetree/bindings/sound/ak4613.txt new file mode 100644 index 000000000000..15a919522b42 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ak4613.txt @@ -0,0 +1,17 @@ +AK4613 I2C transmitter + +This device supports I2C mode only. + +Required properties: + +- compatible : "asahi-kasei,ak4613" +- reg : The chip select number on the I2C bus + +Example: + +&i2c { +	ak4613: ak4613@0x10 { +		compatible = "asahi-kasei,ak4613"; +		reg = <0x10>; +	}; +}; diff --git a/Documentation/devicetree/bindings/sound/ak4642.txt b/Documentation/devicetree/bindings/sound/ak4642.txt index 623d4e70ae11..340784db6808 100644 --- a/Documentation/devicetree/bindings/sound/ak4642.txt +++ b/Documentation/devicetree/bindings/sound/ak4642.txt @@ -7,7 +7,14 @@ Required properties:    - compatible : "asahi-kasei,ak4642" or "asahi-kasei,ak4643" or "asahi-kasei,ak4648"    - reg : The chip select number on the I2C bus -Example: +Optional properties: + +  - #clock-cells :		common clock binding; shall be set to 0 +  - clocks :			common clock binding; MCKI clock +  - clock-frequency :		common clock binding; frequency of MCKO +  - clock-output-names :	common clock binding; MCKO clock name + +Example 1:  &i2c {  	ak4648: ak4648@0x12 { @@ -15,3 +22,16 @@ Example:  		reg = <0x12>;  	};  }; + +Example 2: + +&i2c { +	ak4643: codec@12 { +		compatible = "asahi-kasei,ak4643"; +		reg = <0x12>; +		#clock-cells = <0>; +		clocks = <&audio_clock>; +		clock-frequency = <12288000>; +		clock-output-names = "ak4643_mcko"; +	}; +}; diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index bf9ed380bb1c..1cc1f1e0d17f 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -871,14 +871,7 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as,  	 * Calculate the lowest divider that satisfies the  	 * constraint, assuming div32/fdiv/mbz == 0.  	 */ -	if (xfer->speed_hz) -		scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz); -	else -		/* -		 * This can happend if max_speed is null. -		 * In this case, we set the lowest possible speed -		 */ -		scbr = 0xff; +	scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz);  	/*  	 * If the resulting divider doesn't fit into the @@ -1300,14 +1293,12 @@ static int atmel_spi_one_transfer(struct spi_master *master,  		return -EINVAL;  	} -	if (xfer->bits_per_word) { -		asd = spi->controller_state; -		bits = (asd->csr >> 4) & 0xf; -		if (bits != xfer->bits_per_word - 8) { -			dev_dbg(&spi->dev, +	asd = spi->controller_state; +	bits = (asd->csr >> 4) & 0xf; +	if (bits != xfer->bits_per_word - 8) { +		dev_dbg(&spi->dev,  			"you can't yet change bits_per_word in transfers\n"); -			return -ENOPROTOOPT; -		} +		return -ENOPROTOOPT;  	}  	/* diff --git a/include/sound/soc.h b/include/sound/soc.h index 884e728b09d9..9ffa28514fa7 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -226,6 +226,18 @@  	.info = snd_soc_info_volsw, \  	.get = xhandler_get, .put = xhandler_put, \  	.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) } +#define SOC_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \ +				 xhandler_get, xhandler_put, tlv_array) \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ +	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ +		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\ +	.tlv.p = (tlv_array), \ +	.info = snd_soc_info_volsw_range, \ +	.get = xhandler_get, .put = xhandler_put, \ +	.private_value = (unsigned long)&(struct soc_mixer_control) \ +		{.reg = xreg, .rreg = xreg, .shift = xshift, \ +		 .rshift = xshift, .min = xmin, .max = xmax, \ +		 .platform_max = xmax, .invert = xinvert} }  #define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\  	 xhandler_get, xhandler_put, tlv_array) \  {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c index aa354e1c6ff7..1933bcd46cca 100644 --- a/sound/soc/atmel/atmel_wm8904.c +++ b/sound/soc/atmel/atmel_wm8904.c @@ -176,6 +176,7 @@ static const struct of_device_id atmel_asoc_wm8904_dt_ids[] = {  	{ .compatible = "atmel,asoc-wm8904", },  	{ }  }; +MODULE_DEVICE_TABLE(of, atmel_asoc_wm8904_dt_ids);  #endif  static struct platform_driver atmel_asoc_wm8904_driver = { diff --git a/sound/soc/au1x/db1000.c b/sound/soc/au1x/db1000.c index 452f404abfd2..e97c32798e98 100644 --- a/sound/soc/au1x/db1000.c +++ b/sound/soc/au1x/db1000.c @@ -38,14 +38,7 @@ static int db1000_audio_probe(struct platform_device *pdev)  {  	struct snd_soc_card *card = &db1000_ac97;  	card->dev = &pdev->dev; -	return snd_soc_register_card(card); -} - -static int db1000_audio_remove(struct platform_device *pdev) -{ -	struct snd_soc_card *card = platform_get_drvdata(pdev); -	snd_soc_unregister_card(card); -	return 0; +	return devm_snd_soc_register_card(&pdev->dev, card);  }  static struct platform_driver db1000_audio_driver = { @@ -54,7 +47,6 @@ static struct platform_driver db1000_audio_driver = {  		.pm	= &snd_soc_pm_ops,  	},  	.probe		= db1000_audio_probe, -	.remove		= db1000_audio_remove,  };  module_platform_driver(db1000_audio_driver); diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index 58c3164802b8..638ca0ba7e6e 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -174,14 +174,7 @@ static int db1200_audio_probe(struct platform_device *pdev)  	card = db1200_cards[pid->driver_data];  	card->dev = &pdev->dev; -	return snd_soc_register_card(card); -} - -static int db1200_audio_remove(struct platform_device *pdev) -{ -	struct snd_soc_card *card = platform_get_drvdata(pdev); -	snd_soc_unregister_card(card); -	return 0; +	return devm_snd_soc_register_card(&pdev->dev, card);  }  static struct platform_driver db1200_audio_driver = { @@ -191,7 +184,6 @@ static struct platform_driver db1200_audio_driver = {  	},  	.id_table	= db1200_pids,  	.probe		= db1200_audio_probe, -	.remove		= db1200_audio_remove,  };  module_platform_driver(db1200_audio_driver); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0c9733ecd17f..a92e4d4b2eee 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -36,6 +36,7 @@ config SND_SOC_ALL_CODECS  	select SND_SOC_AK4104 if SPI_MASTER  	select SND_SOC_AK4535 if I2C  	select SND_SOC_AK4554 +	select SND_SOC_AK4613 if I2C  	select SND_SOC_AK4641 if I2C  	select SND_SOC_AK4642 if I2C  	select SND_SOC_AK4671 if I2C @@ -319,6 +320,10 @@ config SND_SOC_AK4535  config SND_SOC_AK4554  	tristate "AKM AK4554 CODEC" +config SND_SOC_AK4613 +	tristate "AKM AK4613 CODEC" +	depends on I2C +  config SND_SOC_AK4641  	tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 4a32077954ae..5b6c8af38a39 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -26,6 +26,7 @@ snd-soc-ads117x-objs := ads117x.o  snd-soc-ak4104-objs := ak4104.o  snd-soc-ak4535-objs := ak4535.o  snd-soc-ak4554-objs := ak4554.o +snd-soc-ak4613-objs := ak4613.o  snd-soc-ak4641-objs := ak4641.o  snd-soc-ak4642-objs := ak4642.o  snd-soc-ak4671-objs := ak4671.o @@ -216,6 +217,7 @@ obj-$(CONFIG_SND_SOC_ADS117X)	+= snd-soc-ads117x.o  obj-$(CONFIG_SND_SOC_AK4104)	+= snd-soc-ak4104.o  obj-$(CONFIG_SND_SOC_AK4535)	+= snd-soc-ak4535.o  obj-$(CONFIG_SND_SOC_AK4554)	+= snd-soc-ak4554.o +obj-$(CONFIG_SND_SOC_AK4613)	+= snd-soc-ak4613.o  obj-$(CONFIG_SND_SOC_AK4641)	+= snd-soc-ak4641.o  obj-$(CONFIG_SND_SOC_AK4642)	+= snd-soc-ak4642.o  obj-$(CONFIG_SND_SOC_AK4671)	+= snd-soc-ak4671.o diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c new file mode 100644 index 000000000000..07a266460ec3 --- /dev/null +++ b/sound/soc/codecs/ak4613.c @@ -0,0 +1,497 @@ +/* + * ak4613.c  --  Asahi Kasei ALSA Soc Audio driver + * + * Copyright (C) 2015 Renesas Electronics Corporation + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * Based on ak4642.c by Kuninori Morimoto + * Based on wm8731.c by Richard Purdie + * Based on ak4535.c by Richard Purdie + * Based on wm8753.c by Liam Girdwood + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/clk.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/of_device.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <sound/soc.h> +#include <sound/pcm_params.h> +#include <sound/tlv.h> + +#define PW_MGMT1	0x00 /* Power Management 1 */ +#define PW_MGMT2	0x01 /* Power Management 2 */ +#define PW_MGMT3	0x02 /* Power Management 3 */ +#define CTRL1		0x03 /* Control 1 */ +#define CTRL2		0x04 /* Control 2 */ +#define DEMP1		0x05 /* De-emphasis1 */ +#define DEMP2		0x06 /* De-emphasis2 */ +#define OFD		0x07 /* Overflow Detect */ +#define ZRD		0x08 /* Zero Detect */ +#define ICTRL		0x09 /* Input Control */ +#define OCTRL		0x0a /* Output Control */ +#define LOUT1		0x0b /* LOUT1 Volume Control */ +#define ROUT1		0x0c /* ROUT1 Volume Control */ +#define LOUT2		0x0d /* LOUT2 Volume Control */ +#define ROUT2		0x0e /* ROUT2 Volume Control */ +#define LOUT3		0x0f /* LOUT3 Volume Control */ +#define ROUT3		0x10 /* ROUT3 Volume Control */ +#define LOUT4		0x11 /* LOUT4 Volume Control */ +#define ROUT4		0x12 /* ROUT4 Volume Control */ +#define LOUT5		0x13 /* LOUT5 Volume Control */ +#define ROUT5		0x14 /* ROUT5 Volume Control */ +#define LOUT6		0x15 /* LOUT6 Volume Control */ +#define ROUT6		0x16 /* ROUT6 Volume Control */ + +/* PW_MGMT1 */ +#define RSTN		BIT(0) +#define PMDAC		BIT(1) +#define PMADC		BIT(2) +#define PMVR		BIT(3) + +/* PW_MGMT2 */ +#define PMAD_ALL	0x7 + +/* PW_MGMT3 */ +#define PMDA_ALL	0x3f + +/* CTRL1 */ +#define DIF0		BIT(3) +#define DIF1		BIT(4) +#define DIF2		BIT(5) +#define TDM0		BIT(6) +#define TDM1		BIT(7) +#define NO_FMT		(0xff) +#define FMT_MASK	(0xf8) + +/* CTRL2 */ +#define DFS_NORMAL_SPEED	(0 << 2) +#define DFS_DOUBLE_SPEED	(1 << 2) +#define DFS_QUAD_SPEED		(2 << 2) + +struct ak4613_priv { +	struct mutex lock; + +	unsigned int fmt; +	u8 fmt_ctrl; +	int cnt; +}; + +struct ak4613_formats { +	unsigned int width; +	unsigned int fmt; +}; + +struct ak4613_interface { +	struct ak4613_formats capture; +	struct ak4613_formats playback; +}; + +/* + * Playback Volume + * + * max : 0x00 : 0 dB + *       ( 0.5 dB step ) + * min : 0xFE : -127.0 dB + * mute: 0xFF + */ +static const DECLARE_TLV_DB_SCALE(out_tlv, -12750, 50, 1); + +static const struct snd_kcontrol_new ak4613_snd_controls[] = { +	SOC_DOUBLE_R_TLV("Digital Playback Volume1", LOUT1, ROUT1, +			 0, 0xFF, 1, out_tlv), +	SOC_DOUBLE_R_TLV("Digital Playback Volume2", LOUT2, ROUT2, +			 0, 0xFF, 1, out_tlv), +	SOC_DOUBLE_R_TLV("Digital Playback Volume3", LOUT3, ROUT3, +			 0, 0xFF, 1, out_tlv), +	SOC_DOUBLE_R_TLV("Digital Playback Volume4", LOUT4, ROUT4, +			 0, 0xFF, 1, out_tlv), +	SOC_DOUBLE_R_TLV("Digital Playback Volume5", LOUT5, ROUT5, +			 0, 0xFF, 1, out_tlv), +	SOC_DOUBLE_R_TLV("Digital Playback Volume6", LOUT6, ROUT6, +			 0, 0xFF, 1, out_tlv), +}; + +static const struct reg_default ak4613_reg[] = { +	{ 0x0,  0x0f }, { 0x1,  0x07 }, { 0x2,  0x3f }, { 0x3,  0x20 }, +	{ 0x4,  0x20 }, { 0x5,  0x55 }, { 0x6,  0x05 }, { 0x7,  0x07 }, +	{ 0x8,  0x0f }, { 0x9,  0x07 }, { 0xa,  0x3f }, { 0xb,  0x00 }, +	{ 0xc,  0x00 }, { 0xd,  0x00 }, { 0xe,  0x00 }, { 0xf,  0x00 }, +	{ 0x10, 0x00 }, { 0x11, 0x00 }, { 0x12, 0x00 }, { 0x13, 0x00 }, +	{ 0x14, 0x00 }, { 0x15, 0x00 }, { 0x16, 0x00 }, +}; + +#define AUDIO_IFACE_IDX_TO_VAL(i) (i << 3) +#define AUDIO_IFACE(b, fmt) { b, SND_SOC_DAIFMT_##fmt } +static const struct ak4613_interface ak4613_iface[] = { +	/* capture */				/* playback */ +	[0] = {	AUDIO_IFACE(24, LEFT_J),	AUDIO_IFACE(16, RIGHT_J) }, +	[1] = {	AUDIO_IFACE(24, LEFT_J),	AUDIO_IFACE(20, RIGHT_J) }, +	[2] = {	AUDIO_IFACE(24, LEFT_J),	AUDIO_IFACE(24, RIGHT_J) }, +	[3] = {	AUDIO_IFACE(24, LEFT_J),	AUDIO_IFACE(24, LEFT_J) }, +	[4] = {	AUDIO_IFACE(24, I2S),		AUDIO_IFACE(24, I2S) }, +}; + +static const struct regmap_config ak4613_regmap_cfg = { +	.reg_bits		= 8, +	.val_bits		= 8, +	.max_register		= 0x16, +	.reg_defaults		= ak4613_reg, +	.num_reg_defaults	= ARRAY_SIZE(ak4613_reg), +}; + +static const struct of_device_id ak4613_of_match[] = { +	{ .compatible = "asahi-kasei,ak4613",	.data = &ak4613_regmap_cfg }, +	{}, +}; +MODULE_DEVICE_TABLE(of, ak4613_of_match); + +static const struct i2c_device_id ak4613_i2c_id[] = { +	{ "ak4613", (kernel_ulong_t)&ak4613_regmap_cfg }, +	{ } +}; +MODULE_DEVICE_TABLE(i2c, ak4613_i2c_id); + +static const struct snd_soc_dapm_widget ak4613_dapm_widgets[] = { + +	/* Outputs */ +	SND_SOC_DAPM_OUTPUT("LOUT1"), +	SND_SOC_DAPM_OUTPUT("LOUT2"), +	SND_SOC_DAPM_OUTPUT("LOUT3"), +	SND_SOC_DAPM_OUTPUT("LOUT4"), +	SND_SOC_DAPM_OUTPUT("LOUT5"), +	SND_SOC_DAPM_OUTPUT("LOUT6"), + +	SND_SOC_DAPM_OUTPUT("ROUT1"), +	SND_SOC_DAPM_OUTPUT("ROUT2"), +	SND_SOC_DAPM_OUTPUT("ROUT3"), +	SND_SOC_DAPM_OUTPUT("ROUT4"), +	SND_SOC_DAPM_OUTPUT("ROUT5"), +	SND_SOC_DAPM_OUTPUT("ROUT6"), + +	/* Inputs */ +	SND_SOC_DAPM_INPUT("LIN1"), +	SND_SOC_DAPM_INPUT("LIN2"), + +	SND_SOC_DAPM_INPUT("RIN1"), +	SND_SOC_DAPM_INPUT("RIN2"), + +	/* DAC */ +	SND_SOC_DAPM_DAC("DAC1", NULL, PW_MGMT3, 0, 0), +	SND_SOC_DAPM_DAC("DAC2", NULL, PW_MGMT3, 1, 0), +	SND_SOC_DAPM_DAC("DAC3", NULL, PW_MGMT3, 2, 0), +	SND_SOC_DAPM_DAC("DAC4", NULL, PW_MGMT3, 3, 0), +	SND_SOC_DAPM_DAC("DAC5", NULL, PW_MGMT3, 4, 0), +	SND_SOC_DAPM_DAC("DAC6", NULL, PW_MGMT3, 5, 0), + +	/* ADC */ +	SND_SOC_DAPM_ADC("ADC1", NULL, PW_MGMT2, 0, 0), +	SND_SOC_DAPM_ADC("ADC2", NULL, PW_MGMT2, 1, 0), +}; + +static const struct snd_soc_dapm_route ak4613_intercon[] = { +	{"LOUT1", NULL, "DAC1"}, +	{"LOUT2", NULL, "DAC2"}, +	{"LOUT3", NULL, "DAC3"}, +	{"LOUT4", NULL, "DAC4"}, +	{"LOUT5", NULL, "DAC5"}, +	{"LOUT6", NULL, "DAC6"}, + +	{"ROUT1", NULL, "DAC1"}, +	{"ROUT2", NULL, "DAC2"}, +	{"ROUT3", NULL, "DAC3"}, +	{"ROUT4", NULL, "DAC4"}, +	{"ROUT5", NULL, "DAC5"}, +	{"ROUT6", NULL, "DAC6"}, + +	{"DAC1", NULL, "Playback"}, +	{"DAC2", NULL, "Playback"}, +	{"DAC3", NULL, "Playback"}, +	{"DAC4", NULL, "Playback"}, +	{"DAC5", NULL, "Playback"}, +	{"DAC6", NULL, "Playback"}, + +	{"Capture", NULL, "ADC1"}, +	{"Capture", NULL, "ADC2"}, + +	{"ADC1", NULL, "LIN1"}, +	{"ADC2", NULL, "LIN2"}, + +	{"ADC1", NULL, "RIN1"}, +	{"ADC2", NULL, "RIN2"}, +}; + +static void ak4613_dai_shutdown(struct snd_pcm_substream *substream, +			       struct snd_soc_dai *dai) +{ +	struct snd_soc_codec *codec = dai->codec; +	struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec); +	struct device *dev = codec->dev; + +	mutex_lock(&priv->lock); +	priv->cnt--; +	if (priv->cnt < 0) { +		dev_err(dev, "unexpected counter error\n"); +		priv->cnt = 0; +	} +	if (!priv->cnt) +		priv->fmt_ctrl = NO_FMT; +	mutex_unlock(&priv->lock); +} + +static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ +	struct snd_soc_codec *codec = dai->codec; +	struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec); + +	fmt &= SND_SOC_DAIFMT_FORMAT_MASK; + +	switch (fmt) { +	case SND_SOC_DAIFMT_RIGHT_J: +	case SND_SOC_DAIFMT_LEFT_J: +	case SND_SOC_DAIFMT_I2S: +		priv->fmt = fmt; + +		break; +	default: +		return -EINVAL; +	} + +	return 0; +} + +static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, +				struct snd_pcm_hw_params *params, +				struct snd_soc_dai *dai) +{ +	struct snd_soc_codec *codec = dai->codec; +	struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec); +	const struct ak4613_formats *fmts; +	struct device *dev = codec->dev; +	unsigned int width = params_width(params); +	unsigned int fmt = priv->fmt; +	unsigned int rate; +	int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; +	int i, ret; +	u8 fmt_ctrl, ctrl2; + +	rate = params_rate(params); +	switch (rate) { +	case 32000: +	case 44100: +	case 48000: +		ctrl2 = DFS_NORMAL_SPEED; +		break; +	case 88200: +	case 96000: +		ctrl2 = DFS_DOUBLE_SPEED; +		break; +	case 176400: +	case 192000: +		ctrl2 = DFS_QUAD_SPEED; +		break; +	default: +		return -EINVAL; +	} + +	/* +	 * FIXME +	 * +	 * It doesn't support TDM at this point +	 */ +	fmt_ctrl = NO_FMT; +	for (i = 0; i < ARRAY_SIZE(ak4613_iface); i++) { +		fmts = (is_play) ?	&ak4613_iface[i].playback : +					&ak4613_iface[i].capture; + +		if (fmts->fmt != fmt) +			continue; + +		if (fmt == SND_SOC_DAIFMT_RIGHT_J) { +			if (fmts->width != width) +				continue; +		} else { +			if (fmts->width < width) +				continue; +		} + +		fmt_ctrl = AUDIO_IFACE_IDX_TO_VAL(i); +		break; +	} + +	ret = -EINVAL; +	if (fmt_ctrl == NO_FMT) +		goto hw_params_end; + +	mutex_lock(&priv->lock); +	if ((priv->fmt_ctrl == NO_FMT) || +	    (priv->fmt_ctrl == fmt_ctrl)) { +		priv->fmt_ctrl = fmt_ctrl; +		priv->cnt++; +		ret = 0; +	} +	mutex_unlock(&priv->lock); + +	if (ret < 0) +		goto hw_params_end; + +	snd_soc_update_bits(codec, CTRL1, FMT_MASK, fmt_ctrl); +	snd_soc_write(codec, CTRL2, ctrl2); + +hw_params_end: +	if (ret < 0) +		dev_warn(dev, "unsupported data width/format combination\n"); + +	return ret; +} + +static int ak4613_set_bias_level(struct snd_soc_codec *codec, +				 enum snd_soc_bias_level level) +{ +	u8 mgmt1 = 0; + +	switch (level) { +	case SND_SOC_BIAS_ON: +		mgmt1 |= RSTN; +		/* fall through */ +	case SND_SOC_BIAS_PREPARE: +		mgmt1 |= PMADC | PMDAC; +		/* fall through */ +	case SND_SOC_BIAS_STANDBY: +		mgmt1 |= PMVR; +		/* fall through */ +	case SND_SOC_BIAS_OFF: +	default: +		break; +	} + +	snd_soc_write(codec, PW_MGMT1, mgmt1); + +	return 0; +} + +static const struct snd_soc_dai_ops ak4613_dai_ops = { +	.shutdown	= ak4613_dai_shutdown, +	.set_fmt	= ak4613_dai_set_fmt, +	.hw_params	= ak4613_dai_hw_params, +}; + +#define AK4613_PCM_RATE		(SNDRV_PCM_RATE_32000  |\ +				 SNDRV_PCM_RATE_44100  |\ +				 SNDRV_PCM_RATE_48000  |\ +				 SNDRV_PCM_RATE_64000  |\ +				 SNDRV_PCM_RATE_88200  |\ +				 SNDRV_PCM_RATE_96000  |\ +				 SNDRV_PCM_RATE_176400 |\ +				 SNDRV_PCM_RATE_192000) +#define AK4613_PCM_FMTBIT	(SNDRV_PCM_FMTBIT_S16_LE |\ +				 SNDRV_PCM_FMTBIT_S24_LE) + +static struct snd_soc_dai_driver ak4613_dai = { +	.name = "ak4613-hifi", +	.playback = { +		.stream_name	= "Playback", +		.channels_min	= 2, +		.channels_max	= 2, +		.rates		= AK4613_PCM_RATE, +		.formats	= AK4613_PCM_FMTBIT, +	}, +	.capture = { +		.stream_name	= "Capture", +		.channels_min	= 2, +		.channels_max	= 2, +		.rates		= AK4613_PCM_RATE, +		.formats	= AK4613_PCM_FMTBIT, +	}, +	.ops = &ak4613_dai_ops, +	.symmetric_rates = 1, +}; + +static int ak4613_resume(struct snd_soc_codec *codec) +{ +	struct regmap *regmap = dev_get_regmap(codec->dev, NULL); + +	regcache_mark_dirty(regmap); +	return regcache_sync(regmap); +} + +static struct snd_soc_codec_driver soc_codec_dev_ak4613 = { +	.resume			= ak4613_resume, +	.set_bias_level		= ak4613_set_bias_level, +	.controls		= ak4613_snd_controls, +	.num_controls		= ARRAY_SIZE(ak4613_snd_controls), +	.dapm_widgets		= ak4613_dapm_widgets, +	.num_dapm_widgets	= ARRAY_SIZE(ak4613_dapm_widgets), +	.dapm_routes		= ak4613_intercon, +	.num_dapm_routes	= ARRAY_SIZE(ak4613_intercon), +}; + +static int ak4613_i2c_probe(struct i2c_client *i2c, +			    const struct i2c_device_id *id) +{ +	struct device *dev = &i2c->dev; +	struct device_node *np = dev->of_node; +	const struct regmap_config *regmap_cfg; +	struct regmap *regmap; +	struct ak4613_priv *priv; + +	regmap_cfg = NULL; +	if (np) { +		const struct of_device_id *of_id; + +		of_id = of_match_device(ak4613_of_match, dev); +		if (of_id) +			regmap_cfg = of_id->data; +	} else { +		regmap_cfg = (const struct regmap_config *)id->driver_data; +	} + +	if (!regmap_cfg) +		return -EINVAL; + +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	priv->fmt_ctrl		= NO_FMT; +	priv->cnt		= 0; + +	mutex_init(&priv->lock); + +	i2c_set_clientdata(i2c, priv); + +	regmap = devm_regmap_init_i2c(i2c, regmap_cfg); +	if (IS_ERR(regmap)) +		return PTR_ERR(regmap); + +	return snd_soc_register_codec(dev, &soc_codec_dev_ak4613, +				      &ak4613_dai, 1); +} + +static int ak4613_i2c_remove(struct i2c_client *client) +{ +	snd_soc_unregister_codec(&client->dev); +	return 0; +} + +static struct i2c_driver ak4613_i2c_driver = { +	.driver = { +		.name = "ak4613-codec", +		.owner = THIS_MODULE, +		.of_match_table = ak4613_of_match, +	}, +	.probe		= ak4613_i2c_probe, +	.remove		= ak4613_i2c_remove, +	.id_table	= ak4613_i2c_id, +}; + +module_i2c_driver(ak4613_i2c_driver); + +MODULE_DESCRIPTION("Soc AK4613 driver"); +MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 4a90143d0e90..cda27c22812a 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -23,6 +23,8 @@   * AK4648 is tested.   */ +#include <linux/clk.h> +#include <linux/clk-provider.h>  #include <linux/delay.h>  #include <linux/i2c.h>  #include <linux/slab.h> @@ -128,11 +130,8 @@  #define I2S		(3 << 0)  /* MD_CTL2 */ -#define FS0		(1 << 0) -#define FS1		(1 << 1) -#define FS2		(1 << 2) -#define FS3		(1 << 5) -#define FS_MASK		(FS0 | FS1 | FS2 | FS3) +#define FSs(val)	(((val & 0x7) << 0) | ((val & 0x8) << 2)) +#define PSs(val)	((val & 0x3) << 6)  /* MD_CTL3 */  #define BST1		(1 << 3) @@ -147,6 +146,7 @@ struct ak4642_drvdata {  struct ak4642_priv {  	const struct ak4642_drvdata *drvdata; +	struct clk *mcko;  };  /* @@ -430,56 +430,56 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)  	return 0;  } +static int ak4642_set_mcko(struct snd_soc_codec *codec, +			   u32 frequency) +{ +	u32 fs_list[] = { +		[0] = 8000, +		[1] = 12000, +		[2] = 16000, +		[3] = 24000, +		[4] = 7350, +		[5] = 11025, +		[6] = 14700, +		[7] = 22050, +		[10] = 32000, +		[11] = 48000, +		[14] = 29400, +		[15] = 44100, +	}; +	u32 ps_list[] = { +		[0] = 256, +		[1] = 128, +		[2] = 64, +		[3] = 32 +	}; +	int ps, fs; + +	for (ps = 0; ps < ARRAY_SIZE(ps_list); ps++) { +		for (fs = 0; fs < ARRAY_SIZE(fs_list); fs++) { +			if (frequency == ps_list[ps] * fs_list[fs]) { +				snd_soc_write(codec, MD_CTL2, +					      PSs(ps) | FSs(fs)); +				return 0; +			} +		} +	} + +	return 0; +} +  static int ak4642_dai_hw_params(struct snd_pcm_substream *substream,  				struct snd_pcm_hw_params *params,  				struct snd_soc_dai *dai)  {  	struct snd_soc_codec *codec = dai->codec; -	u8 rate; +	struct ak4642_priv *priv = snd_soc_codec_get_drvdata(codec); +	u32 rate = clk_get_rate(priv->mcko); -	switch (params_rate(params)) { -	case 7350: -		rate = FS2; -		break; -	case 8000: -		rate = 0; -		break; -	case 11025: -		rate = FS2 | FS0; -		break; -	case 12000: -		rate = FS0; -		break; -	case 14700: -		rate = FS2 | FS1; -		break; -	case 16000: -		rate = FS1; -		break; -	case 22050: -		rate = FS2 | FS1 | FS0; -		break; -	case 24000: -		rate = FS1 | FS0; -		break; -	case 29400: -		rate = FS3 | FS2 | FS1; -		break; -	case 32000: -		rate = FS3 | FS1; -		break; -	case 44100: -		rate = FS3 | FS2 | FS1 | FS0; -		break; -	case 48000: -		rate = FS3 | FS1 | FS0; -		break; -	default: -		return -EINVAL; -	} -	snd_soc_update_bits(codec, MD_CTL2, FS_MASK, rate); +	if (!rate) +		rate = params_rate(params) * 256; -	return 0; +	return ak4642_set_mcko(codec, rate);  }  static int ak4642_set_bias_level(struct snd_soc_codec *codec, @@ -532,7 +532,18 @@ static int ak4642_resume(struct snd_soc_codec *codec)  	return 0;  } +static int ak4642_probe(struct snd_soc_codec *codec) +{ +	struct ak4642_priv *priv = snd_soc_codec_get_drvdata(codec); + +	if (priv->mcko) +		ak4642_set_mcko(codec, clk_get_rate(priv->mcko)); + +	return 0; +} +  static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { +	.probe			= ak4642_probe,  	.resume			= ak4642_resume,  	.set_bias_level		= ak4642_set_bias_level,  	.controls		= ak4642_snd_controls, @@ -580,19 +591,54 @@ static const struct ak4642_drvdata ak4648_drvdata = {  	.extended_frequencies = 1,  }; +#ifdef CONFIG_COMMON_CLK +static struct clk *ak4642_of_parse_mcko(struct device *dev) +{ +	struct device_node *np = dev->of_node; +	struct clk *clk; +	const char *clk_name = np->name; +	const char *parent_clk_name = NULL; +	u32 rate; + +	if (of_property_read_u32(np, "clock-frequency", &rate)) +		return NULL; + +	if (of_property_read_bool(np, "clocks")) +		parent_clk_name = of_clk_get_parent_name(np, 0); + +	of_property_read_string(np, "clock-output-names", &clk_name); + +	clk = clk_register_fixed_rate(dev, clk_name, parent_clk_name, +				      (parent_clk_name) ? 0 : CLK_IS_ROOT, +				      rate); +	if (!IS_ERR(clk)) +		of_clk_add_provider(np, of_clk_src_simple_get, clk); + +	return clk; +} +#else +#define ak4642_of_parse_mcko(d) 0 +#endif +  static const struct of_device_id ak4642_of_match[];  static int ak4642_i2c_probe(struct i2c_client *i2c,  			    const struct i2c_device_id *id)  { -	struct device_node *np = i2c->dev.of_node; +	struct device *dev = &i2c->dev; +	struct device_node *np = dev->of_node;  	const struct ak4642_drvdata *drvdata = NULL;  	struct regmap *regmap;  	struct ak4642_priv *priv; +	struct clk *mcko = NULL;  	if (np) {  		const struct of_device_id *of_id; -		of_id = of_match_device(ak4642_of_match, &i2c->dev); +		mcko = ak4642_of_parse_mcko(dev); +		if (IS_ERR(mcko)) +			mcko = NULL; + +		of_id = of_match_device(ak4642_of_match, dev);  		if (of_id)  			drvdata = of_id->data;  	} else { @@ -600,15 +646,16 @@ static int ak4642_i2c_probe(struct i2c_client *i2c,  	}  	if (!drvdata) { -		dev_err(&i2c->dev, "Unknown device type\n"); +		dev_err(dev, "Unknown device type\n");  		return -EINVAL;  	} -	priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);  	if (!priv)  		return -ENOMEM;  	priv->drvdata = drvdata; +	priv->mcko = mcko;  	i2c_set_clientdata(i2c, priv); @@ -616,7 +663,7 @@ static int ak4642_i2c_probe(struct i2c_client *i2c,  	if (IS_ERR(regmap))  		return PTR_ERR(regmap); -	return snd_soc_register_codec(&i2c->dev, +	return snd_soc_register_codec(dev,  				      &soc_codec_dev_ak4642, &ak4642_dai, 1);  } diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 8a2221ab3d10..ac21b85ff75f 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -147,6 +147,8 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w,  						   0x4f5, 0x0da);  		}  		break; +	default: +		break;  	}  	return 0; @@ -689,6 +691,15 @@ static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)  				    ARIZONA_IN_VU, val);  } +bool arizona_input_analog(struct snd_soc_codec *codec, int shift) +{ +	unsigned int reg = ARIZONA_IN1L_CONTROL + ((shift / 2) * 8); +	unsigned int val = snd_soc_read(codec, reg); + +	return !(val & ARIZONA_IN1_MODE_MASK); +} +EXPORT_SYMBOL_GPL(arizona_input_analog); +  int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,  		  int event)  { @@ -725,6 +736,9 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,  		reg = snd_soc_read(codec, ARIZONA_INPUT_ENABLES);  		if (reg == 0)  			arizona_in_set_vu(codec, 0); +		break; +	default: +		break;  	}  	return 0; @@ -806,6 +820,8 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w,  			break;  		}  		break; +	default: +		break;  	}  	return 0; diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index ada0a418ff4b..7b68d05a0939 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -294,4 +294,6 @@ extern int arizona_init_dai(struct arizona_priv *priv, int dai);  int arizona_set_output_mode(struct snd_soc_codec *codec, int output,  			    bool diff); +extern bool arizona_input_analog(struct snd_soc_codec *codec, int shift); +  #endif diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 9756578fc752..c04c0bc6f58a 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -38,6 +38,12 @@  struct wm5110_priv {  	struct arizona_priv core;  	struct arizona_fll fll[2]; + +	unsigned int in_value; +	int in_pre_pending; +	int in_post_pending; + +	unsigned int in_pga_cache[6];  };  static const struct wm_adsp_region wm5110_dsp1_regions[] = { @@ -428,6 +434,127 @@ err:  	return ret;  } +static int wm5110_in_pga_get(struct snd_kcontrol *kcontrol, +			     struct snd_ctl_elem_value *ucontrol) +{ +	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); +	struct snd_soc_card *card = dapm->card; +	int ret; + +	/* +	 * PGA Volume is also used as part of the enable sequence, so +	 * usage of it should be avoided whilst that is running. +	 */ +	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + +	ret = snd_soc_get_volsw_range(kcontrol, ucontrol); + +	mutex_unlock(&card->dapm_mutex); + +	return ret; +} + +static int wm5110_in_pga_put(struct snd_kcontrol *kcontrol, +			     struct snd_ctl_elem_value *ucontrol) +{ +	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); +	struct snd_soc_card *card = dapm->card; +	int ret; + +	/* +	 * PGA Volume is also used as part of the enable sequence, so +	 * usage of it should be avoided whilst that is running. +	 */ +	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + +	ret = snd_soc_put_volsw_range(kcontrol, ucontrol); + +	mutex_unlock(&card->dapm_mutex); + +	return ret; +} + +static int wm5110_in_analog_ev(struct snd_soc_dapm_widget *w, +			       struct snd_kcontrol *kcontrol, int event) +{ +	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); +	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); +	struct wm5110_priv *wm5110 = snd_soc_codec_get_drvdata(codec); +	struct arizona *arizona = priv->arizona; +	unsigned int reg, mask; +	struct reg_sequence analog_seq[] = { +		{ 0x80, 0x3 }, +		{ 0x35d, 0 }, +		{ 0x80, 0x0 }, +	}; + +	reg = ARIZONA_IN1L_CONTROL + ((w->shift ^ 0x1) * 4); +	mask = ARIZONA_IN1L_PGA_VOL_MASK; + +	switch (event) { +	case SND_SOC_DAPM_WILL_PMU: +		wm5110->in_value |= 0x3 << ((w->shift ^ 0x1) * 2); +		wm5110->in_pre_pending++; +		wm5110->in_post_pending++; +		return 0; +	case SND_SOC_DAPM_PRE_PMU: +		wm5110->in_pga_cache[w->shift] = snd_soc_read(codec, reg); + +		snd_soc_update_bits(codec, reg, mask, +				    0x40 << ARIZONA_IN1L_PGA_VOL_SHIFT); + +		wm5110->in_pre_pending--; +		if (wm5110->in_pre_pending == 0) { +			analog_seq[1].def = wm5110->in_value; +			regmap_multi_reg_write_bypassed(arizona->regmap, +							analog_seq, +							ARRAY_SIZE(analog_seq)); + +			msleep(55); + +			wm5110->in_value = 0; +		} + +		break; +	case SND_SOC_DAPM_POST_PMU: +		snd_soc_update_bits(codec, reg, mask, +				    wm5110->in_pga_cache[w->shift]); + +		wm5110->in_post_pending--; +		if (wm5110->in_post_pending == 0) +			regmap_multi_reg_write_bypassed(arizona->regmap, +							analog_seq, +							ARRAY_SIZE(analog_seq)); +		break; +	default: +		break; +	} + +	return 0; +} + +static int wm5110_in_ev(struct snd_soc_dapm_widget *w, +			struct snd_kcontrol *kcontrol, int event) +{ +	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); +	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); +	struct arizona *arizona = priv->arizona; + +	switch (arizona->rev) { +	case 0 ... 4: +		if (arizona_input_analog(codec, w->shift)) +			wm5110_in_analog_ev(w, kcontrol, event); + +		break; +	default: +		break; +	} + +	return arizona_in_ev(w, kcontrol, event); +} +  static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);  static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);  static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); @@ -454,18 +581,24 @@ SOC_ENUM("IN2 OSR", arizona_in_dmic_osr[1]),  SOC_ENUM("IN3 OSR", arizona_in_dmic_osr[2]),  SOC_ENUM("IN4 OSR", arizona_in_dmic_osr[3]), -SOC_SINGLE_RANGE_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL, -		     ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), -SOC_SINGLE_RANGE_TLV("IN1R Volume", ARIZONA_IN1R_CONTROL, -		     ARIZONA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), -SOC_SINGLE_RANGE_TLV("IN2L Volume", ARIZONA_IN2L_CONTROL, -		     ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), -SOC_SINGLE_RANGE_TLV("IN2R Volume", ARIZONA_IN2R_CONTROL, -		     ARIZONA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), -SOC_SINGLE_RANGE_TLV("IN3L Volume", ARIZONA_IN3L_CONTROL, -		     ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), -SOC_SINGLE_RANGE_TLV("IN3R Volume", ARIZONA_IN3R_CONTROL, -		     ARIZONA_IN3R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), +SOC_SINGLE_RANGE_EXT_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL, +			 ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, +			 wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), +SOC_SINGLE_RANGE_EXT_TLV("IN1R Volume", ARIZONA_IN1R_CONTROL, +			 ARIZONA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, +			 wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), +SOC_SINGLE_RANGE_EXT_TLV("IN2L Volume", ARIZONA_IN2L_CONTROL, +			 ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, +			 wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), +SOC_SINGLE_RANGE_EXT_TLV("IN2R Volume", ARIZONA_IN2R_CONTROL, +			 ARIZONA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, +			 wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), +SOC_SINGLE_RANGE_EXT_TLV("IN3L Volume", ARIZONA_IN3L_CONTROL, +			 ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, +			 wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), +SOC_SINGLE_RANGE_EXT_TLV("IN3R Volume", ARIZONA_IN3R_CONTROL, +			 ARIZONA_IN3R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, +			 wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv),  SOC_ENUM("IN HPF Cutoff Frequency", arizona_in_hpf_cut_enum), @@ -896,29 +1029,35 @@ SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"),  SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),  SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, -		   0, NULL, 0, arizona_in_ev, +		   0, NULL, 0, wm5110_in_ev,  		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | -		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | +		   SND_SOC_DAPM_WILL_PMU),  SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, -		   0, NULL, 0, arizona_in_ev, +		   0, NULL, 0, wm5110_in_ev,  		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | -		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | +		   SND_SOC_DAPM_WILL_PMU),  SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, -		   0, NULL, 0, arizona_in_ev, +		   0, NULL, 0, wm5110_in_ev,  		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | -		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | +		   SND_SOC_DAPM_WILL_PMU),  SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, -		   0, NULL, 0, arizona_in_ev, +		   0, NULL, 0, wm5110_in_ev,  		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | -		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | +		   SND_SOC_DAPM_WILL_PMU),  SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, -		   0, NULL, 0, arizona_in_ev, +		   0, NULL, 0, wm5110_in_ev,  		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | -		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | +		   SND_SOC_DAPM_WILL_PMU),  SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, -		   0, NULL, 0, arizona_in_ev, +		   0, NULL, 0, wm5110_in_ev,  		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | -		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | +		   SND_SOC_DAPM_WILL_PMU),  SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT,  		   0, NULL, 0, arizona_in_ev,  		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | 
