diff options
Diffstat (limited to 'sound/soc/codecs/tas2552.c')
-rw-r--r-- | sound/soc/codecs/tas2552.c | 70 |
1 files changed, 50 insertions, 20 deletions
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 23b32960ff1d..f039dc825971 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c | |||
@@ -78,6 +78,44 @@ struct tas2552_data { | |||
78 | unsigned int mclk; | 78 | unsigned int mclk; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | /* Input mux controls */ | ||
82 | static const char *tas2552_input_texts[] = { | ||
83 | "Digital", "Analog" | ||
84 | }; | ||
85 | |||
86 | static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum, TAS2552_CFG_3, 7, | ||
87 | tas2552_input_texts); | ||
88 | |||
89 | static const struct snd_kcontrol_new tas2552_input_mux_control[] = { | ||
90 | SOC_DAPM_ENUM("Input selection", tas2552_input_mux_enum) | ||
91 | }; | ||
92 | |||
93 | static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] = | ||
94 | { | ||
95 | SND_SOC_DAPM_INPUT("IN"), | ||
96 | |||
97 | /* MUX Controls */ | ||
98 | SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM, 0, 0, | ||
99 | tas2552_input_mux_control), | ||
100 | |||
101 | SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), | ||
102 | SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), | ||
103 | SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0), | ||
104 | SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0), | ||
105 | |||
106 | SND_SOC_DAPM_OUTPUT("OUT") | ||
107 | }; | ||
108 | |||
109 | static const struct snd_soc_dapm_route tas2552_audio_map[] = { | ||
110 | {"DAC", NULL, "DAC IN"}, | ||
111 | {"Input selection", "Digital", "DAC"}, | ||
112 | {"Input selection", "Analog", "IN"}, | ||
113 | {"ClassD", NULL, "Input selection"}, | ||
114 | {"OUT", NULL, "ClassD"}, | ||
115 | {"ClassD", NULL, "PLL"}, | ||
116 | }; | ||
117 | |||
118 | #ifdef CONFIG_PM_RUNTIME | ||
81 | static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown) | 119 | static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown) |
82 | { | 120 | { |
83 | u8 cfg1_reg; | 121 | u8 cfg1_reg; |
@@ -90,6 +128,7 @@ static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown) | |||
90 | snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1, | 128 | snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1, |
91 | TAS2552_SWS_MASK, cfg1_reg); | 129 | TAS2552_SWS_MASK, cfg1_reg); |
92 | } | 130 | } |
131 | #endif | ||
93 | 132 | ||
94 | static int tas2552_hw_params(struct snd_pcm_substream *substream, | 133 | static int tas2552_hw_params(struct snd_pcm_substream *substream, |
95 | struct snd_pcm_hw_params *params, | 134 | struct snd_pcm_hw_params *params, |
@@ -101,10 +140,6 @@ static int tas2552_hw_params(struct snd_pcm_substream *substream, | |||
101 | int d; | 140 | int d; |
102 | u8 p, j; | 141 | u8 p, j; |
103 | 142 | ||
104 | /* Turn on Class D amplifier */ | ||
105 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN_MASK, | ||
106 | TAS2552_CLASSD_EN); | ||
107 | |||
108 | if (!tas2552->mclk) | 143 | if (!tas2552->mclk) |
109 | return -EINVAL; | 144 | return -EINVAL; |
110 | 145 | ||
@@ -147,9 +182,6 @@ static int tas2552_hw_params(struct snd_pcm_substream *substream, | |||
147 | 182 | ||
148 | } | 183 | } |
149 | 184 | ||
150 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, | ||
151 | TAS2552_PLL_ENABLE); | ||
152 | |||
153 | return 0; | 185 | return 0; |
154 | } | 186 | } |
155 | 187 | ||
@@ -269,19 +301,10 @@ static const struct dev_pm_ops tas2552_pm = { | |||
269 | NULL) | 301 | NULL) |
270 | }; | 302 | }; |
271 | 303 | ||
272 | static void tas2552_shutdown(struct snd_pcm_substream *substream, | ||
273 | struct snd_soc_dai *dai) | ||
274 | { | ||
275 | struct snd_soc_codec *codec = dai->codec; | ||
276 | |||
277 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0); | ||
278 | } | ||
279 | |||
280 | static struct snd_soc_dai_ops tas2552_speaker_dai_ops = { | 304 | static struct snd_soc_dai_ops tas2552_speaker_dai_ops = { |
281 | .hw_params = tas2552_hw_params, | 305 | .hw_params = tas2552_hw_params, |
282 | .set_sysclk = tas2552_set_dai_sysclk, | 306 | .set_sysclk = tas2552_set_dai_sysclk, |
283 | .set_fmt = tas2552_set_dai_fmt, | 307 | .set_fmt = tas2552_set_dai_fmt, |
284 | .shutdown = tas2552_shutdown, | ||
285 | .digital_mute = tas2552_mute, | 308 | .digital_mute = tas2552_mute, |
286 | }; | 309 | }; |
287 | 310 | ||
@@ -294,7 +317,7 @@ static struct snd_soc_dai_driver tas2552_dai[] = { | |||
294 | { | 317 | { |
295 | .name = "tas2552-amplifier", | 318 | .name = "tas2552-amplifier", |
296 | .playback = { | 319 | .playback = { |
297 | .stream_name = "Speaker", | 320 | .stream_name = "Playback", |
298 | .channels_min = 2, | 321 | .channels_min = 2, |
299 | .channels_max = 2, | 322 | .channels_max = 2, |
300 | .rates = SNDRV_PCM_RATE_8000_192000, | 323 | .rates = SNDRV_PCM_RATE_8000_192000, |
@@ -312,6 +335,7 @@ static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24); | |||
312 | static const struct snd_kcontrol_new tas2552_snd_controls[] = { | 335 | static const struct snd_kcontrol_new tas2552_snd_controls[] = { |
313 | SOC_SINGLE_TLV("Speaker Driver Playback Volume", | 336 | SOC_SINGLE_TLV("Speaker Driver Playback Volume", |
314 | TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv), | 337 | TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv), |
338 | SOC_DAPM_SINGLE("Playback AMP", SND_SOC_NOPM, 0, 1, 0), | ||
315 | }; | 339 | }; |
316 | 340 | ||
317 | static const struct reg_default tas2552_init_regs[] = { | 341 | static const struct reg_default tas2552_init_regs[] = { |
@@ -321,6 +345,7 @@ static const struct reg_default tas2552_init_regs[] = { | |||
321 | static int tas2552_codec_probe(struct snd_soc_codec *codec) | 345 | static int tas2552_codec_probe(struct snd_soc_codec *codec) |
322 | { | 346 | { |
323 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); | 347 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); |
348 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
324 | int ret; | 349 | int ret; |
325 | 350 | ||
326 | tas2552->codec = codec; | 351 | tas2552->codec = codec; |
@@ -362,9 +387,14 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec) | |||
362 | goto patch_fail; | 387 | goto patch_fail; |
363 | } | 388 | } |
364 | 389 | ||
365 | snd_soc_write(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN | | 390 | snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN | |
366 | TAS2552_BOOST_EN | TAS2552_APT_EN | | 391 | TAS2552_APT_EN | TAS2552_LIM_EN); |
367 | TAS2552_LIM_EN); | 392 | |
393 | snd_soc_dapm_new_controls(dapm, tas2552_dapm_widgets, | ||
394 | ARRAY_SIZE(tas2552_dapm_widgets)); | ||
395 | snd_soc_dapm_add_routes(dapm, tas2552_audio_map, | ||
396 | ARRAY_SIZE(tas2552_audio_map)); | ||
397 | |||
368 | return 0; | 398 | return 0; |
369 | 399 | ||
370 | patch_fail: | 400 | patch_fail: |