diff options
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/codecs/tas571x.c | 188 | ||||
-rw-r--r-- | sound/soc/codecs/tas571x.h | 40 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic31xx.h | 134 | ||||
-rw-r--r-- | sound/soc/codecs/tpa6130a2.c | 394 | ||||
-rw-r--r-- | sound/soc/codecs/tpa6130a2.h | 14 | ||||
-rw-r--r-- | sound/soc/codecs/wm8731.c | 5 | ||||
-rw-r--r-- | sound/soc/omap/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/omap/rx51.c | 46 |
8 files changed, 438 insertions, 385 deletions
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index b8d19b77bde9..d8baca3f8413 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 @@ 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 = { diff --git a/sound/soc/codecs/tas571x.h b/sound/soc/codecs/tas571x.h index cf800c364f0f..c45677bc26ad 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 fe16c34607bb..ac9b146526eb 100644 --- a/sound/soc/codecs/tlv320aic31xx.h +++ b/sound/soc/codecs/tlv320aic31xx.h @@ -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 */ diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 11d85c5c787a..f1ea052a822e 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 @@ 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, }; diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index 417444020ba6..f19cad5d4172 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 4bcf5f8ece50..d18261a44256 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -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, diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 5c471d920898..f5451c78ede5 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -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 diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 54949242bc70..a76845748a10 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 @@ 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); |