Merge remote-tracking branches 'asoc/topic/tas571x', 'asoc/topic/tlv320aic31xx', 'asoc/topic/tpa6130a2', 'asoc/topic/twl6040' and 'asoc/topic/wm8731' into asoc-next
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
index b8d19b7..d8baca3 100644
--- a/sound/soc/codecs/tas571x.c
+++ b/sound/soc/codecs/tas571x.c
@@ -28,6 +28,7 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
+#include <asm/unaligned.h>
 
 #include "tas571x.h"
 
@@ -63,6 +64,10 @@
 	case TAS571X_INPUT_MUX_REG:
 	case TAS571X_CH4_SRC_SELECT_REG:
 	case TAS571X_PWM_MUX_REG:
+	case TAS5717_CH1_RIGHT_CH_MIX_REG:
+	case TAS5717_CH1_LEFT_CH_MIX_REG:
+	case TAS5717_CH2_LEFT_CH_MIX_REG:
+	case TAS5717_CH2_RIGHT_CH_MIX_REG:
 		return 4;
 	default:
 		return 1;
@@ -135,6 +140,129 @@
 	return 0;
 }
 
+/*
+ * register write for 8- and 20-byte registers
+ */
+static int tas571x_reg_write_multiword(struct i2c_client *client,
+		unsigned int reg, const long values[], size_t len)
+{
+	size_t i;
+	uint8_t *buf, *p;
+	int ret;
+	size_t send_size = 1 + len * sizeof(uint32_t);
+
+	buf = kzalloc(send_size, GFP_KERNEL | GFP_DMA);
+	if (!buf)
+		return -ENOMEM;
+	buf[0] = reg;
+
+	for (i = 0, p = buf + 1; i < len; i++, p += sizeof(uint32_t))
+		put_unaligned_be32(values[i], p);
+
+	ret = i2c_master_send(client, buf, send_size);
+
+	kfree(buf);
+
+	if (ret == send_size)
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+/*
+ * register read for 8- and 20-byte registers
+ */
+static int tas571x_reg_read_multiword(struct i2c_client *client,
+		unsigned int reg, long values[], size_t len)
+{
+	unsigned int i;
+	uint8_t send_buf;
+	uint8_t *recv_buf, *p;
+	struct i2c_msg msgs[2];
+	unsigned int recv_size = len * sizeof(uint32_t);
+	int ret;
+
+	recv_buf = kzalloc(recv_size, GFP_KERNEL | GFP_DMA);
+	if (!recv_buf)
+		return -ENOMEM;
+
+	send_buf = reg;
+
+	msgs[0].addr = client->addr;
+	msgs[0].len = sizeof(send_buf);
+	msgs[0].buf = &send_buf;
+	msgs[0].flags = 0;
+
+	msgs[1].addr = client->addr;
+	msgs[1].len = recv_size;
+	msgs[1].buf = recv_buf;
+	msgs[1].flags = I2C_M_RD;
+
+	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+	if (ret < 0)
+		goto err_ret;
+	else if (ret != ARRAY_SIZE(msgs)) {
+		ret = -EIO;
+		goto err_ret;
+	}
+
+	for (i = 0, p = recv_buf; i < len; i++, p += sizeof(uint32_t))
+		values[i] = get_unaligned_be32(p);
+
+err_ret:
+	kfree(recv_buf);
+	return ret;
+}
+
+/*
+ * Integer array controls for setting biquad, mixer, DRC coefficients.
+ * According to the datasheet each coefficient is effectively 26bits,
+ * i.e. stored as 32bits, where bits [31:26] are ignored.
+ * TI's TAS57xx Graphical Development Environment tool however produces
+ * coefficients with more than 26 bits. For this reason we allow values
+ * in the full 32-bits reange.
+ * The coefficients are ordered as given in the TAS571x data sheet:
+ * b0, b1, b2, a1, a2
+ */
+
+static int tas571x_coefficient_info(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_info *uinfo)
+{
+	int numcoef = kcontrol->private_value >> 16;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = numcoef;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 0xffffffff;
+	return 0;
+}
+
+static int tas571x_coefficient_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct i2c_client *i2c = to_i2c_client(codec->dev);
+	int numcoef = kcontrol->private_value >> 16;
+	int index = kcontrol->private_value & 0xffff;
+
+	return tas571x_reg_read_multiword(i2c, index,
+		ucontrol->value.integer.value, numcoef);
+}
+
+static int tas571x_coefficient_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct i2c_client *i2c = to_i2c_client(codec->dev);
+	int numcoef = kcontrol->private_value >> 16;
+	int index = kcontrol->private_value & 0xffff;
+
+	return tas571x_reg_write_multiword(i2c, index,
+		ucontrol->value.integer.value, numcoef);
+}
+
 static int tas571x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)
 {
 	struct tas571x_private *priv = snd_soc_codec_get_drvdata(dai->codec);
@@ -241,6 +369,15 @@
 	.digital_mute	= tas571x_mute,
 };
 
+
+#define BIQUAD_COEFS(xname, reg) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = tas571x_coefficient_info, \
+	.get = tas571x_coefficient_get,\
+	.put = tas571x_coefficient_put, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+	.private_value = reg | (5 << 16) }
+
 static const char *const tas5711_supply_names[] = {
 	"AVDD",
 	"DVDD",
@@ -264,6 +401,16 @@
 		   TAS571X_SOFT_MUTE_REG,
 		   TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
 		   1, 1),
+
+	SOC_DOUBLE_R_RANGE("CH1 Mixer Volume",
+			   TAS5717_CH1_LEFT_CH_MIX_REG,
+			   TAS5717_CH1_RIGHT_CH_MIX_REG,
+			   16, 0, 0x80, 0),
+
+	SOC_DOUBLE_R_RANGE("CH2 Mixer Volume",
+			   TAS5717_CH2_LEFT_CH_MIX_REG,
+			   TAS5717_CH2_RIGHT_CH_MIX_REG,
+			   16, 0, 0x80, 0),
 };
 
 static const struct regmap_range tas571x_readonly_regs_range[] = {
@@ -340,6 +487,43 @@
 		   TAS571X_SOFT_MUTE_REG,
 		   TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
 		   1, 1),
