Merge remote-tracking branches 'asoc/topic/tas571x', 'asoc/topic/tlv320aic31xx',...
authorMark Brown <broonie@kernel.org>
Sun, 24 Jul 2016 21:07:46 +0000 (22:07 +0100)
committerMark Brown <broonie@kernel.org>
Sun, 24 Jul 2016 21:07:46 +0000 (22:07 +0100)
sound/soc/codecs/tas571x.c
sound/soc/codecs/tas571x.h
sound/soc/codecs/tlv320aic31xx.h
sound/soc/codecs/tpa6130a2.c
sound/soc/codecs/tpa6130a2.h
sound/soc/codecs/wm8731.c
sound/soc/omap/Kconfig
sound/soc/omap/rx51.c

index b8d19b7..d8baca3 100644 (file)
@@ -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 @@ static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg)
        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 @@ static int tas571x_reg_read(void *context, unsigned int reg,
        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 @@ static const struct snd_soc_dai_ops tas571x_dai_ops = {
        .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 @@ static const struct snd_kcontrol_new tas5711_controls[] = {
                   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 @@ static const struct snd_kcontrol_new tas5717_controls[] = {
                   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 @@ static const struct reg_default tas5717_reg_defaults[] = {
        { 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 = {
index cf800c3..c45677b 100644 (file)
 #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 */
index fe16c34..ac9b146 100644 (file)
@@ -38,141 +38,143 @@ struct aic31xx_pdata {
        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 */
 
index 11d85c5..f1ea052 100644 (file)
@@ -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 @@ enum tpa_model {
        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)
-{
-       struct tpa6130a2_data *data;
-       int val;
-
-       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)
+static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable)
 {
-       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;
+       int ret;
 
-       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;
-
-       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;
-}
+       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
+       struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c);
+       int ret;
 
-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 DECLARE_TLV_DB_RANGE(tpa6130_tlv,
 );
 
 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 DECLARE_TLV_DB_RANGE(tpa6140_tlv,
 );
 
 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;
+       struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component);
 
-       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);
-       }
+       if (data->id == TPA6140A2)
+               return snd_soc_add_component_controls(component,
+                       tpa6140a2_controls, ARRAY_SIZE(tpa6140a2_controls));
+       else
+               return snd_soc_add_component_controls(component,
+                       tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls));
 }
 
-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);
-       }
+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),
+};
 
-       return ret;
-}
-EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
+static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = {
+       { "Left PGA", NULL, "LEFTIN" },
+       { "Right PGA", NULL, "RIGHTIN" },
 
-int tpa6130a2_add_controls(struct snd_soc_codec *codec)
-{
-       struct  tpa6130a2_data *data;
+       { "Left Mute", NULL, "Left PGA" },
+       { "Right Mute", NULL, "Right PGA" },
 
-       if (tpa6130a2_client == NULL)
-               return -ENODEV;
+       { "HPLEFT", NULL, "Left Mute" },
+       { "HPRIGHT", NULL, "Right Mute" },
 
-       data = i2c_get_clientdata(tpa6130a2_client);
+       { "Left PGA", NULL, "Power" },
+       { "Right PGA", NULL, "Power" },
+};
 
-       if (data->id == TPA6140A2)
-               return snd_soc_add_codec_controls(codec, tpa6140a2_controls,
-                                               ARRAY_SIZE(tpa6140a2_controls));
-       else
-               return snd_soc_add_codec_controls(codec, tpa6130a2_controls,
-                                               ARRAY_SIZE(tpa6130a2_controls));
-}
-EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
+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 @@ static int tpa6130a2_probe(struct i2c_client *client,
        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 @@ static int tpa6130a2_probe(struct i2c_client *client,
        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 @@ static int tpa6130a2_probe(struct i2c_client *client,
                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 @@ static int tpa6130a2_probe(struct i2c_client *client,
        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 0;
-
-err_gpio:
-       tpa6130a2_client = NULL;
+               return ret;
 
-       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 @@ static struct i2c_driver tpa6130a2_i2c_driver = {
                .of_match_table = of_match_ptr(tpa6130a2_of_match),
        },
        .probe = tpa6130a2_probe,
-       .remove = tpa6130a2_remove,
        .id_table = tpa6130a2_id,
 };
 
index 4174440..f19cad5 100644 (file)
 #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__ */
index 4bcf5f8..d18261a 100644 (file)
@@ -358,6 +358,9 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
        case 24:
                iface |= 0x0008;
                break;
+       case 32:
+               iface |= 0x000c;
+               break;
        }
 
        wm8731_set_deemph(codec);
@@ -541,7 +544,7 @@ static int wm8731_startup(struct snd_pcm_substream *substream,
 #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,
index 5c471d9..f5451c7 100644 (file)
@@ -100,7 +100,7 @@ config SND_OMAP_SOC_OMAP_TWL4030
 
 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
index 5494924..a768457 100644 (file)
@@ -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 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w,
        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 struct snd_soc_jack_gpio rx51_av_jack_gpios[] = {
 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 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"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 const struct snd_kcontrol_new aic34_rx51_controls[] = {
 
 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 @@ static struct snd_soc_aux_dev rx51_aux_dev[] = {
                .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 @@ static struct snd_soc_codec_conf rx51_codec_conf[] = {
                .dev_name = "tlv320aic3x-codec.2-0019",
                .name_prefix = "b",
        },
+       {
+               .dev_name = "tpa6130a2.2-0060",
+               .name_prefix = "TPA6130A2",
+       },
 };
 
 /* Audio card */
@@ -435,11 +426,10 @@ static int rx51_soc_probe(struct platform_device *pdev)
                        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);