diff options
-rw-r--r-- | include/sound/control.h | 7 | ||||
-rw-r--r-- | include/sound/soc.h | 14 | ||||
-rw-r--r-- | sound/core/control.c | 6 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 4 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic23.c | 10 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic31xx.c | 23 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic32x4.c | 21 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 21 |
8 files changed, 74 insertions, 32 deletions
diff --git a/include/sound/control.h b/include/sound/control.h index 5358892b1b3..042613938a1 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -31,10 +31,15 @@ typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ct typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol, - int op_flag, /* 0=read,1=write,-1=command */ + int op_flag, /* SNDRV_CTL_TLV_OP_XXX */ unsigned int size, unsigned int __user *tlv); +enum { + SNDRV_CTL_TLV_OP_READ = 0, + SNDRV_CTL_TLV_OP_WRITE = 1, + SNDRV_CTL_TLV_OP_CMD = -1, +}; struct snd_kcontrol_new { snd_ctl_elem_iface_t iface; /* interface identifier */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 27ed5ccb174..be6ecae247b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -272,7 +272,14 @@ .get = xhandler_get, .put = xhandler_put, \ .private_value = (unsigned long)&(struct soc_bytes_ext) \ {.max = xcount} } - +#define SND_SOC_BYTES_TLV(xname, xcount, xhandler_get, xhandler_put) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE | \ + SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ + .tlv.c = (snd_soc_bytes_tlv_callback), \ + .info = snd_soc_info_bytes_ext, \ + .private_value = (unsigned long)&(struct soc_bytes_ext) \ + {.max = xcount, .get = xhandler_get, .put = xhandler_put, } } #define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \ xmin, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -560,6 +567,8 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *ucontrol); +int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, + unsigned int size, unsigned int __user *tlv); int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, @@ -1132,6 +1141,9 @@ struct soc_bytes { struct soc_bytes_ext { int max; + /* used for TLV byte control */ + int (*get)(unsigned int __user *bytes, unsigned int size); + int (*put)(const unsigned int __user *bytes, unsigned int size); }; /* multi register control */ diff --git a/sound/core/control.c b/sound/core/control.c index f0b0e14497a..b9611344ff9 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1406,11 +1406,11 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: return snd_ctl_subscribe_events(ctl, ip); case SNDRV_CTL_IOCTL_TLV_READ: - return snd_ctl_tlv_ioctl(ctl, argp, 0); + return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ); case SNDRV_CTL_IOCTL_TLV_WRITE: - return snd_ctl_tlv_ioctl(ctl, argp, 1); + return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE); case SNDRV_CTL_IOCTL_TLV_COMMAND: - return snd_ctl_tlv_ioctl(ctl, argp, -1); + return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD); case SNDRV_CTL_IOCTL_POWER: return -ENOPROTOOPT; case SNDRV_CTL_IOCTL_POWER_STATE: diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1090135de0b..8838838e25e 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -564,7 +564,9 @@ config SND_SOC_TLV320AIC26 depends on SPI config SND_SOC_TLV320AIC31XX - tristate + tristate "Texas Instruments TLV320AIC31xx CODECs" + depends on I2C + select REGMAP_I2C config SND_SOC_TLV320AIC32X4 tristate diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 686b8b85b95..d67167920c2 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -364,16 +364,16 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: + switch (params_width(params)) { + case 16: break; - case SNDRV_PCM_FORMAT_S20_3LE: + case 20: iface_reg |= (0x01 << 2); break; - case SNDRV_PCM_FORMAT_S24_LE: + case 24: iface_reg |= (0x02 << 2); break; - case SNDRV_PCM_FORMAT_S32_LE: + case 32: iface_reg |= (0x03 << 2); break; } diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 1cdae8ccc61..095f4556ab1 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -249,17 +249,16 @@ static const char * const mic_select_text[] = { "Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm" }; -static const -SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text); -static const -SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text); -static const -SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text); - -static const -SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); -static const -SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text); +static SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, + mic_select_text); +static SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, + mic_select_text); +static SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, + mic_select_text); + +static SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); +static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, + mic_select_text); static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0); static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0); @@ -329,6 +328,7 @@ static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg, unsigned int bits; int counter = count; int ret = regmap_read(aic31xx->regmap, reg, &bits); + while ((bits & mask) != wbits && counter && !ret) { usleep_range(sleep, sleep * 2); ret = regmap_read(aic31xx->regmap, reg, &bits); @@ -435,6 +435,7 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + switch (event) { case SND_SOC_DAPM_POST_PMU: /* change mic bias voltage to user defined */ diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 1d9b117345a..89e41d2f758 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -626,32 +626,33 @@ static int aic32x4_probe(struct snd_soc_codec *codec) snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN | AIC32X4_MICBIAS_2075V); } - if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) { + if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE); - } tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ? AIC32X4_LDOCTLEN : 0; snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg); tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE); - if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) { + if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) tmp_reg |= AIC32X4_LDOIN_18_36; - } - if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) { + if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) tmp_reg |= AIC32X4_LDOIN2HP; - } snd_soc_write(codec, AIC32X4_CMMODE, tmp_reg); /* Mic PGA routing */ if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) - snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K); + snd_soc_write(codec, AIC32X4_LMICPGANIN, + AIC32X4_LMICPGANIN_IN2R_10K); else - snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_CM1L_10K); + snd_soc_write(codec, AIC32X4_LMICPGANIN, + AIC32X4_LMICPGANIN_CM1L_10K); if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) - snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K); + snd_soc_write(codec, AIC32X4_RMICPGANIN, + AIC32X4_RMICPGANIN_IN1L_10K); else - snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_CM1R_10K); + snd_soc_write(codec, AIC32X4_RMICPGANIN, + AIC32X4_RMICPGANIN_CM1R_10K); aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2d6c8b86b7d..d4bfd4a9076 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3289,6 +3289,27 @@ int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); +int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, + unsigned int size, unsigned int __user *tlv) +{ + struct soc_bytes_ext *params = (void *)kcontrol->private_value; + unsigned int count = size < params->max ? size : params->max; + int ret = -ENXIO; + + switch (op_flag) { + case SNDRV_CTL_TLV_OP_READ: + if (params->get) + ret = params->get(tlv, count); + break; + case SNDRV_CTL_TLV_OP_WRITE: + if (params->put) + ret = params->put(tlv, count); + break; + } + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); + /** * snd_soc_info_xr_sx - signed multi register info callback * @kcontrol: mreg control |