]> git.karo-electronics.de Git - karo-tx-linux.git/blob - sound/soc/codecs/sirf-audio-codec.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[karo-tx-linux.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 | ~codec_reset_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,
132                         ~ATLAS6_CODEC_ENABLE_BITS);
133                 break;
134         default:
135                 break;
136         }
137
138         return 0;
139 }
140
141 static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
142                 struct snd_kcontrol *kcontrol, int event)
143 {
144 #define PRIMA2_CODEC_ENABLE_BITS (1 << 27)
145 #define PRIMA2_CODEC_RESET_BITS (1 << 26)
146         struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev);
147         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,
154                         AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS,
155                         ~PRIMA2_CODEC_ENABLE_BITS);
156                 break;
157         default:
158                 break;
159         }
160
161         return 0;
162 }
163
164 static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = {
165         SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
166                         25, 0, NULL, 0),
167         SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
168                         26, 0, NULL, 0),
169         SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
170                         27, 0, NULL, 0),
171 };
172
173 static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = {
174         SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
175                         23, 0, NULL, 0),
176         SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
177                         24, 0, NULL, 0),
178         SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
179                         25, 0, NULL, 0),
180 };
181
182 static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget =
183         SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
184                         atlas6_codec_enable_and_reset_event,
185                         SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
186
187 static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget =
188         SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
189                         prima2_codec_enable_and_reset_event,
190                         SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
191
192 static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = {
193         SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0),
194         SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0),
195         SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0,
196                         &left_dac_to_hp_left_amp_switch_control),
197         SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0,
198                         &left_dac_to_hp_right_amp_switch_control),
199         SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0,
200                         &right_dac_to_hp_left_amp_switch_control),
201         SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0,
202                         &right_dac_to_hp_right_amp_switch_control),
203         SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
204                         NULL, 0),
205         SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
206                         NULL, 0),
207
208         SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0,
209                         &left_dac_to_speaker_lineout_switch_control),
210         SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0,
211                         &right_dac_to_speaker_lineout_switch_control),
212         SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0,
213                         NULL, 0),
214
215         SND_SOC_DAPM_OUTPUT("HPOUTL"),
216         SND_SOC_DAPM_OUTPUT("HPOUTR"),
217         SND_SOC_DAPM_OUTPUT("SPKOUT"),
218
219         SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0,
220                         adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
221         SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0,
222                         adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
223         SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0,
224                 &left_input_path_controls[0],
225                 ARRAY_SIZE(left_input_path_controls)),
226         SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0,
227                 &right_input_path_controls[0],
228                 ARRAY_SIZE(right_input_path_controls)),
229
230         SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0,
231                         &sirf_audio_codec_input_mode_control),
232         SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0),
233         SND_SOC_DAPM_INPUT("MICIN1"),
234         SND_SOC_DAPM_INPUT("MICIN2"),
235         SND_SOC_DAPM_INPUT("LINEIN1"),
236         SND_SOC_DAPM_INPUT("LINEIN2"),
237
238         SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0,
239                         30, 0, NULL, 0),
240 };
241
242 static const struct snd_soc_dapm_route sirf_audio_codec_map[] = {
243         {"SPKOUT", NULL, "Speaker Driver"},
244         {"Speaker Driver", NULL, "Speaker amp driver"},
245         {"Speaker amp driver", NULL, "Left dac to speaker lineout"},
246         {"Speaker amp driver", NULL, "Right dac to speaker lineout"},
247         {"Left dac to speaker lineout", "Switch", "DAC left"},
248         {"Right dac to speaker lineout", "Switch", "DAC right"},
249         {"HPOUTL", NULL, "HP Left Driver"},
250         {"HPOUTR", NULL, "HP Right Driver"},
251         {"HP Left Driver", NULL, "HP amp left driver"},
252         {"HP Right Driver", NULL, "HP amp right driver"},
253         {"HP amp left driver", NULL, "Right dac to hp left amp"},
254         {"HP amp right driver", NULL , "Right dac to hp right amp"},
255         {"HP amp left driver", NULL, "Left dac to hp left amp"},
256         {"HP amp right driver", NULL , "Right dac to hp right amp"},
257         {"Right dac to hp left amp", "Switch", "DAC left"},
258         {"Right dac to hp right amp", "Switch", "DAC right"},
259         {"Left dac to hp left amp", "Switch", "DAC left"},
260         {"Left dac to hp right amp", "Switch", "DAC right"},
261         {"DAC left", NULL, "codecclk"},
262         {"DAC right", NULL, "codecclk"},
263         {"DAC left", NULL, "Playback"},
264         {"DAC right", NULL, "Playback"},
265         {"DAC left", NULL, "HSL Phase Opposite"},
266         {"DAC right", NULL, "HSL Phase Opposite"},
267
268         {"Capture", NULL, "ADC left"},
269         {"Capture", NULL, "ADC right"},
270         {"ADC left", NULL, "codecclk"},
271         {"ADC right", NULL, "codecclk"},
272         {"ADC left", NULL, "Left PGA mixer"},
273         {"ADC right", NULL, "Right PGA mixer"},
274         {"Left PGA mixer", "Line Left Switch", "LINEIN2"},
275         {"Right PGA mixer", "Line Right Switch", "LINEIN1"},
276         {"Left PGA mixer", "Mic Left Switch", "MICIN2"},
277         {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"},
278         {"Mic input mode mux", "Single-ended", "MICIN1"},
279         {"Mic input mode mux", "Differential", "MICIN1"},
280 };
281
282 static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
283                 int cmd,
284                 struct snd_soc_dai *dai)
285 {
286         int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
287         struct snd_soc_codec *codec = dai->codec;
288         u32 val = 0;
289
290         /*
291          * This is a workaround, When stop playback,
292          * need disable HP amp, avoid the current noise.
293          */
294         switch (cmd) {
295         case SNDRV_PCM_TRIGGER_STOP:
296         case SNDRV_PCM_TRIGGER_SUSPEND:
297         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
298                 break;
299         case SNDRV_PCM_TRIGGER_START:
300         case SNDRV_PCM_TRIGGER_RESUME:
301         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
302                 if (playback)
303                         val = IC_HSLEN | IC_HSREN;
304                 break;
305         default:
306                 return -EINVAL;
307         }
308
309         if (playback)
310                 snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0,
311                         IC_HSLEN | IC_HSREN, val);
312         return 0;
313 }
314
315 struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
316         .trigger = sirf_audio_codec_trigger,
317 };
318
319 struct snd_soc_dai_driver sirf_audio_codec_dai = {
320         .name = "sirf-audio-codec",
321         .playback = {
322                 .stream_name = "Playback",
323                 .channels_min = 2,
324                 .channels_max = 2,
325                 .rates = SNDRV_PCM_RATE_48000,
326                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
327         },
328         .capture = {
329                 .stream_name = "Capture",
330                 .channels_min = 1,
331                 .channels_max = 2,
332                 .rates = SNDRV_PCM_RATE_48000,
333                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
334         },
335         .ops = &sirf_audio_codec_dai_ops,
336 };
337
338 static int sirf_audio_codec_probe(struct snd_soc_codec *codec)
339 {
340         struct snd_soc_dapm_context *dapm = &codec->dapm;
341
342         pm_runtime_enable(codec->dev);
343
344         if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) {
345                 snd_soc_dapm_new_controls(dapm,
346                         prima2_output_driver_dapm_widgets,
347                         ARRAY_SIZE(prima2_output_driver_dapm_widgets));
348                 snd_soc_dapm_new_controls(dapm,
349                         &prima2_codec_clock_dapm_widget, 1);
350                 return snd_soc_add_codec_controls(codec,
351                         volume_controls_prima2,
352                         ARRAY_SIZE(volume_controls_prima2));
353         }
354         if (of_device_is_compatible(codec->dev->of_node, "sirf,atlas6-audio-codec")) {
355                 snd_soc_dapm_new_controls(dapm,
356                         atlas6_output_driver_dapm_widgets,
357                         ARRAY_SIZE(atlas6_output_driver_dapm_widgets));
358                 snd_soc_dapm_new_controls(dapm,
359                         &atlas6_codec_clock_dapm_widget, 1);
360                 return snd_soc_add_codec_controls(codec,
361                         volume_controls_atlas6,
362                         ARRAY_SIZE(volume_controls_atlas6));
363         }
364
365         return -EINVAL;
366 }
367
368 static int sirf_audio_codec_remove(struct snd_soc_codec *codec)
369 {
370         pm_runtime_disable(codec->dev);
371         return 0;
372 }
373
374 static struct snd_soc_codec_driver soc_codec_device_sirf_audio_codec = {
375         .probe = sirf_audio_codec_probe,
376         .remove = sirf_audio_codec_remove,
377         .dapm_widgets = sirf_audio_codec_dapm_widgets,
378         .num_dapm_widgets = ARRAY_SIZE(sirf_audio_codec_dapm_widgets),
379         .dapm_routes = sirf_audio_codec_map,
380         .num_dapm_routes = ARRAY_SIZE(sirf_audio_codec_map),
381         .idle_bias_off = true,
382 };
383
384 static const struct of_device_id sirf_audio_codec_of_match[] = {
385         { .compatible = "sirf,prima2-audio-codec" },
386         { .compatible = "sirf,atlas6-audio-codec" },
387         {}
388 };
389 MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match);
390
391 static const struct regmap_config sirf_audio_codec_regmap_config = {
392         .reg_bits = 32,
393         .reg_stride = 4,
394         .val_bits = 32,
395         .max_register = AUDIO_IC_CODEC_CTRL3,
396         .cache_type = REGCACHE_NONE,
397 };
398
399 static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
400 {
401         int ret;
402         struct sirf_audio_codec *sirf_audio_codec;
403         void __iomem *base;
404         struct resource *mem_res;
405         const struct of_device_id *match;
406
407         match = of_match_node(sirf_audio_codec_of_match, pdev->dev.of_node);
408
409         sirf_audio_codec = devm_kzalloc(&pdev->dev,
410                 sizeof(struct sirf_audio_codec), GFP_KERNEL);
411         if (!sirf_audio_codec)
412                 return -ENOMEM;
413
414         platform_set_drvdata(pdev, sirf_audio_codec);
415
416         mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
417         base = devm_ioremap_resource(&pdev->dev, mem_res);
418         if (base == NULL)
419                 return -ENOMEM;
420
421         sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
422                                             &sirf_audio_codec_regmap_config);
423         if (IS_ERR(sirf_audio_codec->regmap))
424                 return PTR_ERR(sirf_audio_codec->regmap);
425
426         sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL);
427         if (IS_ERR(sirf_audio_codec->clk)) {
428                 dev_err(&pdev->dev, "Get clock failed.\n");
429                 return PTR_ERR(sirf_audio_codec->clk);
430         }
431
432         ret = clk_prepare_enable(sirf_audio_codec->clk);
433         if (ret) {
434                 dev_err(&pdev->dev, "Enable clock failed.\n");
435                 return ret;
436         }
437
438         ret = snd_soc_register_codec(&(pdev->dev),
439                         &soc_codec_device_sirf_audio_codec,
440                         &sirf_audio_codec_dai, 1);
441         if (ret) {
442                 dev_err(&pdev->dev, "Register Audio Codec dai failed.\n");
443                 goto err_clk_put;
444         }
445
446         /*
447          * Always open charge pump, if not, when the charge pump closed the
448          * adc will not stable
449          */
450         regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
451                 IC_CPFREQ, IC_CPFREQ);
452
453         if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec"))
454                 regmap_update_bits(sirf_audio_codec->regmap,
455                                 AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN);
456         return 0;
457
458 err_clk_put:
459         clk_disable_unprepare(sirf_audio_codec->clk);
460         return ret;
461 }
462
463 static int sirf_audio_codec_driver_remove(struct platform_device *pdev)
464 {
465         struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev);
466
467         clk_disable_unprepare(sirf_audio_codec->clk);
468         snd_soc_unregister_codec(&(pdev->dev));
469
470         return 0;
471 }
472
473 #ifdef CONFIG_PM_SLEEP
474 static int sirf_audio_codec_suspend(struct device *dev)
475 {
476         struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
477
478         regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
479                 &sirf_audio_codec->reg_ctrl0);
480         regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
481                 &sirf_audio_codec->reg_ctrl1);
482         clk_disable_unprepare(sirf_audio_codec->clk);
483
484         return 0;
485 }
486
487 static int sirf_audio_codec_resume(struct device *dev)
488 {
489         struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
490         int ret;
491
492         ret = clk_prepare_enable(sirf_audio_codec->clk);
493         if (ret)
494                 return ret;
495
496         regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
497                 sirf_audio_codec->reg_ctrl0);
498         regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
499                 sirf_audio_codec->reg_ctrl1);
500
501         return 0;
502 }
503 #endif
504
505 static const struct dev_pm_ops sirf_audio_codec_pm_ops = {
506         SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume)
507 };
508
509 static struct platform_driver sirf_audio_codec_driver = {
510         .driver = {
511                 .name = "sirf-audio-codec",
512                 .owner = THIS_MODULE,
513                 .of_match_table = sirf_audio_codec_of_match,
514                 .pm = &sirf_audio_codec_pm_ops,
515         },
516         .probe = sirf_audio_codec_driver_probe,
517         .remove = sirf_audio_codec_driver_remove,
518 };
519
520 module_platform_driver(sirf_audio_codec_driver);
521
522 MODULE_DESCRIPTION("SiRF audio codec driver");
523 MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
524 MODULE_LICENSE("GPL v2");