+
+	/*
+	 * The biquads are named according to the register names.
+	 * Please note that TI's TAS57xx Graphical Development Environment
+	 * tool names them different.
+	 */
+	BIQUAD_COEFS("CH1 - Biquad 0", TAS5717_CH1_BQ0_REG),
+	BIQUAD_COEFS("CH1 - Biquad 1", TAS5717_CH1_BQ1_REG),
+	BIQUAD_COEFS("CH1 - Biquad 2", TAS5717_CH1_BQ2_REG),
+	BIQUAD_COEFS("CH1 - Biquad 3", TAS5717_CH1_BQ3_REG),
+	BIQUAD_COEFS("CH1 - Biquad 4", TAS5717_CH1_BQ4_REG),
+	BIQUAD_COEFS("CH1 - Biquad 5", TAS5717_CH1_BQ5_REG),
+	BIQUAD_COEFS("CH1 - Biquad 6", TAS5717_CH1_BQ6_REG),
+	BIQUAD_COEFS("CH1 - Biquad 7", TAS5717_CH1_BQ7_REG),
+	BIQUAD_COEFS("CH1 - Biquad 8", TAS5717_CH1_BQ8_REG),
+	BIQUAD_COEFS("CH1 - Biquad 9", TAS5717_CH1_BQ9_REG),
+	BIQUAD_COEFS("CH1 - Biquad 10", TAS5717_CH1_BQ10_REG),
+	BIQUAD_COEFS("CH1 - Biquad 11", TAS5717_CH1_BQ11_REG),
+
+	BIQUAD_COEFS("CH2 - Biquad 0", TAS5717_CH2_BQ0_REG),
+	BIQUAD_COEFS("CH2 - Biquad 1", TAS5717_CH2_BQ1_REG),
+	BIQUAD_COEFS("CH2 - Biquad 2", TAS5717_CH2_BQ2_REG),
+	BIQUAD_COEFS("CH2 - Biquad 3", TAS5717_CH2_BQ3_REG),
+	BIQUAD_COEFS("CH2 - Biquad 4", TAS5717_CH2_BQ4_REG),
+	BIQUAD_COEFS("CH2 - Biquad 5", TAS5717_CH2_BQ5_REG),
+	BIQUAD_COEFS("CH2 - Biquad 6", TAS5717_CH2_BQ6_REG),
+	BIQUAD_COEFS("CH2 - Biquad 7", TAS5717_CH2_BQ7_REG),
+	BIQUAD_COEFS("CH2 - Biquad 8", TAS5717_CH2_BQ8_REG),
+	BIQUAD_COEFS("CH2 - Biquad 9", TAS5717_CH2_BQ9_REG),
+	BIQUAD_COEFS("CH2 - Biquad 10", TAS5717_CH2_BQ10_REG),
+	BIQUAD_COEFS("CH2 - Biquad 11", TAS5717_CH2_BQ11_REG),
+
+	BIQUAD_COEFS("CH3 - Biquad 0", TAS5717_CH3_BQ0_REG),
+	BIQUAD_COEFS("CH3 - Biquad 1", TAS5717_CH3_BQ1_REG),
+
+	BIQUAD_COEFS("CH4 - Biquad 0", TAS5717_CH4_BQ0_REG),
+	BIQUAD_COEFS("CH4 - Biquad 1", TAS5717_CH4_BQ1_REG),
 };
 
 static const struct reg_default tas5717_reg_defaults[] = {
@@ -350,6 +534,10 @@
 	{ 0x08, 0x00c0 },
 	{ 0x09, 0x00c0 },
 	{ 0x1b, 0x82 },
+	{ TAS5717_CH1_RIGHT_CH_MIX_REG, 0x0 },
+	{ TAS5717_CH1_LEFT_CH_MIX_REG, 0x800000},
+	{ TAS5717_CH2_LEFT_CH_MIX_REG, 0x0 },
+	{ TAS5717_CH2_RIGHT_CH_MIX_REG, 0x800000},
 };
 
 static const struct regmap_config tas5717_regmap_config = {
diff --git a/sound/soc/codecs/tas571x.h b/sound/soc/codecs/tas571x.h
index cf800c3..c45677b 100644
--- a/sound/soc/codecs/tas571x.h
+++ b/sound/soc/codecs/tas571x.h
@@ -52,4 +52,44 @@
 #define TAS571X_CH4_SRC_SELECT_REG	0x21
 #define TAS571X_PWM_MUX_REG		0x25
 
+/* 20-byte biquad registers */
+#define TAS5717_CH1_BQ0_REG		0x26
+#define TAS5717_CH1_BQ1_REG		0x27
+#define TAS5717_CH1_BQ2_REG		0x28
+#define TAS5717_CH1_BQ3_REG		0x29
+#define TAS5717_CH1_BQ4_REG		0x2a
+#define TAS5717_CH1_BQ5_REG		0x2b
+#define TAS5717_CH1_BQ6_REG		0x2c
+#define TAS5717_CH1_BQ7_REG		0x2d
+#define TAS5717_CH1_BQ8_REG		0x2e
+#define TAS5717_CH1_BQ9_REG		0x2f
+
+#define TAS5717_CH2_BQ0_REG		0x30
+#define TAS5717_CH2_BQ1_REG		0x31
+#define TAS5717_CH2_BQ2_REG		0x32
+#define TAS5717_CH2_BQ3_REG		0x33
+#define TAS5717_CH2_BQ4_REG		0x34
+#define TAS5717_CH2_BQ5_REG		0x35
+#define TAS5717_CH2_BQ6_REG		0x36
+#define TAS5717_CH2_BQ7_REG		0x37
+#define TAS5717_CH2_BQ8_REG		0x38
+#define TAS5717_CH2_BQ9_REG		0x39
+
+#define TAS5717_CH1_BQ10_REG		0x58
+#define TAS5717_CH1_BQ11_REG		0x59
+
+#define TAS5717_CH4_BQ0_REG		0x5a
+#define TAS5717_CH4_BQ1_REG		0x5b
+
+#define TAS5717_CH2_BQ10_REG		0x5c
+#define TAS5717_CH2_BQ11_REG		0x5d
+
+#define TAS5717_CH3_BQ0_REG		0x5e
+#define TAS5717_CH3_BQ1_REG		0x5f
+
+#define TAS5717_CH1_RIGHT_CH_MIX_REG	0x72
+#define TAS5717_CH1_LEFT_CH_MIX_REG	0x73
+#define TAS5717_CH2_LEFT_CH_MIX_REG	0x76
+#define TAS5717_CH2_RIGHT_CH_MIX_REG	0x77
+
 #endif /* _TAS571X_H */
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h
index fe16c34..ac9b146 100644
--- a/sound/soc/codecs/tlv320aic31xx.h
+++ b/sound/soc/codecs/tlv320aic31xx.h
@@ -38,141 +38,143 @@
 	int micbias_vg;
 };
 
