35 #include <linux/module.h>
40 #include <linux/i2c.h>
44 #include <linux/slab.h>
55 #define AIC3X_NUM_SUPPLIES 4
84 #define AIC3X_MODEL_3X 0
85 #define AIC3X_MODEL_33 1
86 #define AIC3X_MODEL_3007 2
97 0x00, 0x00, 0x00, 0x10,
98 0x04, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x01,
100 0x00, 0x00, 0x00, 0x80,
101 0x80, 0xff, 0xff, 0x78,
102 0x78, 0x78, 0x78, 0x78,
103 0x78, 0x00, 0x00, 0xfe,
104 0x00, 0x00, 0xfe, 0x00,
105 0x18, 0x18, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x80,
108 0x80, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x04,
110 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x04, 0x00,
112 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x04, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00,
115 0x04, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x02, 0x00,
123 0x00, 0x00, 0x00, 0x00,
127 #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
128 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
129 .info = snd_soc_info_volsw, \
130 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw_aic3x, \
131 .private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) }
137 static int snd_soc_dapm_put_volsw_aic3x(
struct snd_kcontrol *kcontrol,
144 unsigned int reg = mc->
reg;
147 unsigned int mask = (1 << fls(
max)) - 1;
149 unsigned short val, val_mask;
154 val = (ucontrol->
value.integer.value[0] &
mask);
162 val_mask =
mask << shift;
177 path->
connect = invert ? 0 : 1;
180 path->
connect = invert ? 1 : 0;
198 static const char *aic3x_left_dac_mux[] = {
"DAC_L1",
"DAC_L3",
"DAC_L2" };
199 static const char *aic3x_right_dac_mux[] = {
"DAC_R1",
"DAC_R3",
"DAC_R2" };
200 static const char *aic3x_left_hpcom_mux[] =
201 {
"differential of HPLOUT",
"constant VCM",
"single-ended" };
202 static const char *aic3x_right_hpcom_mux[] =
203 {
"differential of HPROUT",
"constant VCM",
"single-ended",
204 "differential of HPLCOM",
"external feedback" };
205 static const char *aic3x_linein_mode_mux[] = {
"single-ended",
"differential" };
206 static const char *aic3x_adc_hpf[] =
207 {
"Disabled",
"0.0045xFs",
"0.0125xFs",
"0.025xFs" };
211 #define LHPCOM_ENUM 2
212 #define RHPCOM_ENUM 3
213 #define LINE1L_2_L_ENUM 4
214 #define LINE1L_2_R_ENUM 5
215 #define LINE1R_2_L_ENUM 6
216 #define LINE1R_2_R_ENUM 7
217 #define LINE2L_ENUM 8
218 #define LINE2R_ENUM 9
219 #define ADC_HPF_ENUM 10
221 static const struct soc_enum aic3x_enum[] = {
235 static const char *aic3x_agc_level[] =
236 {
"-5.5dB",
"-8dB",
"-10dB",
"-12dB",
"-14dB",
"-17dB",
"-20dB",
"-24dB" };
237 static const struct soc_enum aic3x_agc_level_enum[] = {
242 static const char *aic3x_agc_attack[] = {
"8ms",
"11ms",
"16ms",
"20ms" };
243 static const struct soc_enum aic3x_agc_attack_enum[] = {
248 static const char *aic3x_agc_decay[] = {
"100ms",
"200ms",
"400ms",
"500ms" };
249 static const struct soc_enum aic3x_agc_decay_enum[] = {
326 0, 118, 1, output_stage_tlv),
329 0, 118, 1, output_stage_tlv),
332 0, 118, 1, output_stage_tlv),
336 0, 118, 1, output_stage_tlv),
339 0, 118, 1, output_stage_tlv),
342 0, 118, 1, output_stage_tlv),
346 0, 118, 1, output_stage_tlv),
349 0, 118, 1, output_stage_tlv),
352 0, 118, 1, output_stage_tlv),
356 0, 118, 1, output_stage_tlv),
359 0, 118, 1, output_stage_tlv),
362 0, 118, 1, output_stage_tlv),
378 SOC_ENUM(
"Left AGC Target level", aic3x_agc_level_enum[0]),
379 SOC_ENUM(
"Right AGC Target level", aic3x_agc_level_enum[1]),
380 SOC_ENUM(
"Left AGC Attack time", aic3x_agc_attack_enum[0]),
381 SOC_ENUM(
"Right AGC Attack time", aic3x_agc_attack_enum[1]),
382 SOC_ENUM(
"Left AGC Decay time", aic3x_agc_decay_enum[0]),
383 SOC_ENUM(
"Right AGC Decay time", aic3x_agc_decay_enum[1]),
532 &aic3x_left_dac_mux_controls),
534 &aic3x_left_hpcom_mux_controls),
542 &aic3x_right_dac_mux_controls),
544 &aic3x_right_hpcom_mux_controls),
555 &aic3x_left_pga_mixer_controls[0],
558 &aic3x_left_line1l_mux_controls),
560 &aic3x_left_line1r_mux_controls),
562 &aic3x_left_line2_mux_controls),
568 &aic3x_right_pga_mixer_controls[0],
571 &aic3x_right_line1l_mux_controls),
573 &aic3x_right_line1r_mux_controls),
575 &aic3x_right_line2_mux_controls),
608 &aic3x_left_line_mixer_controls[0],
611 &aic3x_right_line_mixer_controls[0],
614 &aic3x_mono_mixer_controls[0],
617 &aic3x_left_hp_mixer_controls[0],
620 &aic3x_right_hp_mixer_controls[0],
623 &aic3x_left_hpcom_mixer_controls[0],
626 &aic3x_right_hpcom_mixer_controls[0],
627 ARRAY_SIZE(aic3x_right_hpcom_mixer_controls)),
664 {
"Left Line1L Mux",
"single-ended",
"LINE1L"},
665 {
"Left Line1L Mux",
"differential",
"LINE1L"},
667 {
"Left Line2L Mux",
"single-ended",
"LINE2L"},
668 {
"Left Line2L Mux",
"differential",
"LINE2L"},
670 {
"Left PGA Mixer",
"Line1L Switch",
"Left Line1L Mux"},
671 {
"Left PGA Mixer",
"Line1R Switch",
"Left Line1R Mux"},
672 {
"Left PGA Mixer",
"Line2L Switch",
"Left Line2L Mux"},
673 {
"Left PGA Mixer",
"Mic3L Switch",
"MIC3L"},
674 {
"Left PGA Mixer",
"Mic3R Switch",
"MIC3R"},
676 {
"Left ADC",
NULL,
"Left PGA Mixer"},
677 {
"Left ADC",
NULL,
"GPIO1 dmic modclk"},
680 {
"Right Line1R Mux",
"single-ended",
"LINE1R"},
681 {
"Right Line1R Mux",
"differential",
"LINE1R"},
683 {
"Right Line2R Mux",
"single-ended",
"LINE2R"},
684 {
"Right Line2R Mux",
"differential",
"LINE2R"},
686 {
"Right PGA Mixer",
"Line1L Switch",
"Right Line1L Mux"},
687 {
"Right PGA Mixer",
"Line1R Switch",
"Right Line1R Mux"},
688 {
"Right PGA Mixer",
"Line2R Switch",
"Right Line2R Mux"},
689 {
"Right PGA Mixer",
"Mic3L Switch",
"MIC3L"},
690 {
"Right PGA Mixer",
"Mic3R Switch",
"MIC3R"},
692 {
"Right ADC",
NULL,
"Right PGA Mixer"},
693 {
"Right ADC",
NULL,
"GPIO1 dmic modclk"},
699 {
"GPIO1 dmic modclk",
NULL,
"DMic Rate 128"},
700 {
"GPIO1 dmic modclk",
NULL,
"DMic Rate 64"},
701 {
"GPIO1 dmic modclk",
NULL,
"DMic Rate 32"},
704 {
"Left DAC Mux",
"DAC_L1",
"Left DAC"},
705 {
"Left DAC Mux",
"DAC_L2",
"Left DAC"},
706 {
"Left DAC Mux",
"DAC_L3",
"Left DAC"},
709 {
"Right DAC Mux",
"DAC_R1",
"Right DAC"},
710 {
"Right DAC Mux",
"DAC_R2",
"Right DAC"},
711 {
"Right DAC Mux",
"DAC_R3",
"Right DAC"},
714 {
"Left Line Mixer",
"Line2L Bypass Switch",
"Left Line2L Mux"},
715 {
"Left Line Mixer",
"PGAL Bypass Switch",
"Left PGA Mixer"},
716 {
"Left Line Mixer",
"DACL1 Switch",
"Left DAC Mux"},
717 {
"Left Line Mixer",
"Line2R Bypass Switch",
"Right Line2R Mux"},
718 {
"Left Line Mixer",
"PGAR Bypass Switch",
"Right PGA Mixer"},
719 {
"Left Line Mixer",
"DACR1 Switch",
"Right DAC Mux"},
721 {
"Left Line Out",
NULL,
"Left Line Mixer"},
722 {
"Left Line Out",
NULL,
"Left DAC Mux"},
723 {
"LLOUT",
NULL,
"Left Line Out"},
726 {
"Right Line Mixer",
"Line2L Bypass Switch",
"Left Line2L Mux"},
727 {
"Right Line Mixer",
"PGAL Bypass Switch",
"Left PGA Mixer"},
728 {
"Right Line Mixer",
"DACL1 Switch",
"Left DAC Mux"},
729 {
"Right Line Mixer",
"Line2R Bypass Switch",
"Right Line2R Mux"},
730 {
"Right Line Mixer",
"PGAR Bypass Switch",
"Right PGA Mixer"},
731 {
"Right Line Mixer",
"DACR1 Switch",
"Right DAC Mux"},
733 {
"Right Line Out",
NULL,
"Right Line Mixer"},
734 {
"Right Line Out",
NULL,
"Right DAC Mux"},
735 {
"RLOUT",
NULL,
"Right Line Out"},
738 {
"Mono Mixer",
"Line2L Bypass Switch",
"Left Line2L Mux"},
739 {
"Mono Mixer",
"PGAL Bypass Switch",
"Left PGA Mixer"},
740 {
"Mono Mixer",
"DACL1 Switch",
"Left DAC Mux"},
741 {
"Mono Mixer",
"Line2R Bypass Switch",
"Right Line2R Mux"},
742 {
"Mono Mixer",
"PGAR Bypass Switch",
"Right PGA Mixer"},
743 {
"Mono Mixer",
"DACR1 Switch",
"Right DAC Mux"},
745 {
"Mono Out",
NULL,
"Mono Mixer"},
746 {
"MONO_LOUT",
NULL,
"Mono Out"},
749 {
"Left HP Mixer",
"Line2L Bypass Switch",
"Left Line2L Mux"},
750 {
"Left HP Mixer",
"PGAL Bypass Switch",
"Left PGA Mixer"},
751 {
"Left HP Mixer",
"DACL1 Switch",
"Left DAC Mux"},
752 {
"Left HP Mixer",
"Line2R Bypass Switch",
"Right Line2R Mux"},
753 {
"Left HP Mixer",
"PGAR Bypass Switch",
"Right PGA Mixer"},
754 {
"Left HP Mixer",
"DACR1 Switch",
"Right DAC Mux"},
756 {
"Left HP Out",
NULL,
"Left HP Mixer"},
757 {
"Left HP Out",
NULL,
"Left DAC Mux"},
758 {
"HPLOUT",
NULL,
"Left HP Out"},
761 {
"Right HP Mixer",
"Line2L Bypass Switch",
"Left Line2L Mux"},
762 {
"Right HP Mixer",
"PGAL Bypass Switch",
"Left PGA Mixer"},
763 {
"Right HP Mixer",
"DACL1 Switch",
"Left DAC Mux"},
764 {
"Right HP Mixer",
"Line2R Bypass Switch",
"Right Line2R Mux"},
765 {
"Right HP Mixer",
"PGAR Bypass Switch",
"Right PGA Mixer"},
766 {
"Right HP Mixer",
"DACR1 Switch",
"Right DAC Mux"},
768 {
"Right HP Out",
NULL,
"Right HP Mixer"},
769 {
"Right HP Out",
NULL,
"Right DAC Mux"},
770 {
"HPROUT",
NULL,
"Right HP Out"},
773 {
"Left HPCOM Mixer",
"Line2L Bypass Switch",
"Left Line2L Mux"},
774 {
"Left HPCOM Mixer",
"PGAL Bypass Switch",
"Left PGA Mixer"},
775 {
"Left HPCOM Mixer",
"DACL1 Switch",
"Left DAC Mux"},
776 {
"Left HPCOM Mixer",
"Line2R Bypass Switch",
"Right Line2R Mux"},
777 {
"Left HPCOM Mixer",
"PGAR Bypass Switch",
"Right PGA Mixer"},
778 {
"Left HPCOM Mixer",
"DACR1 Switch",
"Right DAC Mux"},
780 {
"Left HPCOM Mux",
"differential of HPLOUT",
"Left HP Mixer"},
781 {
"Left HPCOM Mux",
"constant VCM",
"Left HPCOM Mixer"},
782 {
"Left HPCOM Mux",
"single-ended",
"Left HPCOM Mixer"},
783 {
"Left HP Com",
NULL,
"Left HPCOM Mux"},
784 {
"HPLCOM",
NULL,
"Left HP Com"},
787 {
"Right HPCOM Mixer",
"Line2L Bypass Switch",
"Left Line2L Mux"},
788 {
"Right HPCOM Mixer",
"PGAL Bypass Switch",
"Left PGA Mixer"},
789 {
"Right HPCOM Mixer",
"DACL1 Switch",
"Left DAC Mux"},
790 {
"Right HPCOM Mixer",
"Line2R Bypass Switch",
"Right Line2R Mux"},
791 {
"Right HPCOM Mixer",
"PGAR Bypass Switch",
"Right PGA Mixer"},
792 {
"Right HPCOM Mixer",
"DACR1 Switch",
"Right DAC Mux"},
794 {
"Right HPCOM Mux",
"differential of HPROUT",
"Right HP Mixer"},
795 {
"Right HPCOM Mux",
"constant VCM",
"Right HPCOM Mixer"},
796 {
"Right HPCOM Mux",
"single-ended",
"Right HPCOM Mixer"},
797 {
"Right HPCOM Mux",
"differential of HPLCOM",
"Left HPCOM Mixer"},
798 {
"Right HPCOM Mux",
"external feedback",
"Right HPCOM Mixer"},
799 {
"Right HP Com",
NULL,
"Right HPCOM Mux"},
800 {
"HPRCOM",
NULL,
"Right HP Com"},
805 {
"Left Class-D Out",
NULL,
"Left Line Out"},
806 {
"Right Class-D Out",
NULL,
"Left Line Out"},
807 {
"SPOP",
NULL,
"Left Class-D Out"},
808 {
"SPOM",
NULL,
"Right Class-D Out"},
813 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
837 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
838 int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
839 u8 data,
j,
r,
p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
861 fsref = (
params_rate(params) % 11025 == 0) ? 44100 : 48000;
865 for (pll_q = 2; pll_q < 18; pll_q++)
866 if (aic3x->
sysclk / (128 * pll_q) == fsref) {
911 codec_clk = (2048 * fsref) / (aic3x->
sysclk / 1000);
913 for (r = 1; r <= 16; r++)
914 for (p = 1; p <= 8; p++) {
915 for (j = 4; j <= 55; j++) {
920 int tmp_clk = (1000 * j *
r) / p;
925 if (
abs(codec_clk - tmp_clk) <
926 abs(codec_clk - last_clk)) {
927 pll_j =
j; pll_d = 0;
928 pll_r =
r; pll_p =
p;
933 if (tmp_clk == codec_clk)
939 for (p = 1; p <= 8; p++) {
940 j = codec_clk * p / 1000;
946 d = ((2048 * p * fsref) - j * aic3x->
sysclk)
947 * 100 / (aic3x->
sysclk/100);
949 clk = (10000 * j +
d) / (10 * p);
953 if (
abs(codec_clk - clk) <
abs(codec_clk - last_clk)) {
954 pll_j =
j; pll_d =
d; pll_r = 1; pll_p =
p;
959 if (clk == codec_clk)
998 static int aic3x_set_dai_sysclk(
struct snd_soc_dai *codec_dai,
999 int clk_id,
unsigned int freq,
int dir)
1002 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1014 static int aic3x_set_dai_fmt(
struct snd_soc_dai *codec_dai,
1018 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1019 u8 iface_areg, iface_breg;
1050 iface_breg |= (0x01 << 6);
1053 iface_breg |= (0x02 << 6);
1056 iface_breg |= (0x03 << 6);
1094 unsigned long event,
void *data)
1107 aic3x->
codec->cache_sync = 1;
1115 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1142 aic3x_init_3007(codec);
1162 static int aic3x_set_bias_level(
struct snd_soc_codec *codec,
1165 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1180 aic3x_set_power(codec, 1);
1190 aic3x_set_power(codec, 0);
1198 #define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
1199 #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1200 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
1203 .hw_params = aic3x_hw_params,
1204 .digital_mute = aic3x_mute,
1205 .set_sysclk = aic3x_set_dai_sysclk,
1206 .set_fmt = aic3x_set_dai_fmt,
1210 .name =
"tlv320aic3x-hifi",
1212 .stream_name =
"Playback",
1218 .stream_name =
"Capture",
1223 .ops = &aic3x_dai_ops,
1224 .symmetric_rates = 1,
1247 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1309 aic3x_init_3007(codec);
1316 static bool aic3x_is_shared_reset(
struct aic3x_priv *aic3x)
1331 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1334 INIT_LIST_HEAD(&aic3x->
list);
1339 dev_err(codec->
dev,
"Failed to set cache I/O: %d\n", ret);
1344 !aic3x_is_shared_reset(aic3x)) {
1352 aic3x->
supplies[i].supply = aic3x_supply_names[i];
1357 dev_err(codec->
dev,
"Failed to request supplies: %d\n", ret);
1361 aic3x->
disable_nb[
i].nb.notifier_call = aic3x_regulator_event;
1367 "Failed to request regulator notifier: %d\n",
1379 (aic3x->
setup->gpio_func[0] & 0xf) << 4);
1381 (aic3x->
setup->gpio_func[1] & 0xf) << 4);
1389 aic3x_add_widgets(codec);
1390 list_add(&aic3x->
list, &reset_list);
1401 !aic3x_is_shared_reset(aic3x))
1409 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1415 !aic3x_is_shared_reset(aic3x)) {
1428 .set_bias_level = aic3x_set_bias_level,
1429 .idle_bias_off =
true,
1431 .reg_word_size =
sizeof(
u8),
1433 .
probe = aic3x_probe,
1434 .
remove = aic3x_remove,
1456 static int aic3x_i2c_probe(
struct i2c_client *i2c,
1466 if (aic3x ==
NULL) {
1467 dev_err(&i2c->
dev,
"failed to create private data\n");
1473 i2c_set_clientdata(i2c, aic3x);
1480 if (ai3x_setup ==
NULL) {
1481 dev_err(&i2c->
dev,
"failed to create private data\n");
1485 ret = of_get_named_gpio(np,
"gpio-reset", 0);
1493 aic3x->
setup = ai3x_setup;
1500 aic3x->
model =
id->driver_data;
1503 &soc_codec_dev_aic3x, &aic3x_dai, 1);
1513 #if defined(CONFIG_OF)
1514 static const struct of_device_id tlv320aic3x_of_match[] = {
1522 static struct i2c_driver aic3x_i2c_driver = {
1524 .name =
"tlv320aic3x-codec",
1528 .probe = aic3x_i2c_probe,
1529 .remove = aic3x_i2c_remove,
1530 .id_table = aic3x_i2c_id,