22 #include <linux/module.h>
28 #include <linux/slab.h>
41 #define TWL6040_RATES SNDRV_PCM_RATE_8000_96000
42 #define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
44 #define TWL6040_OUTHS_0dB 0x00
45 #define TWL6040_OUTHS_M30dB 0x0F
46 #define TWL6040_OUTHF_0dB 0x03
47 #define TWL6040_OUTHF_M52dB 0x1D
50 #define TWL6040_REG_SW_SHADOW 0x2F
51 #define TWL6040_CACHEREGNUM (TWL6040_REG_SW_SHADOW + 1)
54 #define TWL6040_EAR_PATH_ENABLE 0x01
138 static const int twl6040_restore_list[] = {
154 static unsigned int lp_rates[] = {
166 static unsigned int hp_rates[] = {
175 { .count =
ARRAY_SIZE(lp_rates), .list = lp_rates, },
176 { .count =
ARRAY_SIZE(hp_rates), .list = hp_rates, },
196 static inline void twl6040_write_reg_cache(
struct snd_soc_codec *codec,
209 static int twl6040_read_reg_volatile(
struct snd_soc_codec *codec,
220 twl6040_write_reg_cache(codec, reg, value);
222 value = twl6040_read_reg_cache(codec, reg);
232 unsigned int reg,
unsigned int value)
239 twl6040_write_reg_cache(codec, reg, value);
252 val = twl6040_get_revid(twl6040);
278 static void twl6040_restore_regs(
struct snd_soc_codec *codec)
283 for (i = 0; i <
ARRAY_SIZE(twl6040_restore_list); i++) {
284 reg = twl6040_restore_list[
i];
285 twl6040_write(codec, reg, cache[reg]);
290 static int headset_power_mode(
struct snd_soc_codec *codec,
int high_perf)
349 ret = headset_power_mode(codec, 1);
360 static void twl6040_hs_jack_report(
struct snd_soc_codec *codec,
363 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
381 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
387 twl6040_hs_jack_report(codec, hs_jack->
jack, hs_jack->
report);
398 twl6040_hs_jack_report(codec, hs_jack->
jack, hs_jack->
report);
405 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
413 static int twl6040_soc_dapm_put_vibra_enum(
struct snd_kcontrol *kcontrol,
423 val = twl6040_read_reg_volatile(codec, e->
reg);
467 static const char *twl6040_amicl_texts[] =
468 {
"Headset Mic",
"Main Mic",
"Aux/FM Left",
"Off"};
471 static const char *twl6040_amicr_texts[] =
472 {
"Headset Mic",
"Sub Mic",
"Aux/FM Right",
"Off"};
474 static const struct soc_enum twl6040_enum[] = {
479 static const char *twl6040_hs_texts[] = {
480 "Off",
"HS DAC",
"Line-In amp"
483 static const struct soc_enum twl6040_hs_enum[] = {
490 static const char *twl6040_hf_texts[] = {
491 "Off",
"HF DAC",
"Line-In amp"
494 static const struct soc_enum twl6040_hf_enum[] = {
501 static const char *twl6040_vibrapath_texts[] = {
502 "Input FF",
"Audio PDM"
505 static const struct soc_enum twl6040_vibra_enum[] = {
508 twl6040_vibrapath_texts),
511 twl6040_vibrapath_texts),
547 twl6040_soc_dapm_put_vibra_enum);
552 twl6040_soc_dapm_put_vibra_enum);
555 static const char *twl6040_power_mode_texts[] = {
556 "Low-Power",
"High-Performance",
559 static const struct soc_enum twl6040_power_mode_enum =
561 twl6040_power_mode_texts);
563 static int twl6040_headset_power_get_enum(
struct snd_kcontrol *kcontrol,
567 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
574 static int twl6040_headset_power_put_enum(
struct snd_kcontrol *kcontrol,
578 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
579 int high_perf = ucontrol->
value.enumerated.item[0];
583 ret = headset_power_mode(codec, high_perf);
591 static int twl6040_pll_get_enum(
struct snd_kcontrol *kcontrol,
595 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
602 static int twl6040_pll_put_enum(
struct snd_kcontrol *kcontrol,
606 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
637 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
684 SOC_ENUM_EXT(
"Headset Power Mode", twl6040_power_mode_enum,
685 twl6040_headset_power_get_enum,
686 twl6040_headset_power_put_enum),
689 twl6040_pll_get_enum, twl6040_pll_put_enum),
762 &vibral_mux_controls),
764 &vibrar_mux_controls),
767 &ep_path_enable_control),
769 &auxl_switch_control),
771 &auxr_switch_control),
784 twl6040_ep_drv_event,
796 twl6040_hs_dac_event,
809 {
"HSDAC Left",
NULL,
"Legacy Playback"},
810 {
"HSDAC Left",
NULL,
"Headset Playback"},
811 {
"HSDAC Right",
NULL,
"Legacy Playback"},
812 {
"HSDAC Right",
NULL,
"Headset Playback"},
814 {
"HFDAC Left",
NULL,
"Legacy Playback"},
815 {
"HFDAC Left",
NULL,
"Handsfree Playback"},
816 {
"HFDAC Right",
NULL,
"Legacy Playback"},
817 {
"HFDAC Right",
NULL,
"Handsfree Playback"},
819 {
"VIBRA DAC",
NULL,
"Legacy Playback"},
820 {
"VIBRA DAC",
NULL,
"Vibra Playback"},
823 {
"Legacy Capture" ,
NULL,
"ADC Left"},
824 {
"Capture",
NULL,
"ADC Left"},
825 {
"Legacy Capture",
NULL,
"ADC Right"},
826 {
"Capture" ,
NULL,
"ADC Right"},
829 {
"Analog Left Capture Route",
"Headset Mic",
"HSMIC"},
830 {
"Analog Left Capture Route",
"Main Mic",
"MAINMIC"},
831 {
"Analog Left Capture Route",
"Aux/FM Left",
"AFML"},
833 {
"Analog Right Capture Route",
"Headset Mic",
"HSMIC"},
834 {
"Analog Right Capture Route",
"Sub Mic",
"SUBMIC"},
835 {
"Analog Right Capture Route",
"Aux/FM Right",
"AFMR"},
837 {
"MicAmpL",
NULL,
"Analog Left Capture Route"},
838 {
"MicAmpR",
NULL,
"Analog Right Capture Route"},
840 {
"ADC Left",
NULL,
"MicAmpL"},
841 {
"ADC Right",
NULL,
"MicAmpR"},
844 {
"AFMAmpL",
NULL,
"AFML"},
845 {
"AFMAmpR",
NULL,
"AFMR"},
847 {
"HSDAC Left",
NULL,
"HSDAC Power"},
848 {
"HSDAC Right",
NULL,
"HSDAC Power"},
850 {
"Headset Left Playback",
"HS DAC",
"HSDAC Left"},
851 {
"Headset Left Playback",
"Line-In amp",
"AFMAmpL"},
853 {
"Headset Right Playback",
"HS DAC",
"HSDAC Right"},
854 {
"Headset Right Playback",
"Line-In amp",
"AFMAmpR"},
856 {
"HS Left Driver",
NULL,
"Headset Left Playback"},
857 {
"HS Right Driver",
NULL,
"Headset Right Playback"},
859 {
"HSOL",
NULL,
"HS Left Driver"},
860 {
"HSOR",
NULL,
"HS Right Driver"},
863 {
"Earphone Playback",
"Switch",
"HSDAC Left"},
864 {
"Earphone Driver",
NULL,
"Earphone Playback"},
865 {
"EP",
NULL,
"Earphone Driver"},
867 {
"Handsfree Left Playback",
"HF DAC",
"HFDAC Left"},
868 {
"Handsfree Left Playback",
"Line-In amp",
"AFMAmpL"},
870 {
"Handsfree Right Playback",
"HF DAC",
"HFDAC Right"},
871 {
"Handsfree Right Playback",
"Line-In amp",
"AFMAmpR"},
873 {
"HF Left PGA",
NULL,
"Handsfree Left Playback"},
874 {
"HF Right PGA",
NULL,
"Handsfree Right Playback"},
876 {
"HF Left Driver",
NULL,
"HF Left PGA"},
877 {
"HF Right Driver",
NULL,
"HF Right PGA"},
879 {
"HFL",
NULL,
"HF Left Driver"},
880 {
"HFR",
NULL,
"HF Right Driver"},
882 {
"AUXL Playback",
"Switch",
"HF Left PGA"},
883 {
"AUXR Playback",
"Switch",
"HF Right PGA"},
885 {
"AUXL",
NULL,
"AUXL Playback"},
886 {
"AUXR",
NULL,
"AUXR Playback"},
889 {
"Vibra Left Playback",
"Audio PDM",
"VIBRA DAC"},
890 {
"Vibra Right Playback",
"Audio PDM",
"VIBRA DAC"},
892 {
"Vibra Left Driver",
NULL,
"Vibra Left Playback"},
893 {
"Vibra Right Driver",
NULL,
"Vibra Right Playback"},
894 {
"Vibra Left Driver",
NULL,
"Vibra Left Control"},
895 {
"Vibra Right Driver",
NULL,
"Vibra Right Control"},
897 {
"VIBRAL",
NULL,
"Vibra Left Driver"},
898 {
"VIBRAR",
NULL,
"Vibra Right Driver"},
901 static int twl6040_set_bias_level(
struct snd_soc_codec *codec,
905 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
923 twl6040_restore_regs(codec);
946 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
960 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
971 dev_err(codec->
dev,
"HPPLL does not support rate %d\n",
985 dev_err(codec->
dev,
"unsupported rate %d\n", rate);
997 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1002 "no mclk configured, call set_sysclk() on init\n");
1008 dev_err(codec->
dev,
"Can not set PLL (%d)\n", ret);
1015 static int twl6040_set_dai_sysclk(
struct snd_soc_dai *codec_dai,
1016 int clk_id,
unsigned int freq,
int dir)
1019 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1028 dev_err(codec->
dev,
"unknown clk_id %d\n", clk_id);
1036 .startup = twl6040_startup,
1037 .hw_params = twl6040_hw_params,
1038 .prepare = twl6040_prepare,
1039 .set_sysclk = twl6040_set_dai_sysclk,
1044 .name =
"twl6040-legacy",
1046 .stream_name =
"Legacy Playback",
1053 .stream_name =
"Legacy Capture",
1059 .ops = &twl6040_dai_ops,
1062 .name =
"twl6040-ul",
1064 .stream_name =
"Capture",
1070 .ops = &twl6040_dai_ops,
1073 .name =
"twl6040-dl1",
1075 .stream_name =
"Headset Playback",
1081 .ops = &twl6040_dai_ops,
1084 .name =
"twl6040-dl2",
1086 .stream_name =
"Handsfree Playback",
1092 .ops = &twl6040_dai_ops,
1095 .name =
"twl6040-vib",
1097 .stream_name =
"Vibra Playback",
1103 .ops = &twl6040_dai_ops,
1118 twl6040_set_bias_level(codec, codec->
dapm.suspend_bias_level);
1123 #define twl6040_suspend NULL
1124 #define twl6040_resume NULL
1138 snd_soc_codec_set_drvdata(codec, priv);
1177 0,
"twl6040_irq_plug", codec);
1179 dev_err(codec->
dev,
"PLUG IRQ request failed: %d\n", ret);
1183 twl6040_init_chip(codec);
1201 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1212 .probe = twl6040_probe,
1213 .remove = twl6040_remove,
1216 .read = twl6040_read_reg_cache,
1217 .write = twl6040_write,
1218 .set_bias_level = twl6040_set_bias_level,
1220 .reg_word_size =
sizeof(
u8),
1226 .dapm_widgets = twl6040_dapm_widgets,
1227 .num_dapm_widgets =
ARRAY_SIZE(twl6040_dapm_widgets),
1228 .dapm_routes = intercon,
1246 .name =
"twl6040-codec",
1249 .probe = twl6040_codec_probe,