+#define AIC31XX_REG(page, reg)	((page * 128) + reg)
+
 /* Page Control Register */
-#define AIC31XX_PAGECTL				0x00
+#define AIC31XX_PAGECTL		AIC31XX_REG(0, 0)
 
 /* Page 0 Registers */
 /* Software reset register */
-#define AIC31XX_RESET				0x01
+#define AIC31XX_RESET		AIC31XX_REG(0, 1)
 /* OT FLAG register */
-#define AIC31XX_OT_FLAG				0x03
+#define AIC31XX_OT_FLAG		AIC31XX_REG(0, 3)
 /* Clock clock Gen muxing, Multiplexers*/
-#define AIC31XX_CLKMUX				0x04
+#define AIC31XX_CLKMUX		AIC31XX_REG(0, 4)
 /* PLL P and R-VAL register */
-#define AIC31XX_PLLPR				0x05
+#define AIC31XX_PLLPR		AIC31XX_REG(0, 5)
 /* PLL J-VAL register */
-#define AIC31XX_PLLJ				0x06
+#define AIC31XX_PLLJ		AIC31XX_REG(0, 6)
 /* PLL D-VAL MSB register */
-#define AIC31XX_PLLDMSB				0x07
+#define AIC31XX_PLLDMSB		AIC31XX_REG(0, 7)
 /* PLL D-VAL LSB register */
-#define AIC31XX_PLLDLSB				0x08
+#define AIC31XX_PLLDLSB		AIC31XX_REG(0, 8)
 /* DAC NDAC_VAL register*/
-#define AIC31XX_NDAC				0x0B
+#define AIC31XX_NDAC		AIC31XX_REG(0, 11)
 /* DAC MDAC_VAL register */
-#define AIC31XX_MDAC				0x0C
+#define AIC31XX_MDAC		AIC31XX_REG(0, 12)
 /* DAC OSR setting register 1, MSB value */
-#define AIC31XX_DOSRMSB				0x0D
+#define AIC31XX_DOSRMSB		AIC31XX_REG(0, 13)
 /* DAC OSR setting register 2, LSB value */
-#define AIC31XX_DOSRLSB				0x0E
-#define AIC31XX_MINI_DSP_INPOL			0x10
+#define AIC31XX_DOSRLSB		AIC31XX_REG(0, 14)
+#define AIC31XX_MINI_DSP_INPOL	AIC31XX_REG(0, 16)
 /* Clock setting register 8, PLL */
-#define AIC31XX_NADC				0x12
+#define AIC31XX_NADC		AIC31XX_REG(0, 18)
 /* Clock setting register 9, PLL */
-#define AIC31XX_MADC				0x13
+#define AIC31XX_MADC		AIC31XX_REG(0, 19)
 /* ADC Oversampling (AOSR) Register */
-#define AIC31XX_AOSR				0x14
+#define AIC31XX_AOSR		AIC31XX_REG(0, 20)
 /* Clock setting register 9, Multiplexers */
-#define AIC31XX_CLKOUTMUX			0x19
+#define AIC31XX_CLKOUTMUX	AIC31XX_REG(0, 25)
 /* Clock setting register 10, CLOCKOUT M divider value */
-#define AIC31XX_CLKOUTMVAL			0x1A
+#define AIC31XX_CLKOUTMVAL	AIC31XX_REG(0, 26)
 /* Audio Interface Setting Register 1 */
-#define AIC31XX_IFACE1				0x1B
+#define AIC31XX_IFACE1		AIC31XX_REG(0, 27)
 /* Audio Data Slot Offset Programming */
-#define AIC31XX_DATA_OFFSET			0x1C
+#define AIC31XX_DATA_OFFSET	AIC31XX_REG(0, 28)
 /* Audio Interface Setting Register 2 */
-#define AIC31XX_IFACE2				0x1D
+#define AIC31XX_IFACE2		AIC31XX_REG(0, 29)
 /* Clock setting register 11, BCLK N Divider */
-#define AIC31XX_BCLKN				0x1E
+#define AIC31XX_BCLKN		AIC31XX_REG(0, 30)
 /* Audio Interface Setting Register 3, Secondary Audio Interface */
-#define AIC31XX_IFACESEC1			0x1F
+#define AIC31XX_IFACESEC1	AIC31XX_REG(0, 31)
 /* Audio Interface Setting Register 4 */
-#define AIC31XX_IFACESEC2			0x20
+#define AIC31XX_IFACESEC2	AIC31XX_REG(0, 32)
 /* Audio Interface Setting Register 5 */
-#define AIC31XX_IFACESEC3			0x21
+#define AIC31XX_IFACESEC3	AIC31XX_REG(0, 33)
 /* I2C Bus Condition */
-#define AIC31XX_I2C				0x22
+#define AIC31XX_I2C		AIC31XX_REG(0, 34)
 /* ADC FLAG */
-#define AIC31XX_ADCFLAG				0x24
+#define AIC31XX_ADCFLAG		AIC31XX_REG(0, 36)
 /* DAC Flag Registers */
