diff options
author | Nikita Yushchenko <nikita.yoush@cogentembedded.com> | 2016-09-23 07:52:52 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-09-26 12:42:27 -0400 |
commit | ef9656b6936fb7f66e7e25d284c955f4893ac421 (patch) | |
tree | daadc3a815e6b5ca88b7373445ff25e1ab3349a1 | |
parent | 8180bd56bdd1dcade8d1b2a0b6f70b2397bec372 (diff) |
ASoC: tlv320aic31xx: add explicit support for tlv320dac31xx
tlv320dac31xx is a subset of tlv320aic31xx:
- it does not have MIC inputs and ADC, thus capture is not supported,
- it has analog inputs AIN1/AIN2 that can be mixed into output.
Although tlv320dac31xx does work with tlv320aic31xx driver, this setup
does register non-existent widgets and non-existent capture stream.
Thus userspace lists non-existent objects in user interfaces, an can
access these, causing operations with device registers that are
declared as "reserved" in tlv320dac31xx datasheet.
This patch fixes this situation by separating controls/widgets/routes
into common, aic31xx-specific, and dac31xx-specific parts. Only parts
that match actual hardware (as declared in "compatible" device tree
property) are registered.
Changes from v1:
- update device tree binding documentation,
- rebased on top of "ASoC: codec duplicated callback function goes to
component on tlv320aic31xx" commit.
Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | Documentation/devicetree/bindings/sound/tlv320aic31xx.txt | 9 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic31xx.c | 212 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic31xx.h | 2 |
3 files changed, 164 insertions, 59 deletions
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt index eff12be5e789..9340d2ddcc54 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt | |||
@@ -11,6 +11,7 @@ Required properties: | |||
11 | "ti,tlv320aic3110" - TLV320AIC3110 (stereo speaker amp, no MiniDSP) | 11 | "ti,tlv320aic3110" - TLV320AIC3110 (stereo speaker amp, no MiniDSP) |
12 | "ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP) | 12 | "ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP) |
13 | "ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP) | 13 | "ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP) |
14 | "ti,tlv320dac3100" - TLV320DAC3100 (no ADC, mono speaker amp, no MiniDSP) | ||
14 | 15 | ||
15 | - reg - <int> - I2C slave address | 16 | - reg - <int> - I2C slave address |
16 | - HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply, | 17 | - HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply, |
@@ -37,9 +38,11 @@ CODEC output pins: | |||
37 | * MICBIAS | 38 | * MICBIAS |
38 | 39 | ||
39 | CODEC input pins: | 40 | CODEC input pins: |
40 | * MIC1LP | 41 | * MIC1LP, devices with ADC |
41 | * MIC1RP | 42 | * MIC1RP, devices with ADC |
42 | * MIC1LM | 43 | * MIC1LM, devices with ADC |
44 | * AIN1, devices without ADC | ||
45 | * AIN2, devices without ADC | ||
43 | 46 | ||
44 | The pins can be used in referring sound node's audio-routing property. | 47 | The pins can be used in referring sound node's audio-routing property. |
45 | 48 | ||
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index e46fb472e48d..725173b12725 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -273,10 +273,20 @@ static const DECLARE_TLV_DB_SCALE(sp_vol_tlv, -6350, 50, 0); | |||
273 | /* | 273 | /* |
274 | * controls to be exported to the user space | 274 | * controls to be exported to the user space |
275 | */ | 275 | */ |
276 | static const struct snd_kcontrol_new aic31xx_snd_controls[] = { | 276 | static const struct snd_kcontrol_new common31xx_snd_controls[] = { |
277 | SOC_DOUBLE_R_S_TLV("DAC Playback Volume", AIC31XX_LDACVOL, | 277 | SOC_DOUBLE_R_S_TLV("DAC Playback Volume", AIC31XX_LDACVOL, |
278 | AIC31XX_RDACVOL, 0, -127, 48, 7, 0, dac_vol_tlv), | 278 | AIC31XX_RDACVOL, 0, -127, 48, 7, 0, dac_vol_tlv), |
279 | 279 | ||
280 | SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN, | ||
281 | AIC31XX_HPRGAIN, 2, 1, 0), | ||
282 | SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN, | ||
283 | AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv), | ||
284 | |||
285 | SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL, | ||
286 | AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv), | ||
287 | }; | ||
288 | |||
289 | static const struct snd_kcontrol_new aic31xx_snd_controls[] = { | ||
280 | SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1, | 290 | SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1, |
281 | adc_fgain_tlv), | 291 | adc_fgain_tlv), |
282 | 292 | ||
@@ -286,14 +296,6 @@ static const struct snd_kcontrol_new aic31xx_snd_controls[] = { | |||
286 | 296 | ||
287 | SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0, | 297 | SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0, |
288 | 119, 0, mic_pga_tlv), | 298 | 119, 0, mic_pga_tlv), |
289 | |||
290 | SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN, | ||
291 | AIC31XX_HPRGAIN, 2, 1, 0), | ||
292 | SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN, | ||
293 | AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv), | ||
294 | |||
295 | SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL, | ||
296 | AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv), | ||
297 | }; | 299 | }; |
298 | 300 | ||
299 | static const struct snd_kcontrol_new aic311x_snd_controls[] = { | 301 | static const struct snd_kcontrol_new aic311x_snd_controls[] = { |
@@ -397,17 +399,28 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, | |||
397 | return 0; | 399 | return 0; |
398 | } | 400 | } |
399 | 401 | ||
400 | static const struct snd_kcontrol_new left_output_switches[] = { | 402 | static const struct snd_kcontrol_new aic31xx_left_output_switches[] = { |
401 | SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), | 403 | SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), |
402 | SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0), | 404 | SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0), |
403 | SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0), | 405 | SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0), |
404 | }; | 406 | }; |
405 | 407 | ||
406 | static const struct snd_kcontrol_new right_output_switches[] = { | 408 | static const struct snd_kcontrol_new aic31xx_right_output_switches[] = { |
407 | SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), | 409 | SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), |
408 | SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0), | 410 | SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0), |
409 | }; | 411 | }; |
410 | 412 | ||
413 | static const struct snd_kcontrol_new dac31xx_left_output_switches[] = { | ||
414 | SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), | ||
415 | SOC_DAPM_SINGLE("From AIN1", AIC31XX_DACMIXERROUTE, 5, 1, 0), | ||
416 | SOC_DAPM_SINGLE("From AIN2", AIC31XX_DACMIXERROUTE, 4, 1, 0), | ||
417 | }; | ||
418 | |||
419 | static const struct snd_kcontrol_new dac31xx_right_output_switches[] = { | ||
420 | SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), | ||
421 | SOC_DAPM_SINGLE("From AIN2", AIC31XX_DACMIXERROUTE, 1, 1, 0), | ||
422 | }; | ||
423 | |||
411 | static const struct snd_kcontrol_new p_term_mic1lp = | 424 | static const struct snd_kcontrol_new p_term_mic1lp = |
412 | SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum); | 425 | SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum); |
413 | 426 | ||
@@ -457,7 +470,7 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, | |||
457 | return 0; | 470 | return 0; |
458 | } | 471 | } |
459 | 472 | ||
460 | static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { | 473 | static const struct snd_soc_dapm_widget common31xx_dapm_widgets[] = { |
461 | SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), | 474 | SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), |
462 | 475 | ||
463 | SND_SOC_DAPM_MUX("DAC Left Input", | 476 | SND_SOC_DAPM_MUX("DAC Left Input", |
@@ -473,14 +486,7 @@ static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { | |||
473 | AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event, | 486 | AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event, |
474 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | 487 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
475 | 488 | ||
476 | /* Output Mixers */ | 489 | /* HP */ |
477 | SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, | ||
478 | left_output_switches, | ||
479 | ARRAY_SIZE(left_output_switches)), | ||
480 | SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, | ||
481 | right_output_switches, | ||
482 | ARRAY_SIZE(right_output_switches)), | ||
483 | |||
484 | SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0, | 490 | SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0, |
485 | &aic31xx_dapm_hpl_switch), | 491 | &aic31xx_dapm_hpl_switch), |
486 | SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0, | 492 | SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0, |
@@ -494,10 +500,34 @@ static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { | |||
494 | NULL, 0, aic31xx_dapm_power_event, | 500 | NULL, 0, aic31xx_dapm_power_event, |
495 | SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), | 501 | SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), |
496 | 502 | ||
497 | /* ADC */ | 503 | /* Mic Bias */ |
498 | SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0, | 504 | SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event, |
499 | aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | | 505 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
500 | SND_SOC_DAPM_POST_PMD), | 506 | |
507 | /* Outputs */ | ||
508 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
509 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
510 | }; | ||
511 | |||
512 | static const struct snd_soc_dapm_widget dac31xx_dapm_widgets[] = { | ||
513 | /* Inputs */ | ||
514 | SND_SOC_DAPM_INPUT("AIN1"), | ||
515 | SND_SOC_DAPM_INPUT("AIN2"), | ||
516 | |||
517 | /* Output Mixers */ | ||
518 | SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, | ||
519 | dac31xx_left_output_switches, | ||
520 | ARRAY_SIZE(dac31xx_left_output_switches)), | ||
521 | SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, | ||
522 | dac31xx_right_output_switches, | ||
523 | ARRAY_SIZE(dac31xx_right_output_switches)), | ||
524 | }; | ||
525 | |||
526 | static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { | ||
527 | /* Inputs */ | ||
528 | SND_SOC_DAPM_INPUT("MIC1LP"), | ||
529 | SND_SOC_DAPM_INPUT("MIC1RP"), | ||
530 | SND_SOC_DAPM_INPUT("MIC1LM"), | ||
501 | 531 | ||
502 | /* Input Selection to MIC_PGA */ | 532 | /* Input Selection to MIC_PGA */ |
503 | SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0, | 533 | SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0, |
@@ -507,24 +537,25 @@ static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { | |||
507 | SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0, | 537 | SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0, |
508 | &p_term_mic1lm), | 538 | &p_term_mic1lm), |
509 | 539 | ||
540 | /* ADC */ | ||
541 | SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0, | ||
542 | aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | | ||
543 | SND_SOC_DAPM_POST_PMD), | ||
544 | |||
510 | SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0, | 545 | SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0, |
511 | &m_term_mic1lm), | 546 | &m_term_mic1lm), |
547 | |||
512 | /* Enabling & Disabling MIC Gain Ctl */ | 548 | /* Enabling & Disabling MIC Gain Ctl */ |
513 | SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA, | 549 | SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA, |
514 | 7, 1, NULL, 0), | 550 | 7, 1, NULL, 0), |
515 | 551 | ||
516 | /* Mic Bias */ | 552 | /* Output Mixers */ |
517 | SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event, | 553 | SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, |
518 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 554 | aic31xx_left_output_switches, |
519 | 555 | ARRAY_SIZE(aic31xx_left_output_switches)), | |
520 | /* Outputs */ | 556 | SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, |
521 | SND_SOC_DAPM_OUTPUT("HPL"), | 557 | aic31xx_right_output_switches, |
522 | SND_SOC_DAPM_OUTPUT("HPR"), | 558 | ARRAY_SIZE(aic31xx_right_output_switches)), |
523 | |||
524 | /* Inputs */ | ||
525 | SND_SOC_DAPM_INPUT("MIC1LP"), | ||
526 | SND_SOC_DAPM_INPUT("MIC1RP"), | ||
527 | SND_SOC_DAPM_INPUT("MIC1LM"), | ||
528 | }; | 559 | }; |
529 | 560 | ||
530 | static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = { | 561 | static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = { |
@@ -554,7 +585,7 @@ static const struct snd_soc_dapm_widget aic310x_dapm_widgets[] = { | |||
554 | }; | 585 | }; |
555 | 586 | ||
556 | static const struct snd_soc_dapm_route | 587 | static const struct snd_soc_dapm_route |
557 | aic31xx_audio_map[] = { | 588 | common31xx_audio_map[] = { |
558 | /* DAC Input Routing */ | 589 | /* DAC Input Routing */ |
559 | {"DAC Left Input", "Left Data", "DAC IN"}, | 590 | {"DAC Left Input", "Left Data", "DAC IN"}, |
560 | {"DAC Left Input", "Right Data", "DAC IN"}, | 591 | {"DAC Left Input", "Right Data", "DAC IN"}, |
@@ -565,6 +596,31 @@ aic31xx_audio_map[] = { | |||
565 | {"DAC Left", NULL, "DAC Left Input"}, | 596 | {"DAC Left", NULL, "DAC Left Input"}, |
566 | {"DAC Right", NULL, "DAC Right Input"}, | 597 | {"DAC Right", NULL, "DAC Right Input"}, |
567 | 598 | ||
599 | /* HPL path */ | ||
600 | {"HP Left", "Switch", "Output Left"}, | ||
601 | {"HPL Driver", NULL, "HP Left"}, | ||
602 | {"HPL", NULL, "HPL Driver"}, | ||
603 | |||
604 | /* HPR path */ | ||
605 | {"HP Right", "Switch", "Output Right"}, | ||
606 | {"HPR Driver", NULL, "HP Right"}, | ||
607 | {"HPR", NULL, "HPR Driver"}, | ||
608 | }; | ||
609 | |||
610 | static const struct snd_soc_dapm_route | ||
611 | dac31xx_audio_map[] = { | ||
612 | /* Left Output */ | ||
613 | {"Output Left", "From Left DAC", "DAC Left"}, | ||
614 | {"Output Left", "From AIN1", "AIN1"}, | ||
615 | {"Output Left", "From AIN2", "AIN2"}, | ||
616 | |||
617 | /* Right Output */ | ||
618 | {"Output Right", "From Right DAC", "DAC Right"}, | ||
619 | {"Output Right", "From AIN2", "AIN2"}, | ||
620 | }; | ||
621 | |||
622 | static const struct snd_soc_dapm_route | ||
623 | aic31xx_audio_map[] = { | ||
568 | /* Mic input */ | 624 | /* Mic input */ |
569 | {"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"}, | 625 | {"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"}, |
570 | {"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"}, | 626 | {"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"}, |
@@ -595,16 +651,6 @@ aic31xx_audio_map[] = { | |||
595 | /* Right Output */ | 651 | /* Right Output */ |
596 | {"Output Right", "From Right DAC", "DAC Right"}, | 652 | {"Output Right", "From Right DAC", "DAC Right"}, |
597 | {"Output Right", "From MIC1RP", "MIC1RP"}, | 653 | {"Output Right", "From MIC1RP", "MIC1RP"}, |
598 | |||
599 | /* HPL path */ | ||
600 | {"HP Left", "Switch", "Output Left"}, | ||
601 | {"HPL Driver", NULL, "HP Left"}, | ||
602 | {"HPL", NULL, "HPL Driver"}, | ||
603 | |||
604 | /* HPR path */ | ||
605 | {"HP Right", "Switch", "Output Right"}, | ||
606 | {"HPR Driver", NULL, "HP Right"}, | ||
607 | {"HPR", NULL, "HPR Driver"}, | ||
608 | }; | 654 | }; |
609 | 655 | ||
610 | static const struct snd_soc_dapm_route | 656 | static const struct snd_soc_dapm_route |
@@ -633,6 +679,13 @@ static int aic31xx_add_controls(struct snd_soc_codec *codec) | |||
633 | int ret = 0; | 679 | int ret = 0; |
634 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | 680 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); |
635 | 681 | ||
682 | if (!(aic31xx->pdata.codec_type & DAC31XX_BIT)) | ||
683 | ret = snd_soc_add_codec_controls( | ||
684 | codec, aic31xx_snd_controls, | ||
685 | ARRAY_SIZE(aic31xx_snd_controls)); | ||
686 | if (ret) | ||
687 | return ret; | ||
688 | |||
636 | if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) | 689 | if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) |
637 | ret = snd_soc_add_codec_controls( | 690 | ret = snd_soc_add_codec_controls( |
638 | codec, aic311x_snd_controls, | 691 | codec, aic311x_snd_controls, |
@@ -651,6 +704,30 @@ static int aic31xx_add_widgets(struct snd_soc_codec *codec) | |||
651 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | 704 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); |
652 | int ret = 0; | 705 | int ret = 0; |
653 | 706 | ||
707 | if (aic31xx->pdata.codec_type & DAC31XX_BIT) { | ||
708 | ret = snd_soc_dapm_new_controls( | ||
709 | dapm, dac31xx_dapm_widgets, | ||
710 | ARRAY_SIZE(dac31xx_dapm_widgets)); | ||
711 | if (ret) | ||
712 | return ret; | ||
713 | |||
714 | ret = snd_soc_dapm_add_routes(dapm, dac31xx_audio_map, | ||
715 | ARRAY_SIZE(dac31xx_audio_map)); | ||
716 | if (ret) | ||
717 | return ret; | ||
718 | } else { | ||
719 | ret = snd_soc_dapm_new_controls( | ||
720 | dapm, aic31xx_dapm_widgets, | ||
721 | ARRAY_SIZE(aic31xx_dapm_widgets)); | ||
722 | if (ret) | ||
723 | return ret; | ||
724 | |||
725 | ret = snd_soc_dapm_add_routes(dapm, aic31xx_audio_map, | ||
726 | ARRAY_SIZE(aic31xx_audio_map)); | ||
727 | if (ret) | ||
728 | return ret; | ||
729 | } | ||
730 | |||
654 | if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) { | 731 | if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) { |
655 | ret = snd_soc_dapm_new_controls( | 732 | ret = snd_soc_dapm_new_controls( |
656 | dapm, aic311x_dapm_widgets, | 733 | dapm, aic311x_dapm_widgets, |
@@ -1115,12 +1192,12 @@ static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { | |||
1115 | .suspend_bias_off = true, | 1192 | .suspend_bias_off = true, |
1116 | 1193 | ||
1117 | .component_driver = { | 1194 | .component_driver = { |
1118 | .controls = aic31xx_snd_controls, | 1195 | .controls = common31xx_snd_controls, |
1119 | .num_controls = ARRAY_SIZE(aic31xx_snd_controls), | 1196 | .num_controls = ARRAY_SIZE(common31xx_snd_controls), |
1120 | .dapm_widgets = aic31xx_dapm_widgets, | 1197 | .dapm_widgets = common31xx_dapm_widgets, |
1121 | .num_dapm_widgets = ARRAY_SIZE(aic31xx_dapm_widgets), | 1198 | .num_dapm_widgets = ARRAY_SIZE(common31xx_dapm_widgets), |
1122 | .dapm_routes = aic31xx_audio_map, | 1199 | .dapm_routes = common31xx_audio_map, |
1123 | .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), | 1200 | .num_dapm_routes = ARRAY_SIZE(common31xx_audio_map), |
1124 | }, | 1201 | }, |
1125 | }; | 1202 | }; |
1126 | 1203 | ||
@@ -1131,6 +1208,21 @@ static const struct snd_soc_dai_ops aic31xx_dai_ops = { | |||
1131 | .digital_mute = aic31xx_dac_mute, | 1208 | .digital_mute = aic31xx_dac_mute, |
1132 | }; | 1209 | }; |
1133 | 1210 | ||
1211 | static struct snd_soc_dai_driver dac31xx_dai_driver[] = { | ||
1212 | { | ||
1213 | .name = "tlv32dac31xx-hifi", | ||
1214 | .playback = { | ||
1215 | .stream_name = "Playback", | ||
1216 | .channels_min = 1, | ||
1217 | .channels_max = 2, | ||
1218 | .rates = AIC31XX_RATES, | ||
1219 | .formats = AIC31XX_FORMATS, | ||
1220 | }, | ||
1221 | .ops = &aic31xx_dai_ops, | ||
1222 | .symmetric_rates = 1, | ||
1223 | } | ||
1224 | }; | ||
1225 | |||
1134 | static struct snd_soc_dai_driver aic31xx_dai_driver[] = { | 1226 | static struct snd_soc_dai_driver aic31xx_dai_driver[] = { |
1135 | { | 1227 | { |
1136 | .name = "tlv320aic31xx-hifi", | 1228 | .name = "tlv320aic31xx-hifi", |
@@ -1261,9 +1353,16 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, | |||
1261 | if (ret) | 1353 | if (ret) |
1262 | return ret; | 1354 | return ret; |
1263 | 1355 | ||
1264 | return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, | 1356 | if (aic31xx->pdata.codec_type & DAC31XX_BIT) |
1265 | aic31xx_dai_driver, | 1357 | return snd_soc_register_codec(&i2c->dev, |
1266 | ARRAY_SIZE(aic31xx_dai_driver)); | 1358 | &soc_codec_driver_aic31xx, |
1359 | dac31xx_dai_driver, | ||
1360 | ARRAY_SIZE(dac31xx_dai_driver)); | ||
1361 | else | ||
1362 | return snd_soc_register_codec(&i2c->dev, | ||
1363 | &soc_codec_driver_aic31xx, | ||
1364 | aic31xx_dai_driver, | ||
1365 | ARRAY_SIZE(aic31xx_dai_driver)); | ||
1267 | } | 1366 | } |
1268 | 1367 | ||
1269 | static int aic31xx_i2c_remove(struct i2c_client *i2c) | 1368 | static int aic31xx_i2c_remove(struct i2c_client *i2c) |
@@ -1279,6 +1378,7 @@ static const struct i2c_device_id aic31xx_i2c_id[] = { | |||
1279 | { "tlv320aic3110", AIC3110 }, | 1378 | { "tlv320aic3110", AIC3110 }, |
1280 | { "tlv320aic3120", AIC3120 }, | 1379 | { "tlv320aic3120", AIC3120 }, |
1281 | { "tlv320aic3111", AIC3111 }, | 1380 | { "tlv320aic3111", AIC3111 }, |
1381 | { "tlv320dac3100", DAC3100 }, | ||
1282 | { } | 1382 | { } |
1283 | }; | 1383 | }; |
1284 | MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); | 1384 | MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); |
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h index ac9b146526eb..5acd5b69fb83 100644 --- a/sound/soc/codecs/tlv320aic31xx.h +++ b/sound/soc/codecs/tlv320aic31xx.h | |||
@@ -24,12 +24,14 @@ | |||
24 | 24 | ||
25 | #define AIC31XX_STEREO_CLASS_D_BIT 0x1 | 25 | #define AIC31XX_STEREO_CLASS_D_BIT 0x1 |
26 | #define AIC31XX_MINIDSP_BIT 0x2 | 26 | #define AIC31XX_MINIDSP_BIT 0x2 |
27 | #define DAC31XX_BIT 0x4 | ||
27 | 28 | ||
28 | enum aic31xx_type { | 29 | enum aic31xx_type { |
29 | AIC3100 = 0, | 30 | AIC3100 = 0, |
30 | AIC3110 = AIC31XX_STEREO_CLASS_D_BIT, | 31 | AIC3110 = AIC31XX_STEREO_CLASS_D_BIT, |
31 | AIC3120 = AIC31XX_MINIDSP_BIT, | 32 | AIC3120 = AIC31XX_MINIDSP_BIT, |
32 | AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT), | 33 | AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT), |
34 | DAC3100 = DAC31XX_BIT, | ||
33 | }; | 35 | }; |
34 | 36 | ||
35 | struct aic31xx_pdata { | 37 | struct aic31xx_pdata { |