blob: a061d78473ac4e812faab7759cb80d472e9131ff [file] [log] [blame]
Thomas Gleixnera636cd62019-05-19 15:51:34 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Rongjun Yingf516e362014-03-05 16:34:34 +08002/*
3 * SiRF audio codec driver
4 *
5 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
Rongjun Yingf516e362014-03-05 16:34:34 +08006 */
7
8#include <linux/module.h>
9#include <linux/platform_device.h>
10#include <linux/pm_runtime.h>
11#include <linux/of.h>
12#include <linux/of_device.h>
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/io.h>
16#include <linux/regmap.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/initval.h>
21#include <sound/tlv.h>
22#include <sound/soc.h>
23#include <sound/dmaengine_pcm.h>
24
25#include "sirf-audio-codec.h"
26
27struct sirf_audio_codec {
28 struct clk *clk;
29 struct regmap *regmap;
30 u32 reg_ctrl0, reg_ctrl1;
31};
32
33static const char * const input_mode_mux[] = {"Single-ended",
34 "Differential"};
35
36static const struct soc_enum input_mode_mux_enum =
37 SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux);
38
39static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control =
40 SOC_DAPM_ENUM("Route", input_mode_mux_enum);
41
42static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0);
43static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0);
44static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6,
45 0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0),
46 0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0),
47);
48
49static struct snd_kcontrol_new volume_controls_atlas6[] = {
50 SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
51 0x7F, 0, playback_vol_tlv),
52 SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10,
53 0x3F, 0, capture_vol_tlv_atlas6),
54};
55
56static struct snd_kcontrol_new volume_controls_prima2[] = {
57 SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
58 0x7F, 0, playback_vol_tlv),
59 SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10,
60 0x1F, 0, capture_vol_tlv_prima2),
61};
62
63static struct snd_kcontrol_new left_input_path_controls[] = {
64 SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0),
65 SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0),
66};
67
68static struct snd_kcontrol_new right_input_path_controls[] = {
69 SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0),
70 SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0),
71};
72
73static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control =
74 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0);
75
76static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control =
77 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0);
78
79static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control =
80 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0);
81
82static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control =
83 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0);
84
85static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control =
86 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0);
87
88static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control =
89 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0);
90
91/* After enable adc, Delay 200ms to avoid pop noise */
92static int adc_enable_delay_event(struct snd_soc_dapm_widget *w,
93 struct snd_kcontrol *kcontrol, int event)
94{
95 switch (event) {
96 case SND_SOC_DAPM_POST_PMU:
97 msleep(200);
98 break;
99 default:
100 break;
101 }
102
103 return 0;
104}
105
106static void enable_and_reset_codec(struct regmap *regmap,
107 u32 codec_enable_bits, u32 codec_reset_bits)
108{
109 regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
110 codec_enable_bits | codec_reset_bits,
Axel Lin772bc5942014-05-08 16:29:49 +0800111 codec_enable_bits);
Rongjun Yingf516e362014-03-05 16:34:34 +0800112 msleep(20);
113 regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
114 codec_reset_bits, codec_reset_bits);
115}
116
117static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
118 struct snd_kcontrol *kcontrol, int event)
119{
120#define ATLAS6_CODEC_ENABLE_BITS (1 << 29)
121#define ATLAS6_CODEC_RESET_BITS (1 << 28)
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000122 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
123 struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
Rongjun Yingf516e362014-03-05 16:34:34 +0800124 switch (event) {
125 case SND_SOC_DAPM_PRE_PMU:
126 enable_and_reset_codec(sirf_audio_codec->regmap,
127 ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS);
128 break;
129 case SND_SOC_DAPM_POST_PMD:
130 regmap_update_bits(sirf_audio_codec->regmap,
Axel Lin772bc5942014-05-08 16:29:49 +0800131 AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, 0);
Rongjun Yingf516e362014-03-05 16:34:34 +0800132 break;
133 default:
134 break;
135 }
136
137 return 0;
138}
139
140static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
141 struct snd_kcontrol *kcontrol, int event)
142{
143#define PRIMA2_CODEC_ENABLE_BITS (1 << 27)
144#define PRIMA2_CODEC_RESET_BITS (1 << 26)
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000145 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
146 struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
Rongjun Yingf516e362014-03-05 16:34:34 +0800147 switch (event) {
148 case SND_SOC_DAPM_POST_PMU:
149 enable_and_reset_codec(sirf_audio_codec->regmap,
150 PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS);
151 break;
152 case SND_SOC_DAPM_POST_PMD:
153 regmap_update_bits(sirf_audio_codec->regmap,
Axel Lin772bc5942014-05-08 16:29:49 +0800154 AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, 0);
Rongjun Yingf516e362014-03-05 16:34:34 +0800155 break;
156 default:
157 break;
158 }
159
160 return 0;
161}
162
163static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = {
164 SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
165 25, 0, NULL, 0),
166 SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
167 26, 0, NULL, 0),
168 SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
169 27, 0, NULL, 0),
170};
171
172static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = {
173 SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
174 23, 0, NULL, 0),
175 SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
176 24, 0, NULL, 0),
177 SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
178 25, 0, NULL, 0),
179};
180
181static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget =
182 SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
183 atlas6_codec_enable_and_reset_event,
184 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
185
186static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget =
187 SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
188 prima2_codec_enable_and_reset_event,
189 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
190
191static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = {
192 SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0),
193 SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0),
194 SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0,
195 &left_dac_to_hp_left_amp_switch_control),
196 SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0,
197 &left_dac_to_hp_right_amp_switch_control),
198 SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0,
199 &right_dac_to_hp_left_amp_switch_control),
200 SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0,
201 &right_dac_to_hp_right_amp_switch_control),
202 SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
203 NULL, 0),
204 SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
205 NULL, 0),
206
207 SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0,
208 &left_dac_to_speaker_lineout_switch_control),
209 SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0,
210 &right_dac_to_speaker_lineout_switch_control),
211 SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0,
212 NULL, 0),
213
214 SND_SOC_DAPM_OUTPUT("HPOUTL"),
215 SND_SOC_DAPM_OUTPUT("HPOUTR"),
216 SND_SOC_DAPM_OUTPUT("SPKOUT"),
217
218 SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0,
219 adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
220 SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0,
221 adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
222 SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0,
223 &left_input_path_controls[0],
224 ARRAY_SIZE(left_input_path_controls)),
225 SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0,
226 &right_input_path_controls[0],
227 ARRAY_SIZE(right_input_path_controls)),
228
229 SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0,
230 &sirf_audio_codec_input_mode_control),
231 SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0),
232 SND_SOC_DAPM_INPUT("MICIN1"),
233 SND_SOC_DAPM_INPUT("MICIN2"),
234 SND_SOC_DAPM_INPUT("LINEIN1"),
235 SND_SOC_DAPM_INPUT("LINEIN2"),
236
237 SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0,
238 30, 0, NULL, 0),
239};
240
241static const struct snd_soc_dapm_route sirf_audio_codec_map[] = {
242 {"SPKOUT", NULL, "Speaker Driver"},
243 {"Speaker Driver", NULL, "Speaker amp driver"},
244 {"Speaker amp driver", NULL, "Left dac to speaker lineout"},
245 {"Speaker amp driver", NULL, "Right dac to speaker lineout"},
246 {"Left dac to speaker lineout", "Switch", "DAC left"},
247 {"Right dac to speaker lineout", "Switch", "DAC right"},
248 {"HPOUTL", NULL, "HP Left Driver"},
249 {"HPOUTR", NULL, "HP Right Driver"},
250 {"HP Left Driver", NULL, "HP amp left driver"},
251 {"HP Right Driver", NULL, "HP amp right driver"},
252 {"HP amp left driver", NULL, "Right dac to hp left amp"},
253 {"HP amp right driver", NULL , "Right dac to hp right amp"},
254 {"HP amp left driver", NULL, "Left dac to hp left amp"},
255 {"HP amp right driver", NULL , "Right dac to hp right amp"},
256 {"Right dac to hp left amp", "Switch", "DAC left"},
257 {"Right dac to hp right amp", "Switch", "DAC right"},
258 {"Left dac to hp left amp", "Switch", "DAC left"},
259 {"Left dac to hp right amp", "Switch", "DAC right"},
260 {"DAC left", NULL, "codecclk"},
261 {"DAC right", NULL, "codecclk"},
262 {"DAC left", NULL, "Playback"},
263 {"DAC right", NULL, "Playback"},
264 {"DAC left", NULL, "HSL Phase Opposite"},
265 {"DAC right", NULL, "HSL Phase Opposite"},
266
267 {"Capture", NULL, "ADC left"},
268 {"Capture", NULL, "ADC right"},
269 {"ADC left", NULL, "codecclk"},
270 {"ADC right", NULL, "codecclk"},
271 {"ADC left", NULL, "Left PGA mixer"},
272 {"ADC right", NULL, "Right PGA mixer"},
273 {"Left PGA mixer", "Line Left Switch", "LINEIN2"},
274 {"Right PGA mixer", "Line Right Switch", "LINEIN1"},
275 {"Left PGA mixer", "Mic Left Switch", "MICIN2"},
276 {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"},
277 {"Mic input mode mux", "Single-ended", "MICIN1"},
278 {"Mic input mode mux", "Differential", "MICIN1"},
279};
280
Rongjun Yingb87704c2014-03-20 15:46:19 +0800281static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec)
282{
283 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
284 AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
285 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
286 AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
287 regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0);
288 regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
289 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
290 AUDIO_FIFO_START, AUDIO_FIFO_START);
291 regmap_update_bits(sirf_audio_codec->regmap,
292 AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE);
293}
294
295static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec)
296{
297 regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
298 regmap_update_bits(sirf_audio_codec->regmap,
299 AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE);
300}
301
302static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec,
303 int channels)
304{
305 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
306 AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
307 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
308 AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
309 regmap_write(sirf_audio_codec->regmap,
310 AUDIO_PORT_IC_RXFIFO_INT_MSK, 0);
311 regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0);
312 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
313 AUDIO_FIFO_START, AUDIO_FIFO_START);
314 if (channels == 1)
315 regmap_update_bits(sirf_audio_codec->regmap,
316 AUDIO_PORT_IC_CODEC_RX_CTRL,
317 IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO);
318 else
319 regmap_update_bits(sirf_audio_codec->regmap,
320 AUDIO_PORT_IC_CODEC_RX_CTRL,
321 IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO);
322}
323
324static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec)
325{
326 regmap_update_bits(sirf_audio_codec->regmap,
327 AUDIO_PORT_IC_CODEC_RX_CTRL,
328 IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO);
329}
330
Rongjun Yingf516e362014-03-05 16:34:34 +0800331static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
332 int cmd,
333 struct snd_soc_dai *dai)
334{
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000335 struct snd_soc_component *component = dai->component;
336 struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
Rongjun Yingb87704c2014-03-20 15:46:19 +0800337 int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
Rongjun Yingf516e362014-03-05 16:34:34 +0800338
339 /*
340 * This is a workaround, When stop playback,
341 * need disable HP amp, avoid the current noise.
342 */
343 switch (cmd) {
344 case SNDRV_PCM_TRIGGER_STOP:
345 case SNDRV_PCM_TRIGGER_SUSPEND:
346 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
Rongjun Yingb87704c2014-03-20 15:46:19 +0800347 if (playback) {
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000348 snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
Rongjun Yingb87704c2014-03-20 15:46:19 +0800349 IC_HSLEN | IC_HSREN, 0);
350 sirf_audio_codec_tx_disable(sirf_audio_codec);
351 } else
352 sirf_audio_codec_rx_disable(sirf_audio_codec);
Rongjun Yingf516e362014-03-05 16:34:34 +0800353 break;
354 case SNDRV_PCM_TRIGGER_START:
355 case SNDRV_PCM_TRIGGER_RESUME:
356 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
Rongjun Yingb87704c2014-03-20 15:46:19 +0800357 if (playback) {
358 sirf_audio_codec_tx_enable(sirf_audio_codec);
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000359 snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
Rongjun Yingb87704c2014-03-20 15:46:19 +0800360 IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN);
361 } else
362 sirf_audio_codec_rx_enable(sirf_audio_codec,
363 substream->runtime->channels);
Rongjun Yingf516e362014-03-05 16:34:34 +0800364 break;
365 default:
366 return -EINVAL;
367 }
368
Rongjun Yingf516e362014-03-05 16:34:34 +0800369 return 0;
370}
371
Axel Lin8e2175d2015-07-15 13:50:49 +0800372static const struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
Rongjun Yingf516e362014-03-05 16:34:34 +0800373 .trigger = sirf_audio_codec_trigger,
374};
375
Axel Lin8e2175d2015-07-15 13:50:49 +0800376static struct snd_soc_dai_driver sirf_audio_codec_dai = {
Rongjun Yingf516e362014-03-05 16:34:34 +0800377 .name = "sirf-audio-codec",
378 .playback = {
379 .stream_name = "Playback",
380 .channels_min = 2,
381 .channels_max = 2,
382 .rates = SNDRV_PCM_RATE_48000,
383 .formats = SNDRV_PCM_FMTBIT_S16_LE,
384 },
385 .capture = {
386 .stream_name = "Capture",
387 .channels_min = 1,
388 .channels_max = 2,
389 .rates = SNDRV_PCM_RATE_48000,
390 .formats = SNDRV_PCM_FMTBIT_S16_LE,
391 },
392 .ops = &sirf_audio_codec_dai_ops,
393};
394
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000395static int sirf_audio_codec_probe(struct snd_soc_component *component)
Rongjun Yingf516e362014-03-05 16:34:34 +0800396{
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000397 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
Rongjun Yingf516e362014-03-05 16:34:34 +0800398
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000399 pm_runtime_enable(component->dev);
Rongjun Yingf516e362014-03-05 16:34:34 +0800400
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000401 if (of_device_is_compatible(component->dev->of_node, "sirf,prima2-audio-codec")) {
Rongjun Yingf516e362014-03-05 16:34:34 +0800402 snd_soc_dapm_new_controls(dapm,
403 prima2_output_driver_dapm_widgets,
404 ARRAY_SIZE(prima2_output_driver_dapm_widgets));
405 snd_soc_dapm_new_controls(dapm,
406 &prima2_codec_clock_dapm_widget, 1);
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000407 return snd_soc_add_component_controls(component,
Rongjun Yingf516e362014-03-05 16:34:34 +0800408 volume_controls_prima2,
409 ARRAY_SIZE(volume_controls_prima2));
410 }
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000411 if (of_device_is_compatible(component->dev->of_node, "sirf,atlas6-audio-codec")) {
Rongjun Yingf516e362014-03-05 16:34:34 +0800412 snd_soc_dapm_new_controls(dapm,
413 atlas6_output_driver_dapm_widgets,
414 ARRAY_SIZE(atlas6_output_driver_dapm_widgets));
415 snd_soc_dapm_new_controls(dapm,
416 &atlas6_codec_clock_dapm_widget, 1);
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000417 return snd_soc_add_component_controls(component,
Rongjun Yingf516e362014-03-05 16:34:34 +0800418 volume_controls_atlas6,
419 ARRAY_SIZE(volume_controls_atlas6));
420 }
421
422 return -EINVAL;
423}
424
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000425static void sirf_audio_codec_remove(struct snd_soc_component *component)
Rongjun Yingf516e362014-03-05 16:34:34 +0800426{
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000427 pm_runtime_disable(component->dev);
Rongjun Yingf516e362014-03-05 16:34:34 +0800428}
429
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000430static const struct snd_soc_component_driver soc_codec_device_sirf_audio_codec = {
431 .probe = sirf_audio_codec_probe,
432 .remove = sirf_audio_codec_remove,
433 .dapm_widgets = sirf_audio_codec_dapm_widgets,
434 .num_dapm_widgets = ARRAY_SIZE(sirf_audio_codec_dapm_widgets),
435 .dapm_routes = sirf_audio_codec_map,
436 .num_dapm_routes = ARRAY_SIZE(sirf_audio_codec_map),
437 .use_pmdown_time = 1,
438 .endianness = 1,
439 .non_legacy_dai_naming = 1,
Rongjun Yingf516e362014-03-05 16:34:34 +0800440};
441
442static const struct of_device_id sirf_audio_codec_of_match[] = {
443 { .compatible = "sirf,prima2-audio-codec" },
444 { .compatible = "sirf,atlas6-audio-codec" },
445 {}
446};
447MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match);
448
449static const struct regmap_config sirf_audio_codec_regmap_config = {
450 .reg_bits = 32,
451 .reg_stride = 4,
452 .val_bits = 32,
Rongjun Yingb87704c2014-03-20 15:46:19 +0800453 .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
Rongjun Yingf516e362014-03-05 16:34:34 +0800454 .cache_type = REGCACHE_NONE,
455};
456
457static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
458{
459 int ret;
460 struct sirf_audio_codec *sirf_audio_codec;
461 void __iomem *base;
Rongjun Yingf516e362014-03-05 16:34:34 +0800462
463 sirf_audio_codec = devm_kzalloc(&pdev->dev,
464 sizeof(struct sirf_audio_codec), GFP_KERNEL);
465 if (!sirf_audio_codec)
466 return -ENOMEM;
467
468 platform_set_drvdata(pdev, sirf_audio_codec);
469
YueHaibing2f302d42019-09-04 16:34:12 +0800470 base = devm_platform_ioremap_resource(pdev, 0);
Wei Yongjunc8448052014-07-30 08:04:12 +0800471 if (IS_ERR(base))
472 return PTR_ERR(base);
Rongjun Yingf516e362014-03-05 16:34:34 +0800473
474 sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
475 &sirf_audio_codec_regmap_config);
476 if (IS_ERR(sirf_audio_codec->regmap))
477 return PTR_ERR(sirf_audio_codec->regmap);
478
479 sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL);
480 if (IS_ERR(sirf_audio_codec->clk)) {
481 dev_err(&pdev->dev, "Get clock failed.\n");
482 return PTR_ERR(sirf_audio_codec->clk);
483 }
484
485 ret = clk_prepare_enable(sirf_audio_codec->clk);
486 if (ret) {
487 dev_err(&pdev->dev, "Enable clock failed.\n");
488 return ret;
489 }
490
Kuninori Morimoto4218bcf2018-01-29 04:38:39 +0000491 ret = devm_snd_soc_register_component(&(pdev->dev),
Rongjun Yingf516e362014-03-05 16:34:34 +0800492 &soc_codec_device_sirf_audio_codec,
493 &sirf_audio_codec_dai, 1);
494 if (ret) {
495 dev_err(&pdev->dev, "Register Audio Codec dai failed.\n");
496 goto err_clk_put;
497 }
498
499 /*
500 * Always open charge pump, if not, when the charge pump closed the
501 * adc will not stable
502 */
503 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
504 IC_CPFREQ, IC_CPFREQ);
505
506 if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec"))
507 regmap_update_bits(sirf_audio_codec->regmap,
508 AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN);
509 return 0;
510
511err_clk_put:
512 clk_disable_unprepare(sirf_audio_codec->clk);
513 return ret;
514}
515
516static int sirf_audio_codec_driver_remove(struct platform_device *pdev)
517{
518 struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev);
519
520 clk_disable_unprepare(sirf_audio_codec->clk);
Rongjun Yingf516e362014-03-05 16:34:34 +0800521
522 return 0;
523}
524
525#ifdef CONFIG_PM_SLEEP
526static int sirf_audio_codec_suspend(struct device *dev)
527{
528 struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
529
530 regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
531 &sirf_audio_codec->reg_ctrl0);
532 regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
533 &sirf_audio_codec->reg_ctrl1);
534 clk_disable_unprepare(sirf_audio_codec->clk);
535
536 return 0;
537}
538
539static int sirf_audio_codec_resume(struct device *dev)
540{
541 struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
542 int ret;
543
544 ret = clk_prepare_enable(sirf_audio_codec->clk);
545 if (ret)
546 return ret;
547
548 regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
549 sirf_audio_codec->reg_ctrl0);
550 regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
551 sirf_audio_codec->reg_ctrl1);
552
553 return 0;
554}
555#endif
556
557static const struct dev_pm_ops sirf_audio_codec_pm_ops = {
558 SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume)
559};
560
561static struct platform_driver sirf_audio_codec_driver = {
562 .driver = {
563 .name = "sirf-audio-codec",
Rongjun Yingf516e362014-03-05 16:34:34 +0800564 .of_match_table = sirf_audio_codec_of_match,
565 .pm = &sirf_audio_codec_pm_ops,
566 },
567 .probe = sirf_audio_codec_driver_probe,
568 .remove = sirf_audio_codec_driver_remove,
569};
570
571module_platform_driver(sirf_audio_codec_driver);
572
573MODULE_DESCRIPTION("SiRF audio codec driver");
574MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
575MODULE_LICENSE("GPL v2");