-#define AIC31XX_DACFLAG1			0x25
-#define AIC31XX_DACFLAG2			0x26
+#define AIC31XX_DACFLAG1	AIC31XX_REG(0, 37)
+#define AIC31XX_DACFLAG2	AIC31XX_REG(0, 38)
 /* Sticky Interrupt flag (overflow) */
-#define AIC31XX_OFFLAG				0x27
+#define AIC31XX_OFFLAG		AIC31XX_REG(0, 39)
 /* Sticy DAC Interrupt flags */
-#define AIC31XX_INTRDACFLAG			0x2C
+#define AIC31XX_INTRDACFLAG	AIC31XX_REG(0, 44)
 /* Sticy ADC Interrupt flags */
-#define AIC31XX_INTRADCFLAG			0x2D
+#define AIC31XX_INTRADCFLAG	AIC31XX_REG(0, 45)
 /* DAC Interrupt flags 2 */
-#define AIC31XX_INTRDACFLAG2			0x2E
+#define AIC31XX_INTRDACFLAG2	AIC31XX_REG(0, 46)
 /* ADC Interrupt flags 2 */
-#define AIC31XX_INTRADCFLAG2			0x2F
+#define AIC31XX_INTRADCFLAG2	AIC31XX_REG(0, 47)
 /* INT1 interrupt control */
-#define AIC31XX_INT1CTRL			0x30
+#define AIC31XX_INT1CTRL	AIC31XX_REG(0, 48)
 /* INT2 interrupt control */
-#define AIC31XX_INT2CTRL			0x31
+#define AIC31XX_INT2CTRL	AIC31XX_REG(0, 49)
 /* GPIO1 control */
-#define AIC31XX_GPIO1				0x33
+#define AIC31XX_GPIO1		AIC31XX_REG(0, 50)
 
-#define AIC31XX_DACPRB				0x3C
+#define AIC31XX_DACPRB		AIC31XX_REG(0, 60)
 /* ADC Instruction Set Register */
-#define AIC31XX_ADCPRB				0x3D
+#define AIC31XX_ADCPRB		AIC31XX_REG(0, 61)
 /* DAC channel setup register */
-#define AIC31XX_DACSETUP			0x3F
+#define AIC31XX_DACSETUP	AIC31XX_REG(0, 63)
 /* DAC Mute and volume control register */
-#define AIC31XX_DACMUTE				0x40
+#define AIC31XX_DACMUTE		AIC31XX_REG(0, 64)
 /* Left DAC channel digital volume control */
-#define AIC31XX_LDACVOL				0x41
+#define AIC31XX_LDACVOL		AIC31XX_REG(0, 65)
 /* Right DAC channel digital volume control */
-#define AIC31XX_RDACVOL				0x42
+#define AIC31XX_RDACVOL		AIC31XX_REG(0, 66)
 /* Headset detection */
-#define AIC31XX_HSDETECT			0x43
+#define AIC31XX_HSDETECT	AIC31XX_REG(0, 67)
 /* ADC Digital Mic */
-#define AIC31XX_ADCSETUP			0x51
+#define AIC31XX_ADCSETUP	AIC31XX_REG(0, 81)
 /* ADC Digital Volume Control Fine Adjust */
-#define AIC31XX_ADCFGA				0x52
+#define AIC31XX_ADCFGA		AIC31XX_REG(0, 82)
 /* ADC Digital Volume Control Coarse Adjust */
-#define AIC31XX_ADCVOL				0x53
+#define AIC31XX_ADCVOL		AIC31XX_REG(0, 83)
 
 
 /* Page 1 Registers */
 /* Headphone drivers */
-#define AIC31XX_HPDRIVER			0x9F
+#define AIC31XX_HPDRIVER	AIC31XX_REG(1, 31)
 /* Class-D Speakear Amplifier */
-#define AIC31XX_SPKAMP				0xA0
+#define AIC31XX_SPKAMP		AIC31XX_REG(1, 32)
 /* HP Output Drivers POP Removal Settings */
-#define AIC31XX_HPPOP				0xA1
+#define AIC31XX_HPPOP		AIC31XX_REG(1, 33)
 /* Output Driver PGA Ramp-Down Period Control */
-#define AIC31XX_SPPGARAMP			0xA2
+#define AIC31XX_SPPGARAMP	AIC31XX_REG(1, 34)
 /* DAC_L and DAC_R Output Mixer Routing */
-#define AIC31XX_DACMIXERROUTE			0xA3
+#define AIC31XX_DACMIXERROUTE	AIC31XX_REG(1, 35)
 /* Left Analog Vol to HPL */
-#define AIC31XX_LANALOGHPL			0xA4
+#define AIC31XX_LANALOGHPL	AIC31XX_REG(1, 36)
 /* Right Analog Vol to HPR */
-#define AIC31XX_RANALOGHPR			0xA5
+#define AIC31XX_RANALOGHPR	AIC31XX_REG(1, 37)
 /* Left Analog Vol to SPL */
-#define AIC31XX_LANALOGSPL			0xA6
+#define AIC31XX_LANALOGSPL	AIC31XX_REG(1, 38)
 /* Right Analog Vol to SPR */
-#define AIC31XX_RANALOGSPR			0xA7
+#define AIC31XX_RANALOGSPR	AIC31XX_REG(1, 39)
 /* HPL Driver */
-#define AIC31XX_HPLGAIN				0xA8
+#define AIC31XX_HPLGAIN		AIC31XX_REG(1, 40)
 /* HPR Driver */
-#define AIC31XX_HPRGAIN				0xA9
+#define AIC31XX_HPRGAIN		AIC31XX_REG(1, 41)
 /* SPL Driver */
-#define AIC31XX_SPLGAIN				0xAA
+#define AIC31XX_SPLGAIN		AIC31XX_REG(1, 42)
 /* SPR Driver */
-#define AIC31XX_SPRGAIN				0xAB
+#define AIC31XX_SPRGAIN		AIC31XX_REG(1, 43)
 /* HP Driver Control */
-#define AIC31XX_HPCONTROL			0xAC
+#define AIC31XX_HPCONTROL	AIC31XX_REG(1, 44)
 /* MIC Bias Control */
