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 /sound/soc/codecs | |
| 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>
Diffstat (limited to 'sound/soc/codecs')
| -rw-r--r-- | sound/soc/codecs/tlv320aic31xx.c | 212 | ||||
| -rw-r--r-- | sound/soc/codecs/tlv320aic31xx.h | 2 |
2 files changed, 158 insertions, 56 deletions
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 { |
