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 5358892b1b39..042613938a1d 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 | |||
31 | typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); | 31 | typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); |
32 | typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); | 32 | typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); |
33 | typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol, | 33 | typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol, |
34 | int op_flag, /* 0=read,1=write,-1=command */ | 34 | int op_flag, /* SNDRV_CTL_TLV_OP_XXX */ |
35 | unsigned int size, | 35 | unsigned int size, |
36 | unsigned int __user *tlv); | 36 | unsigned int __user *tlv); |
37 | 37 | ||
38 | enum { | ||
39 | SNDRV_CTL_TLV_OP_READ = 0, | ||
40 | SNDRV_CTL_TLV_OP_WRITE = 1, | ||
41 | SNDRV_CTL_TLV_OP_CMD = -1, | ||
42 | }; | ||
38 | 43 | ||
39 | struct snd_kcontrol_new { | 44 | struct snd_kcontrol_new { |
40 | snd_ctl_elem_iface_t iface; /* interface identifier */ | 45 | snd_ctl_elem_iface_t iface; /* interface identifier */ |
diff --git a/include/sound/soc.h b/include/sound/soc.h index 27ed5ccb174a..be6ecae247b0 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -272,7 +272,14 @@ | |||
272 | .get = xhandler_get, .put = xhandler_put, \ | 272 | .get = xhandler_get, .put = xhandler_put, \ |
273 | .private_value = (unsigned long)&(struct soc_bytes_ext) \ | 273 | .private_value = (unsigned long)&(struct soc_bytes_ext) \ |
274 | {.max = xcount} } | 274 | {.max = xcount} } |
275 | 275 | #define SND_SOC_BYTES_TLV(xname, xcount, xhandler_get, xhandler_put) \ | |
276 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
277 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE | \ | ||
278 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ | ||
279 | .tlv.c = (snd_soc_bytes_tlv_callback), \ | ||
280 | .info = snd_soc_info_bytes_ext, \ | ||
281 | .private_value = (unsigned long)&(struct soc_bytes_ext) \ | ||
282 | {.max = xcount, .get = xhandler_get, .put = xhandler_put, } } | ||
276 | #define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \ | 283 | #define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \ |
277 | xmin, xmax, xinvert) \ | 284 | xmin, xmax, xinvert) \ |
278 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 285 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
@@ -560,6 +567,8 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, | |||
560 | struct snd_ctl_elem_value *ucontrol); | 567 | struct snd_ctl_elem_value *ucontrol); |
561 | int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, | 568 | int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, |
562 | struct snd_ctl_elem_info *ucontrol); | 569 | struct snd_ctl_elem_info *ucontrol); |
570 | int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, | ||
571 | unsigned int size, unsigned int __user *tlv); | ||
563 | int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, | 572 | int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, |
564 | struct snd_ctl_elem_info *uinfo); | 573 | struct snd_ctl_elem_info *uinfo); |
565 | int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, | 574 | int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, |
@@ -1132,6 +1141,9 @@ struct soc_bytes { | |||
1132 | 1141 | ||
1133 | struct soc_bytes_ext { | 1142 | struct soc_bytes_ext { |
1134 | int max; | 1143 | int max; |
1144 | /* used for TLV byte control */ | ||
1145 | int (*get)(unsigned int __user *bytes, unsigned int size); | ||
1146 | int (*put)(const unsigned int __user *bytes, unsigned int size); | ||
1135 | }; | 1147 | }; |
1136 | 1148 | ||
1137 | /* multi register control */ | 1149 | /* multi register control */ |
diff --git a/sound/core/control.c b/sound/core/control.c index f0b0e14497a5..b9611344ff9e 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 | |||
1406 | case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: | 1406 | case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: |
1407 | return snd_ctl_subscribe_events(ctl, ip); | 1407 | return snd_ctl_subscribe_events(ctl, ip); |
1408 | case SNDRV_CTL_IOCTL_TLV_READ: | 1408 | case SNDRV_CTL_IOCTL_TLV_READ: |
1409 | return snd_ctl_tlv_ioctl(ctl, argp, 0); | 1409 | return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ); |
1410 | case SNDRV_CTL_IOCTL_TLV_WRITE: | 1410 | case SNDRV_CTL_IOCTL_TLV_WRITE: |
1411 | return snd_ctl_tlv_ioctl(ctl, argp, 1); | 1411 | return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE); |
1412 | case SNDRV_CTL_IOCTL_TLV_COMMAND: | 1412 | case SNDRV_CTL_IOCTL_TLV_COMMAND: |
1413 | return snd_ctl_tlv_ioctl(ctl, argp, -1); | 1413 | return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD); |
1414 | case SNDRV_CTL_IOCTL_POWER: | 1414 | case SNDRV_CTL_IOCTL_POWER: |
1415 | return -ENOPROTOOPT; | 1415 | return -ENOPROTOOPT; |
1416 | case SNDRV_CTL_IOCTL_POWER_STATE: | 1416 | case SNDRV_CTL_IOCTL_POWER_STATE: |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1090135de0ba..8838838e25ed 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -564,7 +564,9 @@ config SND_SOC_TLV320AIC26 | |||
564 | depends on SPI | 564 | depends on SPI |
565 | 565 | ||
566 | config SND_SOC_TLV320AIC31XX | 566 | config SND_SOC_TLV320AIC31XX |
567 | tristate | 567 | tristate "Texas Instruments TLV320AIC31xx CODECs" |
568 | depends on I2C | ||
569 | select REGMAP_I2C | ||
568 | 570 | ||
569 | config SND_SOC_TLV320AIC32X4 | 571 | config SND_SOC_TLV320AIC32X4 |
570 | tristate | 572 | tristate |
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 686b8b85b956..d67167920c2f 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, | |||
364 | 364 | ||
365 | iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); | 365 | iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); |
366 | 366 | ||
367 | switch (params_format(params)) { | 367 | switch (params_width(params)) { |
368 | case SNDRV_PCM_FORMAT_S16_LE: | 368 | case 16: |
369 | break; | 369 | break; |
370 | case SNDRV_PCM_FORMAT_S20_3LE: | 370 | case 20: |
371 | iface_reg |= (0x01 << 2); | 371 | iface_reg |= (0x01 << 2); |
372 | break; | 372 | break; |
373 | case SNDRV_PCM_FORMAT_S24_LE: | 373 | case 24: |
374 | iface_reg |= (0x02 << 2); | 374 | iface_reg |= (0x02 << 2); |
375 | break; | 375 | break; |
376 | case SNDRV_PCM_FORMAT_S32_LE: | 376 | case 32: |
377 | iface_reg |= (0x03 << 2); | 377 | iface_reg |= (0x03 << 2); |
378 | break; | 378 | break; |
379 | } | 379 | } |
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 1cdae8ccc61b..095f4556ab1b 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -249,17 +249,16 @@ static const char * const mic_select_text[] = { | |||
249 | "Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm" | 249 | "Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm" |
250 | }; | 250 | }; |
251 | 251 | ||
252 | static const | 252 | static SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, |
253 | SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text); | 253 | mic_select_text); |
254 | static const | 254 | static SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, |
255 | SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text); | 255 | mic_select_text); |
256 | static const | 256 | static SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, |
257 | SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text); | 257 | mic_select_text); |
258 | 258 | ||
259 | static const | 259 | static SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); |
260 | SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); | 260 | static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, |
261 | static const | 261 | mic_select_text); |
262 | SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text); | ||
263 | 262 | ||
264 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0); | 263 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0); |
265 | static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0); | 264 | 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, | |||
329 | unsigned int bits; | 328 | unsigned int bits; |
330 | int counter = count; | 329 | int counter = count; |
331 | int ret = regmap_read(aic31xx->regmap, reg, &bits); | 330 | int ret = regmap_read(aic31xx->regmap, reg, &bits); |
331 | |||
332 | while ((bits & mask) != wbits && counter && !ret) { | 332 | while ((bits & mask) != wbits && counter && !ret) { |
333 | usleep_range(sleep, sleep * 2); | 333 | usleep_range(sleep, sleep * 2); |
334 | ret = regmap_read(aic31xx->regmap, reg, &bits); | 334 | ret = regmap_read(aic31xx->regmap, reg, &bits); |
@@ -435,6 +435,7 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, | |||
435 | { | 435 | { |
436 | struct snd_soc_codec *codec = w->codec; | 436 | struct snd_soc_codec *codec = w->codec; |
437 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | 437 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); |
438 | |||
438 | switch (event) { | 439 | switch (event) { |
439 | case SND_SOC_DAPM_POST_PMU: | 440 | case SND_SOC_DAPM_POST_PMU: |
440 | /* change mic bias voltage to user defined */ | 441 | /* change mic bias voltage to user defined */ |
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 1d9b117345a3..89e41d2f7586 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) | |||
626 | snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN | | 626 | snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN | |
627 | AIC32X4_MICBIAS_2075V); | 627 | AIC32X4_MICBIAS_2075V); |
628 | } | 628 | } |
629 | if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) { | 629 | if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) |
630 | snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE); | 630 | snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE); |
631 | } | ||
632 | 631 | ||
633 | tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ? | 632 | tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ? |
634 | AIC32X4_LDOCTLEN : 0; | 633 | AIC32X4_LDOCTLEN : 0; |
635 | snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg); | 634 | snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg); |
636 | 635 | ||
637 | tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE); | 636 | tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE); |
638 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) { | 637 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) |
639 | tmp_reg |= AIC32X4_LDOIN_18_36; | 638 | tmp_reg |= AIC32X4_LDOIN_18_36; |
640 | } | 639 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) |
641 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) { | ||
642 | tmp_reg |= AIC32X4_LDOIN2HP; | 640 | tmp_reg |= AIC32X4_LDOIN2HP; |
643 | } | ||
644 | snd_soc_write(codec, AIC32X4_CMMODE, tmp_reg); | 641 | snd_soc_write(codec, AIC32X4_CMMODE, tmp_reg); |
645 | 642 | ||
646 | /* Mic PGA routing */ | 643 | /* Mic PGA routing */ |
647 | if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) | 644 | if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) |
648 | snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K); | 645 | snd_soc_write(codec, AIC32X4_LMICPGANIN, |
646 | AIC32X4_LMICPGANIN_IN2R_10K); | ||
649 | else | 647 | else |
650 | snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_CM1L_10K); | 648 | snd_soc_write(codec, AIC32X4_LMICPGANIN, |
649 | AIC32X4_LMICPGANIN_CM1L_10K); | ||
651 | if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) | 650 | if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) |
652 | snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K); | 651 | snd_soc_write(codec, AIC32X4_RMICPGANIN, |
652 | AIC32X4_RMICPGANIN_IN1L_10K); | ||
653 | else | 653 | else |
654 | snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_CM1R_10K); | 654 | snd_soc_write(codec, AIC32X4_RMICPGANIN, |
655 | AIC32X4_RMICPGANIN_CM1R_10K); | ||
655 | 656 | ||
656 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 657 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
657 | 658 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2d6c8b86b7d3..d4bfd4a9076f 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, | |||
3289 | } | 3289 | } |
3290 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); | 3290 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); |
3291 | 3291 | ||
3292 | int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, | ||
3293 | unsigned int size, unsigned int __user *tlv) | ||
3294 | { | ||
3295 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
3296 | unsigned int count = size < params->max ? size : params->max; | ||
3297 | int ret = -ENXIO; | ||
3298 | |||
3299 | switch (op_flag) { | ||
3300 | case SNDRV_CTL_TLV_OP_READ: | ||
3301 | if (params->get) | ||
3302 | ret = params->get(tlv, count); | ||
3303 | break; | ||
3304 | case SNDRV_CTL_TLV_OP_WRITE: | ||
3305 | if (params->put) | ||
3306 | ret = params->put(tlv, count); | ||
3307 | break; | ||
3308 | } | ||
3309 | return ret; | ||
3310 | } | ||
3311 | EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); | ||
3312 | |||
3292 | /** | 3313 | /** |
3293 | * snd_soc_info_xr_sx - signed multi register info callback | 3314 | * snd_soc_info_xr_sx - signed multi register info callback |
3294 | * @kcontrol: mreg control | 3315 | * @kcontrol: mreg control |