-#define AIC31XX_MICBIAS				0xAE
+#define AIC31XX_MICBIAS		AIC31XX_REG(1, 46)
 /* MIC PGA*/
-#define AIC31XX_MICPGA				0xAF
+#define AIC31XX_MICPGA		AIC31XX_REG(1, 47)
 /* Delta-Sigma Mono ADC Channel Fine-Gain Input Selection for P-Terminal */
-#define AIC31XX_MICPGAPI			0xB0
+#define AIC31XX_MICPGAPI	AIC31XX_REG(1, 48)
 /* ADC Input Selection for M-Terminal */
-#define AIC31XX_MICPGAMI			0xB1
+#define AIC31XX_MICPGAMI	AIC31XX_REG(1, 49)
 /* Input CM Settings */
-#define AIC31XX_MICPGACM			0xB2
+#define AIC31XX_MICPGACM	AIC31XX_REG(1, 50)
 
 /* Bits, masks and shifts */
 
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 11d85c5..f1ea052 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -32,6 +32,7 @@
 #include <sound/tlv.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/regmap.h>
 
 #include "tpa6130a2.h"
 
@@ -40,219 +41,72 @@
 	TPA6140A2,
 };
 
-static struct i2c_client *tpa6130a2_client;
-
 /* This struct is used to save the context */
 struct tpa6130a2_data {
-	struct mutex mutex;
-	unsigned char regs[TPA6130A2_CACHEREGNUM];
+	struct device *dev;
+	struct regmap *regmap;
 	struct regulator *supply;
 	int power_gpio;
-	u8 power_state:1;
 	enum tpa_model id;
 };
 
