]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blob - sound/soc/codecs/sirf-audio-codec.c
d90cb0fafcb27d54142f8a2e81df5fd607c4d89e
[mirror_ubuntu-eoan-kernel.git] / sound / soc / codecs / sirf-audio-codec.c
1 /*
2 * SiRF audio codec driver
3 *
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/of.h>
13 #include <linux/of_device.h>
14 #include <linux/clk.h>
15 #include <linux/delay.h>
16 #include <linux/io.h>
17 #include <linux/regmap.h>
18 #include <sound/core.h>
19 #include <sound/pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/initval.h>
22 #include <sound/tlv.h>
23 #include <sound/soc.h>
24 #include <sound/dmaengine_pcm.h>
25
26 #include "sirf-audio-codec.h"
27
28 struct sirf_audio_codec {
29 struct clk *clk;
30 struct regmap *regmap;
31 u32 reg_ctrl0, reg_ctrl1;
32 };
33
34 static const char * const input_mode_mux[] = {"Single-ended",
35 "Differential"};
36
37 static const struct soc_enum input_mode_mux_enum =
38 SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux);
39
40 static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control =
41 SOC_DAPM_ENUM("Route", input_mode_mux_enum);
42
43 static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0);
44 static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0);
45 static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6,
46 0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0),
47 0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0),
48 );
49
50 static struct snd_kcontrol_new volume_controls_atlas6[] = {
51 SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
52 0x7F, 0, playback_vol_tlv),
53 SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10,
54 0x3F, 0, capture_vol_tlv_atlas6),
55 };
56
57 static struct snd_kcontrol_new volume_controls_prima2[] = {
58 SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
59 0x7F, 0, playback_vol_tlv),
60 SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10,
61 0x1F, 0, capture_vol_tlv_prima2),
62 };
63
64 static struct snd_kcontrol_new left_input_path_controls[] = {
65 SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0),
66 SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0),
67 };
68
69 static struct snd_kcontrol_new right_input_path_controls[] = {
70 SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0),
71 SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0),
72 };
73
74 static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control =
75 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0);
76
77 static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control =
78 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0);
79
80 static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control =
81 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0);
82
83 static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control =
84 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0);
85
86 static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control =
87 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0);
88
89 static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control =
90 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0);
91
92 /* After enable adc, Delay 200ms to avoid pop noise */
93 static int adc_enable_delay_event(struct snd_soc_dapm_widget *w,
94 struct snd_kcontrol *kcontrol, int event)
95 {
96 switch (event) {
97 case SND_SOC_DAPM_POST_PMU:
98 msleep(200);
99 break;
100 default:
101 break;
102 }
103
104 return 0;
105 }
106
107 static void enable_and_reset_codec(struct regmap *regmap,
108 u32 codec_enable_bits, u32 codec_reset_bits)
109 {
110 regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
111 codec_enable_bits | codec_reset_bits,
112 codec_enable_bits);
113 msleep(20);
114 regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
115 codec_reset_bits, codec_reset_bits);
116 }
117
118 static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
119 struct snd_kcontrol *kcontrol, int event)
120 {
121 #define ATLAS6_CODEC_ENABLE_BITS (1 << 29)
122 #define ATLAS6_CODEC_RESET_BITS (1 << 28)
123 struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev);
124 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,
131 AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, 0);
132 break;
133 default:
134 break;
135 }
136
137 return 0;
138 }
139
140 static 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)
145 struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev);
146 switch (event) {
147 case SND_SOC_DAPM_POST_PMU:
148 enable_and_reset_codec(sirf_audio_codec->regmap,
149 PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS);
150 break;
151 case SND_SOC_DAPM_POST_PMD:
152 regmap_update_bits(sirf_audio_codec->regmap,
153 AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, 0);
154 break;
155 default:
156 break;
157 }
158
159 return 0;
160 }
161
162 static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = {
163 SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
164 25, 0, NULL, 0),
165 SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
166 26, 0, NULL, 0),
167 SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
168 27, 0, NULL, 0),
169 };
170
171 static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = {
172 SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
173 23, 0, NULL, 0),
174 SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
175 24, 0, NULL, 0),
176 SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
177 25, 0, NULL, 0),
178 };
179
180 static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget =
181 SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
182 atlas6_codec_enable_and_reset_event,
183 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
184
185 static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget =
186 SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
187 prima2_codec_enable_and_reset_event,
188 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
189
190 static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = {
191 SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0),
192 SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0),
193 SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0,
194 &left_dac_to_hp_left_amp_switch_control),
195 SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0,
196 &left_dac_to_hp_right_amp_switch_control),
197 SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0,
198 &right_dac_to_hp_left_amp_switch_control),
199 SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0,
200 &right_dac_to_hp_right_amp_switch_control),
201 SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
202 NULL, 0),
203 SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
204 NULL, 0),
205
206 SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0,
207 &left_dac_to_speaker_lineout_switch_control),
208 SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0,
209 &right_dac_to_speaker_lineout_switch_control),
210 SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0,
211 NULL, 0),
212
213 SND_SOC_DAPM_OUTPUT("HPOUTL"),
214 SND_SOC_DAPM_OUTPUT("HPOUTR"),
215 SND_SOC_DAPM_OUTPUT("SPKOUT"),
216
217 SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0,
218 adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
219 SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0,
220 adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
221 SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0,
222 &left_input_path_controls[0],
223 ARRAY_SIZE(left_input_path_controls)),
224 SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0,
225 &right_input_path_controls[0],
226 ARRAY_SIZE(right_input_path_controls)),
227
228 SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0,
229 &sirf_audio_codec_input_mode_control),
230 SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0),
231 SND_SOC_DAPM_INPUT("MICIN1"),
232 SND_SOC_DAPM_INPUT("MICIN2"),
233 SND_SOC_DAPM_INPUT("LINEIN1"),
234 SND_SOC_DAPM_INPUT("LINEIN2"),
235
236 SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0,
237 30, 0, NULL, 0),
238 };
239
240 static const struct snd_soc_dapm_route sirf_audio_codec_map[] = {
241 {"SPKOUT", NULL, "Speaker Driver"},
242 {"Speaker Driver", NULL, "Speaker amp driver"},
243 {"Speaker amp driver", NULL, "Left dac to speaker lineout"},
244 {"Speaker amp driver", NULL, "Right dac to speaker lineout"},
245 {"Left dac to speaker lineout", "Switch", "DAC left"},
246 {"Right dac to speaker lineout", "Switch", "DAC right"},
247 {"HPOUTL", NULL, "HP Left Driver"},
248 {"HPOUTR", NULL, "HP Right Driver"},
249 {"HP Left Driver", NULL, "HP amp left driver"},
250 {"HP Right Driver", NULL, "HP amp right driver"},
251 {"HP amp left driver", NULL, "Right dac to hp left amp"},
252 {"HP amp right driver", NULL , "Right dac to hp right amp"},
253 {"HP amp left driver", NULL, "Left dac to hp left amp"},
254 {"HP amp right driver", NULL , "Right dac to hp right amp"},
255 {"Right dac to hp left amp", "Switch", "DAC left"},
256 {"Right dac to hp right amp", "Switch", "DAC right"},
257 {"Left dac to hp left amp", "Switch", "DAC left"},
258 {"Left dac to hp right amp", "Switch", "DAC right"},
259 {"DAC left", NULL, "codecclk"},
260 {"DAC right", NULL, "codecclk"},
261 {"DAC left", NULL, "Playback"},
262 {"DAC right", NULL, "Playback"},
263 {"DAC left", NULL, "HSL Phase Opposite"},
264 {"DAC right", NULL, "HSL Phase Opposite"},
265
266 {"Capture", NULL, "ADC left"},
267 {"Capture", NULL, "ADC right"},
268 {"ADC left", NULL, "codecclk"},
269 {"ADC right", NULL, "codecclk"},
270 {"ADC left", NULL, "Left PGA mixer"},
271 {"ADC right", NULL, "Right PGA mixer"},
272 {"Left PGA mixer", "Line Left Switch", "LINEIN2"},
273 {"Right PGA mixer", "Line Right Switch", "LINEIN1"},
274 {"Left PGA mixer", "Mic Left Switch", "MICIN2"},
275 {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"},
276 {"Mic input mode mux", "Single-ended", "MICIN1"},
277 {"Mic input mode mux", "Differential", "MICIN1"},
278 };
279
280 static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec)
281 {
282 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
283 AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
284 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
285 AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
286 regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0);
287 regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
288 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
289 AUDIO_FIFO_START, AUDIO_FIFO_START);
290 regmap_update_bits(sirf_audio_codec->regmap,
291 AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE);
292 }
293
294 static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec)
295 {
296 regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
297 regmap_update_bits(sirf_audio_codec->regmap,
298 AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE);
299 }
300
301 static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec,
302 int channels)
303 {
304 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
305 AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
306 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
307 AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
308 regmap_write(sirf_audio_codec->regmap,
309 AUDIO_PORT_IC_RXFIFO_INT_MSK, 0);
310 regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0);
311 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
312 AUDIO_FIFO_START, AUDIO_FIFO_START);
313 if (channels == 1)
314 regmap_update_bits(sirf_audio_codec->regmap,
315 AUDIO_PORT_IC_CODEC_RX_CTRL,
316 IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO);
317 else
318 regmap_update_bits(sirf_audio_codec->regmap,
319 AUDIO_PORT_IC_CODEC_RX_CTRL,
320 IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO);
321 }
322
323 static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec)
324 {
325 regmap_update_bits(sirf_audio_codec->regmap,
326 AUDIO_PORT_IC_CODEC_RX_CTRL,
327 IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO);
328 }
329
330 static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
331 int cmd,
332 struct snd_soc_dai *dai)
333 {
334 struct snd_soc_codec *codec = dai->codec;
335 struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec);
336 int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
337
338 /*
339 * This is a workaround, When stop playback,
340 * need disable HP amp, avoid the current noise.
341 */
342 switch (cmd) {
343 case SNDRV_PCM_TRIGGER_STOP:
344 case SNDRV_PCM_TRIGGER_SUSPEND:
345 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
346 if (playback) {
347 snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0,
348 IC_HSLEN | IC_HSREN, 0);
349 sirf_audio_codec_tx_disable(sirf_audio_codec);
350 } else
351 sirf_audio_codec_rx_disable(sirf_audio_codec);
352 break;
353 case SNDRV_PCM_TRIGGER_START:
354 case SNDRV_PCM_TRIGGER_RESUME:
355 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
356 if (playback) {
357 sirf_audio_codec_tx_enable(sirf_audio_codec);
358 snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0,
359 IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN);
360 } else
361 sirf_audio_codec_rx_enable(sirf_audio_codec,
362 substream->runtime->channels);
363 break;
364 default:
365 return -EINVAL;
366 }
367
368 return 0;
369 }
370
371 struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
372 .trigger = sirf_audio_codec_trigger,
373 };
374
375 struct snd_soc_dai_driver sirf_audio_codec_dai = {
376 .name = "sirf-audio-codec",
377 .playback = {
378 .stream_name = "Playback",
379 .channels_min = 2,
380 .channels_max = 2,
381 .rates = SNDRV_PCM_RATE_48000,
382 .formats = SNDRV_PCM_FMTBIT_S16_LE,
383 },
384 .capture = {
385 .stream_name = "Capture",
386 .channels_min = 1,
387 .channels_max = 2,
388 .rates = SNDRV_PCM_RATE_48000,
389 .formats = SNDRV_PCM_FMTBIT_S16_LE,
390 },
391 .ops = &sirf_audio_codec_dai_ops,
392 };
393
394 static int sirf_audio_codec_probe(struct snd_soc_codec *codec)
395 {
396 struct snd_soc_dapm_context *dapm = &codec->dapm;
397
398 pm_runtime_enable(codec->dev);
399
400 if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) {
401 snd_soc_dapm_new_controls(dapm,
402 prima2_output_driver_dapm_widgets,
403 ARRAY_SIZE(prima2_output_driver_dapm_widgets));
404 snd_soc_dapm_new_controls(dapm,
405 &prima2_codec_clock_dapm_widget, 1);
406 return snd_soc_add_codec_controls(codec,
407 volume_controls_prima2,
408 ARRAY_SIZE(volume_controls_prima2));
409 }
410 if (of_device_is_compatible(codec->dev->of_node, "sirf,atlas6-audio-codec")) {
411 snd_soc_dapm_new_controls(dapm,
412 atlas6_output_driver_dapm_widgets,
413 ARRAY_SIZE(atlas6_output_driver_dapm_widgets));
414 snd_soc_dapm_new_controls(dapm,
415 &atlas6_codec_clock_dapm_widget, 1);
416 return snd_soc_add_codec_controls(codec,
417 volume_controls_atlas6,
418 ARRAY_SIZE(volume_controls_atlas6));
419 }
420
421 return -EINVAL;
422 }
423
424 static int sirf_audio_codec_remove(struct snd_soc_codec *codec)
425 {
426 pm_runtime_disable(codec->dev);
427 return 0;
428 }
429
430 static struct snd_soc_codec_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 .idle_bias_off = true,
438 };
439
440 static const struct of_device_id sirf_audio_codec_of_match[] = {
441 { .compatible = "sirf,prima2-audio-codec" },
442 { .compatible = "sirf,atlas6-audio-codec" },
443 {}
444 };
445 MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match);
446
447 static const struct regmap_config sirf_audio_codec_regmap_config = {
448 .reg_bits = 32,
449 .reg_stride = 4,
450 .val_bits = 32,
451 .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
452 .cache_type = REGCACHE_NONE,
453 };
454
455 static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
456 {
457 int ret;
458 struct sirf_audio_codec *sirf_audio_codec;
459 void __iomem *base;
460 struct resource *mem_res;
461 const struct of_device_id *match;
462
463 match = of_match_node(sirf_audio_codec_of_match, pdev->dev.of_node);
464
465 sirf_audio_codec = devm_kzalloc(&pdev->dev,
466 sizeof(struct sirf_audio_codec), GFP_KERNEL);
467 if (!sirf_audio_codec)
468 return -ENOMEM;
469
470 platform_set_drvdata(pdev, sirf_audio_codec);
471
472 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
473 base = devm_ioremap_resource(&pdev->dev, mem_res);
474 if (base == NULL)
475 return -ENOMEM;
476
477 sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
478 &sirf_audio_codec_regmap_config);
479 if (IS_ERR(sirf_audio_codec->regmap))
480 return PTR_ERR(sirf_audio_codec->regmap);
481
482 sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL);
483 if (IS_ERR(sirf_audio_codec->clk)) {
484 dev_err(&pdev->dev, "Get clock failed.\n");
485 return PTR_ERR(sirf_audio_codec->clk);
486 }
487
488 ret = clk_prepare_enable(sirf_audio_codec->clk);
489 if (ret) {
490 dev_err(&pdev->dev, "Enable clock failed.\n");
491 return ret;
492 }
493
494 ret = snd_soc_register_codec(&(pdev->dev),
495 &soc_codec_device_sirf_audio_codec,
496 &sirf_audio_codec_dai, 1);
497 if (ret) {
498 dev_err(&pdev->dev, "Register Audio Codec dai failed.\n");
499 goto err_clk_put;
500 }
501
502 /*
503 * Always open charge pump, if not, when the charge pump closed the
504 * adc will not stable
505 */
506 regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
507 IC_CPFREQ, IC_CPFREQ);
508
509 if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec"))
510 regmap_update_bits(sirf_audio_codec->regmap,
511 AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN);
512 return 0;
513
514 err_clk_put:
515 clk_disable_unprepare(sirf_audio_codec->clk);
516 return ret;
517 }
518
519 static int sirf_audio_codec_driver_remove(struct platform_device *pdev)
520 {
521 struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev);
522
523 clk_disable_unprepare(sirf_audio_codec->clk);
524 snd_soc_unregister_codec(&(pdev->dev));
525
526 return 0;
527 }
528
529 #ifdef CONFIG_PM_SLEEP
530 static int sirf_audio_codec_suspend(struct device *dev)
531 {
532 struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
533
534 regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
535 &sirf_audio_codec->reg_ctrl0);
536 regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
537 &sirf_audio_codec->reg_ctrl1);
538 clk_disable_unprepare(sirf_audio_codec->clk);
539
540 return 0;
541 }
542
543 static int sirf_audio_codec_resume(struct device *dev)
544 {
545 struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
546 int ret;
547
548 ret = clk_prepare_enable(sirf_audio_codec->clk);
549 if (ret)
550 return ret;
551
552 regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
553 sirf_audio_codec->reg_ctrl0);
554 regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
555 sirf_audio_codec->reg_ctrl1);
556
557 return 0;
558 }
559 #endif
560
561 static const struct dev_pm_ops sirf_audio_codec_pm_ops = {
562 SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume)
563 };
564
565 static struct platform_driver sirf_audio_codec_driver = {
566 .driver = {
567 .name = "sirf-audio-codec",
568 .owner = THIS_MODULE,
569 .of_match_table = sirf_audio_codec_of_match,
570 .pm = &sirf_audio_codec_pm_ops,
571 },
572 .probe = sirf_audio_codec_driver_probe,
573 .remove = sirf_audio_codec_driver_remove,
574 };
575
576 module_platform_driver(sirf_audio_codec_driver);
577
578 MODULE_DESCRIPTION("SiRF audio codec driver");
579 MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
580 MODULE_LICENSE("GPL v2");