-static int tpa6130a2_i2c_read(int reg)
+static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable)
 {
-	struct tpa6130a2_data *data;
-	int val;
+	int ret;
 
-	if (WARN_ON(!tpa6130a2_client))
-		return -EINVAL;
-	data = i2c_get_clientdata(tpa6130a2_client);
-
-	/* If powered off, return the cached value */
-	if (data->power_state) {
-		val = i2c_smbus_read_byte_data(tpa6130a2_client, reg);
-		if (val < 0)
-			dev_err(&tpa6130a2_client->dev, "Read failed\n");
-		else
-			data->regs[reg] = val;
-	} else {
-		val = data->regs[reg];
-	}
-
-	return val;
-}
-
-static int tpa6130a2_i2c_write(int reg, u8 value)
-{
-	struct tpa6130a2_data *data;
-	int val = 0;
-
-	if (WARN_ON(!tpa6130a2_client))
-		return -EINVAL;
-	data = i2c_get_clientdata(tpa6130a2_client);
-
-	if (data->power_state) {
-		val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value);
-		if (val < 0) {
-			dev_err(&tpa6130a2_client->dev, "Write failed\n");
-			return val;
-		}
-	}
-
-	/* Either powered on or off, we save the context */
-	data->regs[reg] = value;
-
-	return val;
-}
-
-static u8 tpa6130a2_read(int reg)
-{
-	struct tpa6130a2_data *data;
-
-	if (WARN_ON(!tpa6130a2_client))
-		return 0;
-	data = i2c_get_clientdata(tpa6130a2_client);
-
-	return data->regs[reg];
-}
-
-static int tpa6130a2_initialize(void)
-{
-	struct tpa6130a2_data *data;
-	int i, ret = 0;
-
-	if (WARN_ON(!tpa6130a2_client))
-		return -EINVAL;
-	data = i2c_get_clientdata(tpa6130a2_client);
-
-	for (i = 1; i < TPA6130A2_REG_VERSION; i++) {
-		ret = tpa6130a2_i2c_write(i, data->regs[i]);
-		if (ret < 0)
-			break;
-	}
-
-	return ret;
-}
-
-static int tpa6130a2_power(u8 power)
-{
-	struct	tpa6130a2_data *data;
-	u8	val;
-	int	ret = 0;
-
-	if (WARN_ON(!tpa6130a2_client))
-		return -EINVAL;
-	data = i2c_get_clientdata(tpa6130a2_client);
-
-	mutex_lock(&data->mutex);
-	if (power == data->power_state)
-		goto exit;
-
-	if (power) {
+	if (enable) {
 		ret = regulator_enable(data->supply);
 		if (ret != 0) {
-			dev_err(&tpa6130a2_client->dev,
+			dev_err(data->dev,
 				"Failed to enable supply: %d\n", ret);
-			goto exit;
+			return ret;
 		}
 		/* Power on */
 		if (data->power_gpio >= 0)
 			gpio_set_value(data->power_gpio, 1);
-
-		data->power_state = 1;
-		ret = tpa6130a2_initialize();
-		if (ret < 0) {
-			dev_err(&tpa6130a2_client->dev,
-				"Failed to initialize chip\n");
-			if (data->power_gpio >= 0)
-				gpio_set_value(data->power_gpio, 0);
-			regulator_disable(data->supply);
-			data->power_state = 0;
-			goto exit;
-		}
 	} else {
-		/* set SWS */
-		val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
-		val |= TPA6130A2_SWS;
-		tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
-
 		/* Power off */
 		if (data->power_gpio >= 0)
 			gpio_set_value(data->power_gpio, 0);
 
 		ret = regulator_disable(data->supply);
 		if (ret != 0) {
-			dev_err(&tpa6130a2_client->dev,
+			dev_err(data->dev,
 				"Failed to disable supply: %d\n", ret);
-			goto exit;
+			return ret;
 		}
 
-		data->power_state = 0;
+		/* device regs does not match the cache state anymore */
+		regcache_mark_dirty(data->regmap);
 	}
 
-exit:
-	mutex_unlock(&data->mutex);
 	return ret;
 }
 
-static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol,
-		struct snd_ctl_elem_value *ucontrol)
+static int tpa6130a2_power_event(struct snd_soc_dapm_widget *w,
+				 struct snd_kcontrol *kctrl, int event)
 {
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
-	struct tpa6130a2_data *data;
-	unsigned int reg = mc->reg;
-	unsigned int shift = mc->shift;
-	int max = mc->max;
-	unsigned int mask = (1 << fls(max)) - 1;
-	unsigned int invert = mc->invert;
+	struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
+	struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c);
+	int ret;
 
-	if (WARN_ON(!tpa6130a2_client))
-		return -EINVAL;
-	data = i2c_get_clientdata(tpa6130a2_client);
-
-	mutex_lock(&data->mutex);
-
-	ucontrol->value.integer.value[0] =
-		(tpa6130a2_read(reg) >> shift) & mask;
-
-	if (invert)
-		ucontrol->value.integer.value[0] =
-			max - ucontrol->value.integer.value[0];
-
-	mutex_unlock(&data->mutex);
-	return 0;
-}
-
-static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol,
-		struct snd_ctl_elem_value *ucontrol)
-{
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
-	struct tpa6130a2_data *data;
-	unsigned int reg = mc->reg;
-	unsigned int shift = mc->shift;
-	int max = mc->max;
-	unsigned int mask = (1 << fls(max)) - 1;
-	unsigned int invert = mc->invert;
-	unsigned int val = (ucontrol->value.integer.value[0] & mask);
-	unsigned int val_reg;
-
-	if (WARN_ON(!tpa6130a2_client))
-		return -EINVAL;
-	data = i2c_get_clientdata(tpa6130a2_client);
-
-	if (invert)
-		val = max - val;
-
-	mutex_lock(&data->mutex);
-
-	val_reg = tpa6130a2_read(reg);
-	if (((val_reg >> shift) & mask) == val) {
-		mutex_unlock(&data->mutex);
-		return 0;
+	/* before widget power up */
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Turn on the chip */
+		tpa6130a2_power(data, true);
+		/* Sync the registers */
+		ret = regcache_sync(data->regmap);
+		if (ret < 0) {
+			dev_err(c->dev, "Failed to initialize chip\n");
+			tpa6130a2_power(data, false);
+			return ret;
+		}
+	/* after widget power down */
+	} else {
+		tpa6130a2_power(data, false);
 	}
 
-	val_reg &= ~(mask << shift);
-	val_reg |= val << shift;
-	tpa6130a2_i2c_write(reg, val_reg);
-
-	mutex_unlock(&data->mutex);
-
-	return 1;
+	return 0;
 }
 
 /*
@@ -273,9 +127,8 @@
 );
 
 static const struct snd_kcontrol_new tpa6130a2_controls[] = {
-	SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume",
+	SOC_SINGLE_TLV("Headphone Playback Volume",
 		       TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0,
-		       tpa6130a2_get_volsw, tpa6130a2_put_volsw,
 		       tpa6130_tlv),
 };
 
@@ -286,85 +139,79 @@
 );
 
 static const struct snd_kcontrol_new tpa6140a2_controls[] = {
-	SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume",
+	SOC_SINGLE_TLV("Headphone Playback Volume",
 		       TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0,
-		       tpa6130a2_get_volsw, tpa6130a2_put_volsw,
 		       tpa6140_tlv),
 };
 
-/*
- * Enable or disable channel (left or right)
- * The bit number for mute and amplifier are the same per channel:
- * bit 6: Right channel
- * bit 7: Left channel
- * in both registers.
- */
-static void tpa6130a2_channel_enable(u8 channel, int enable)
+static int tpa6130a2_component_probe(struct snd_soc_component *component)
 {
-	u8	val;
-
-	if (enable) {
-		/* Enable channel */
-		/* Enable amplifier */
-		val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
-		val |= channel;
-		val &= ~TPA6130A2_SWS;
-		tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
-
-		/* Unmute channel */
-		val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE);
-		val &= ~channel;
-		tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val);
-	} else {
-		/* Disable channel */
-		/* Mute channel */
-		val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE);
-		val |= channel;
-		tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val);
-
-		/* Disable amplifier */
-		val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
-		val &= ~channel;
-		tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
-	}
-}
-
-int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable)
-{
-	int ret = 0;
-	if (enable) {
-		ret = tpa6130a2_power(1);
-		if (ret < 0)
-			return ret;
-		tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L,
-					 1);
-	} else {
-		tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L,
-					 0);
-		ret = tpa6130a2_power(0);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
-
-int tpa6130a2_add_controls(struct snd_soc_codec *codec)
-{
-	struct	tpa6130a2_data *data;
-
-	if (tpa6130a2_client == NULL)
-		return -ENODEV;
-
-	data = i2c_get_clientdata(tpa6130a2_client);
+	struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component);
 
 	if (data->id == TPA6140A2)
-		return snd_soc_add_codec_controls(codec, tpa6140a2_controls,
-						ARRAY_SIZE(tpa6140a2_controls));
+		return snd_soc_add_component_controls(component,
+			tpa6140a2_controls, ARRAY_SIZE(tpa6140a2_controls));
 	else
-		return snd_soc_add_codec_controls(codec, tpa6130a2_controls,
-						ARRAY_SIZE(tpa6130a2_controls));
+		return snd_soc_add_component_controls(component,
+			tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls));
 }
-EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
+
+static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
+	SND_SOC_DAPM_INPUT("LEFTIN"),
+	SND_SOC_DAPM_INPUT("RIGHTIN"),
+	SND_SOC_DAPM_OUTPUT("HPLEFT"),
+	SND_SOC_DAPM_OUTPUT("HPRIGHT"),
+
+	SND_SOC_DAPM_PGA("Left Mute", TPA6130A2_REG_VOL_MUTE,
+			 TPA6130A2_HP_EN_L_SHIFT, 1, NULL, 0),
+	SND_SOC_DAPM_PGA("Right Mute", TPA6130A2_REG_VOL_MUTE,
+			 TPA6130A2_HP_EN_R_SHIFT, 1, NULL, 0),
+	SND_SOC_DAPM_PGA("Left PGA", TPA6130A2_REG_CONTROL,
+			 TPA6130A2_HP_EN_L_SHIFT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Right PGA", TPA6130A2_REG_CONTROL,
+			 TPA6130A2_HP_EN_R_SHIFT, 0, NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY("Power", TPA6130A2_REG_CONTROL,
+			    TPA6130A2_SWS_SHIFT, 1, tpa6130a2_power_event,
+			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = {
+	{ "Left PGA", NULL, "LEFTIN" },
+	{ "Right PGA", NULL, "RIGHTIN" },
+
+	{ "Left Mute", NULL, "Left PGA" },
+	{ "Right Mute", NULL, "Right PGA" },
+
+	{ "HPLEFT", NULL, "Left Mute" },
+	{ "HPRIGHT", NULL, "Right Mute" },
+
+	{ "Left PGA", NULL, "Power" },
+	{ "Right PGA", NULL, "Power" },
+};
+
+struct snd_soc_component_driver tpa6130a2_component_driver = {
+	.name = "tpa6130a2",
+	.probe = tpa6130a2_component_probe,
+	.dapm_widgets = tpa6130a2_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tpa6130a2_dapm_widgets),
+	.dapm_routes = tpa6130a2_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(tpa6130a2_dapm_routes),
+};
+
+static const struct reg_default tpa6130a2_reg_defaults[] = {
+	{ TPA6130A2_REG_CONTROL, TPA6130A2_SWS },
+	{ TPA6130A2_REG_VOL_MUTE, TPA6130A2_MUTE_R | TPA6130A2_MUTE_L },
+};
+
+static const struct regmap_config tpa6130a2_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = TPA6130A2_REG_VERSION,
+	.reg_defaults = tpa6130a2_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(tpa6130a2_reg_defaults),
+	.cache_type = REGCACHE_RBTREE,
+};
 
 static int tpa6130a2_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
@@ -374,6 +221,7 @@
 	struct tpa6130a2_platform_data *pdata = client->dev.platform_data;
 	struct device_node *np = client->dev.of_node;
 	const char *regulator;
+	unsigned int version;
 	int ret;
 
 	dev = &client->dev;
@@ -382,6 +230,12 @@
 	if (!data)
 		return -ENOMEM;
 
+	data->dev = dev;
+
+	data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config);
+	if (IS_ERR(data->regmap))
+		return PTR_ERR(data->regmap);
+
 	if (pdata) {
 		data->power_gpio = pdata->power_gpio;
 	} else if (np) {
@@ -392,26 +246,17 @@
 		return -ENODEV;
 	}
 
-	tpa6130a2_client = client;
-
-	i2c_set_clientdata(tpa6130a2_client, data);
+	i2c_set_clientdata(client, data);
 
 	data->id = id->driver_data;
 
-	mutex_init(&data->mutex);
-
-	/* Set default register values */
-	data->regs[TPA6130A2_REG_CONTROL] =	TPA6130A2_SWS;
-	data->regs[TPA6130A2_REG_VOL_MUTE] =	TPA6130A2_MUTE_R |
-						TPA6130A2_MUTE_L;
-
 	if (data->power_gpio >= 0) {
 		ret = devm_gpio_request(dev, data->power_gpio,
 					"tpa6130a2 enable");
 		if (ret < 0) {
 			dev_err(dev, "Failed to request power GPIO (%d)\n",
 				data->power_gpio);
-			goto err_gpio;
+			return ret;
 		}
 		gpio_direction_output(data->power_gpio, 0);
 	}
@@ -432,39 +277,27 @@
 	if (IS_ERR(data->supply)) {
 		ret = PTR_ERR(data->supply);
 		dev_err(dev, "Failed to request supply: %d\n", ret);
-		goto err_gpio;
+		return ret;
 	}
 
-	ret = tpa6130a2_power(1);
+	ret = tpa6130a2_power(data, true);
 	if (ret != 0)
-		goto err_gpio;
+		return ret;
 
 
 	/* Read version */
-	ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
-				 TPA6130A2_VERSION_MASK;
-	if ((ret != 1) && (ret != 2))
-		dev_warn(dev, "UNTESTED version detected (%d)\n", ret);
+	regmap_read(data->regmap, TPA6130A2_REG_VERSION, &version);
+	version &= TPA6130A2_VERSION_MASK;
+	if ((version != 1) && (version != 2))
+		dev_warn(dev, "UNTESTED version detected (%d)\n", version);
 
 	/* Disable the chip */
-	ret = tpa6130a2_power(0);
+	ret = tpa6130a2_power(data, false);
 	if (ret != 0)
-		goto err_gpio;
+		return ret;
 
-	return 0;
-
-err_gpio:
-	tpa6130a2_client = NULL;
-
-	return ret;
-}
-
-static int tpa6130a2_remove(struct i2c_client *client)
-{
-	tpa6130a2_power(0);
-	tpa6130a2_client = NULL;
-
-	return 0;
+	return devm_snd_soc_register_component(&client->dev,
+			&tpa6130a2_component_driver, NULL, 0);
 }
 
 static const struct i2c_device_id tpa6130a2_id[] = {
@@ -489,7 +322,6 @@
 		.of_match_table = of_match_ptr(tpa6130a2_of_match),
 	},
 	.probe = tpa6130a2_probe,
-	.remove = tpa6130a2_remove,
 	.id_table = tpa6130a2_id,
 };
 
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h
index 4174440..f19cad5 100644
--- a/sound/soc/codecs/tpa6130a2.h
+++ b/sound/soc/codecs/tpa6130a2.h
@@ -30,19 +30,20 @@
 #define TPA6130A2_REG_OUT_IMPEDANCE	0x03
 #define TPA6130A2_REG_VERSION		0x04
 
-#define TPA6130A2_CACHEREGNUM	(TPA6130A2_REG_VERSION + 1)
-
 /* Register bits */
 /* TPA6130A2_REG_CONTROL (0x01) */
-#define TPA6130A2_SWS			(0x01 << 0)
+#define TPA6130A2_SWS_SHIFT		0
+#define TPA6130A2_SWS			(0x01 << TPA6130A2_SWS_SHIFT)
 #define TPA6130A2_TERMAL		(0x01 << 1)
 #define TPA6130A2_MODE(x)		(x << 4)
 #define TPA6130A2_MODE_STEREO		(0x00)
 #define TPA6130A2_MODE_DUAL_MONO	(0x01)
 #define TPA6130A2_MODE_BRIDGE		(0x02)
 #define TPA6130A2_MODE_MASK		(0x03)
-#define TPA6130A2_HP_EN_R		(0x01 << 6)
-#define TPA6130A2_HP_EN_L		(0x01 << 7)
+#define TPA6130A2_HP_EN_R_SHIFT		6
+#define TPA6130A2_HP_EN_R		(0x01 << TPA6130A2_HP_EN_R_SHIFT)
+#define TPA6130A2_HP_EN_L_SHIFT		7
+#define TPA6130A2_HP_EN_L		(0x01 << TPA6130A2_HP_EN_L_SHIFT)
 
 /* TPA6130A2_REG_VOL_MUTE (0x02) */
 #define TPA6130A2_VOLUME(x)		((x & 0x3f) << 0)
@@ -56,7 +57,4 @@
 /* TPA6130A2_REG_VERSION (0x04) */
 #define TPA6130A2_VERSION_MASK		(0x0f)
 
-extern int tpa6130a2_add_controls(struct snd_soc_codec *codec);
-extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable);
-
 #endif /* __TPA6130A2_H__ */
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 4bcf5f8..d18261a 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -358,6 +358,9 @@
 	case 24:
 		iface |= 0x0008;
 		break;
+	case 32:
+		iface |= 0x000c;
+		break;
 	}
 
 	wm8731_set_deemph(codec);
@@ -541,7 +544,7 @@
 #define WM8731_RATES SNDRV_PCM_RATE_8000_96000
 
 #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
-	SNDRV_PCM_FMTBIT_S24_LE)
+	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 static const struct snd_soc_dai_ops wm8731_dai_ops = {
 	.startup	= wm8731_startup,
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 5c471d9..f5451c7 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -100,7 +100,7 @@
 
 config SND_OMAP_SOC_OMAP_ABE_TWL6040
 	tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
-	depends on TWL6040_CORE && SND_OMAP_SOC
+	depends on TWL6040_CORE && SND_OMAP_SOC && COMMON_CLK
 	depends on ARCH_OMAP4 || (SOC_OMAP5 && MFD_PALMAS) || COMPILE_TEST
 	select SND_OMAP_SOC_DMIC
 	select SND_OMAP_SOC_MCPDM
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 5494924..a768457 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -33,7 +33,6 @@
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
-#include "../codecs/tpa6130a2.h"
 
 #include <asm/mach-types.h>
 
@@ -164,19 +163,6 @@
 	return 0;
 }
 
-static int rx51_hp_event(struct snd_soc_dapm_widget *w,
-			 struct snd_kcontrol *k, int event)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
-	if (SND_SOC_DAPM_EVENT_ON(event))
-		tpa6130a2_stereo_enable(codec, 1);
-	else
-		tpa6130a2_stereo_enable(codec, 0);
-
-	return 0;
-}
-
 static int rx51_get_input(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
@@ -235,7 +221,7 @@
 static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
 	SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event),
 	SND_SOC_DAPM_MIC("DMic", NULL),
-	SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event),
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
 	SND_SOC_DAPM_MIC("HS Mic", NULL),
 	SND_SOC_DAPM_LINE("FM Transmitter", NULL),
 	SND_SOC_DAPM_SPK("Earphone", NULL),
@@ -246,11 +232,14 @@
 	{"Ext Spk", NULL, "HPROUT"},
 	{"Ext Spk", NULL, "HPLCOM"},
 	{"Ext Spk", NULL, "HPRCOM"},
-	{"Headphone Jack", NULL, "LLOUT"},
-	{"Headphone Jack", NULL, "RLOUT"},
 	{"FM Transmitter", NULL, "LLOUT"},
 	{"FM Transmitter", NULL, "RLOUT"},
 
+	{"Headphone Jack", NULL, "TPA6130A2 HPLEFT"},
+	{"Headphone Jack", NULL, "TPA6130A2 HPRIGHT"},
+	{"TPA6130A2 LEFTIN", NULL, "LLOUT"},
+	{"TPA6130A2 RIGHTIN", NULL, "RLOUT"},
+
 	{"DMic Rate 64", NULL, "DMic"},
 	{"DMic", NULL, "Mic Bias"},
 
@@ -286,16 +275,10 @@
 
 static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_card *card = rtd->card;
 	struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card);
 	int err;
 
-	err = tpa6130a2_add_controls(codec);
-	if (err < 0) {
-		dev_err(card->dev, "Failed to add TPA6130A2 controls\n");
-		return err;
-	}
 	snd_soc_limit_volume(card, "TPA6130A2 Headphone Playback Volume", 42);
 
 	err = omap_mcbsp_st_add_controls(rtd, 2);
@@ -357,6 +340,10 @@
 		.name = "TLV320AIC34b",
 		.codec_name = "tlv320aic3x-codec.2-0019",
 	},
+	{
+		.name = "TPA61320A2",
+		.codec_name = "tpa6130a2.2-0060",
+	},
 };
 
 static struct snd_soc_codec_conf rx51_codec_conf[] = {
@@ -364,6 +351,10 @@
 		.dev_name = "tlv320aic3x-codec.2-0019",
 		.name_prefix = "b",
 	},
+	{
+		.dev_name = "tpa6130a2.2-0060",
+		.name_prefix = "TPA6130A2",
+	},
 };
 
 /* Audio card */
@@ -435,11 +426,10 @@
 			dev_err(&pdev->dev, "Headphone amplifier node is not provided\n");
 			return -EINVAL;
 		}
-
-		/* TODO: tpa6130a2a driver supports only a single instance, so
-		 * this driver ignores the headphone-amplifier node for now.
-		 * It's already mandatory in the DT binding to be future proof.
-		 */
+		rx51_aux_dev[1].codec_name = NULL;
+		rx51_aux_dev[1].codec_of_node = dai_node;
+		rx51_codec_conf[1].dev_name = NULL;
+		rx51_codec_conf[1].of_node = dai_node;
 	}
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);