Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  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
 28struct sirf_audio_codec {
 29	struct clk *clk;
 30	struct regmap *regmap;
 31	u32 reg_ctrl0, reg_ctrl1;
 32};
 33
 34static const char * const input_mode_mux[] = {"Single-ended",
 35	"Differential"};
 36
 37static const struct soc_enum input_mode_mux_enum =
 38	SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux);
 39
 40static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control =
 41	SOC_DAPM_ENUM("Route", input_mode_mux_enum);
 42
 43static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0);
 44static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0);
 45static 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
 50static 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
 57static 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
 64static 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
 69static 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
 74static 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
 77static 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
 80static 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
 83static 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
 86static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control =
 87	SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0);
 88
 89static 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 */
 93static 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
107static 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
118static 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 snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
124	struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
125	switch (event) {
126	case SND_SOC_DAPM_PRE_PMU:
127		enable_and_reset_codec(sirf_audio_codec->regmap,
128			ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS);
129		break;
130	case SND_SOC_DAPM_POST_PMD:
131		regmap_update_bits(sirf_audio_codec->regmap,
132			AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, 0);
133		break;
134	default:
135		break;
136	}
137
138	return 0;
139}
140
141static 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 snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
147	struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
148	switch (event) {
149	case SND_SOC_DAPM_POST_PMU:
150		enable_and_reset_codec(sirf_audio_codec->regmap,
151			PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS);
152		break;
153	case SND_SOC_DAPM_POST_PMD:
154		regmap_update_bits(sirf_audio_codec->regmap,
155			AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, 0);
156		break;
157	default:
158		break;
159	}
160
161	return 0;
162}
163
164static 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
173static 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
182static 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
187static 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
192static 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
242static 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
282static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec)
283{
284	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
285		AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
286	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
287		AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
288	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0);
289	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
290	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
291		AUDIO_FIFO_START, AUDIO_FIFO_START);
292	regmap_update_bits(sirf_audio_codec->regmap,
293		AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE);
294}
295
296static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec)
297{
298	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
299	regmap_update_bits(sirf_audio_codec->regmap,
300		AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE);
301}
302
303static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec,
304	int channels)
305{
306	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
307		AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
308	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
309		AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
310	regmap_write(sirf_audio_codec->regmap,
311		AUDIO_PORT_IC_RXFIFO_INT_MSK, 0);
312	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0);
313	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
314		AUDIO_FIFO_START, AUDIO_FIFO_START);
315	if (channels == 1)
316		regmap_update_bits(sirf_audio_codec->regmap,
317			AUDIO_PORT_IC_CODEC_RX_CTRL,
318			IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO);
319	else
320		regmap_update_bits(sirf_audio_codec->regmap,
321			AUDIO_PORT_IC_CODEC_RX_CTRL,
322			IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO);
323}
324
325static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec)
326{
327	regmap_update_bits(sirf_audio_codec->regmap,
328			AUDIO_PORT_IC_CODEC_RX_CTRL,
329			IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO);
330}
331
332static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
333		int cmd,
334		struct snd_soc_dai *dai)
335{
336	struct snd_soc_component *component = dai->component;
337	struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
338	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
339
340	/*
341	 * This is a workaround, When stop playback,
342	 * need disable HP amp, avoid the current noise.
343	 */
344	switch (cmd) {
345	case SNDRV_PCM_TRIGGER_STOP:
346	case SNDRV_PCM_TRIGGER_SUSPEND:
347	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
348		if (playback) {
349			snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
350				IC_HSLEN | IC_HSREN, 0);
351			sirf_audio_codec_tx_disable(sirf_audio_codec);
352		} else
353			sirf_audio_codec_rx_disable(sirf_audio_codec);
354		break;
355	case SNDRV_PCM_TRIGGER_START:
356	case SNDRV_PCM_TRIGGER_RESUME:
357	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
358		if (playback) {
359			sirf_audio_codec_tx_enable(sirf_audio_codec);
360			snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
361				IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN);
362		} else
363			sirf_audio_codec_rx_enable(sirf_audio_codec,
364				substream->runtime->channels);
365		break;
366	default:
367		return -EINVAL;
368	}
369
370	return 0;
371}
372
373static const struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
374	.trigger = sirf_audio_codec_trigger,
375};
376
377static struct snd_soc_dai_driver sirf_audio_codec_dai = {
378	.name = "sirf-audio-codec",
379	.playback = {
380		.stream_name = "Playback",
381		.channels_min = 2,
382		.channels_max = 2,
383		.rates = SNDRV_PCM_RATE_48000,
384		.formats = SNDRV_PCM_FMTBIT_S16_LE,
385	},
386	.capture = {
387		.stream_name = "Capture",
388		.channels_min = 1,
389		.channels_max = 2,
390		.rates = SNDRV_PCM_RATE_48000,
391		.formats = SNDRV_PCM_FMTBIT_S16_LE,
392	},
393	.ops = &sirf_audio_codec_dai_ops,
394};
395
396static int sirf_audio_codec_probe(struct snd_soc_component *component)
397{
398	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
399
400	pm_runtime_enable(component->dev);
401
402	if (of_device_is_compatible(component->dev->of_node, "sirf,prima2-audio-codec")) {
403		snd_soc_dapm_new_controls(dapm,
404			prima2_output_driver_dapm_widgets,
405			ARRAY_SIZE(prima2_output_driver_dapm_widgets));
406		snd_soc_dapm_new_controls(dapm,
407			&prima2_codec_clock_dapm_widget, 1);
408		return snd_soc_add_component_controls(component,
409			volume_controls_prima2,
410			ARRAY_SIZE(volume_controls_prima2));
411	}
412	if (of_device_is_compatible(component->dev->of_node, "sirf,atlas6-audio-codec")) {
413		snd_soc_dapm_new_controls(dapm,
414			atlas6_output_driver_dapm_widgets,
415			ARRAY_SIZE(atlas6_output_driver_dapm_widgets));
416		snd_soc_dapm_new_controls(dapm,
417			&atlas6_codec_clock_dapm_widget, 1);
418		return snd_soc_add_component_controls(component,
419			volume_controls_atlas6,
420			ARRAY_SIZE(volume_controls_atlas6));
421	}
422
423	return -EINVAL;
424}
425
426static void sirf_audio_codec_remove(struct snd_soc_component *component)
427{
428	pm_runtime_disable(component->dev);
429}
430
431static const struct snd_soc_component_driver soc_codec_device_sirf_audio_codec = {
432	.probe			= sirf_audio_codec_probe,
433	.remove			= sirf_audio_codec_remove,
434	.dapm_widgets		= sirf_audio_codec_dapm_widgets,
435	.num_dapm_widgets	= ARRAY_SIZE(sirf_audio_codec_dapm_widgets),
436	.dapm_routes		= sirf_audio_codec_map,
437	.num_dapm_routes	= ARRAY_SIZE(sirf_audio_codec_map),
438	.use_pmdown_time	= 1,
439	.endianness		= 1,
440	.non_legacy_dai_naming	= 1,
441};
442
443static const struct of_device_id sirf_audio_codec_of_match[] = {
444	{ .compatible = "sirf,prima2-audio-codec" },
445	{ .compatible = "sirf,atlas6-audio-codec" },
446	{}
447};
448MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match);
449
450static const struct regmap_config sirf_audio_codec_regmap_config = {
451	.reg_bits = 32,
452	.reg_stride = 4,
453	.val_bits = 32,
454	.max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
455	.cache_type = REGCACHE_NONE,
456};
457
458static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
459{
460	int ret;
461	struct sirf_audio_codec *sirf_audio_codec;
462	void __iomem *base;
463	struct resource *mem_res;
464	const struct of_device_id *match;
465
466	match = of_match_node(sirf_audio_codec_of_match, pdev->dev.of_node);
467
468	sirf_audio_codec = devm_kzalloc(&pdev->dev,
469		sizeof(struct sirf_audio_codec), GFP_KERNEL);
470	if (!sirf_audio_codec)
471		return -ENOMEM;
472
473	platform_set_drvdata(pdev, sirf_audio_codec);
474
475	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
476	base = devm_ioremap_resource(&pdev->dev, mem_res);
477	if (IS_ERR(base))
478		return PTR_ERR(base);
479
480	sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
481					    &sirf_audio_codec_regmap_config);
482	if (IS_ERR(sirf_audio_codec->regmap))
483		return PTR_ERR(sirf_audio_codec->regmap);
484
485	sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL);
486	if (IS_ERR(sirf_audio_codec->clk)) {
487		dev_err(&pdev->dev, "Get clock failed.\n");
488		return PTR_ERR(sirf_audio_codec->clk);
489	}
490
491	ret = clk_prepare_enable(sirf_audio_codec->clk);
492	if (ret) {
493		dev_err(&pdev->dev, "Enable clock failed.\n");
494		return ret;
495	}
496
497	ret = devm_snd_soc_register_component(&(pdev->dev),
498			&soc_codec_device_sirf_audio_codec,
499			&sirf_audio_codec_dai, 1);
500	if (ret) {
501		dev_err(&pdev->dev, "Register Audio Codec dai failed.\n");
502		goto err_clk_put;
503	}
504
505	/*
506	 * Always open charge pump, if not, when the charge pump closed the
507	 * adc will not stable
508	 */
509	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
510		IC_CPFREQ, IC_CPFREQ);
511
512	if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec"))
513		regmap_update_bits(sirf_audio_codec->regmap,
514				AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN);
515	return 0;
516
517err_clk_put:
518	clk_disable_unprepare(sirf_audio_codec->clk);
519	return ret;
520}
521
522static int sirf_audio_codec_driver_remove(struct platform_device *pdev)
523{
524	struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev);
525
526	clk_disable_unprepare(sirf_audio_codec->clk);
527
528	return 0;
529}
530
531#ifdef CONFIG_PM_SLEEP
532static int sirf_audio_codec_suspend(struct device *dev)
533{
534	struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
535
536	regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
537		&sirf_audio_codec->reg_ctrl0);
538	regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
539		&sirf_audio_codec->reg_ctrl1);
540	clk_disable_unprepare(sirf_audio_codec->clk);
541
542	return 0;
543}
544
545static int sirf_audio_codec_resume(struct device *dev)
546{
547	struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
548	int ret;
549
550	ret = clk_prepare_enable(sirf_audio_codec->clk);
551	if (ret)
552		return ret;
553
554	regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
555		sirf_audio_codec->reg_ctrl0);
556	regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
557		sirf_audio_codec->reg_ctrl1);
558
559	return 0;
560}
561#endif
562
563static const struct dev_pm_ops sirf_audio_codec_pm_ops = {
564	SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume)
565};
566
567static struct platform_driver sirf_audio_codec_driver = {
568	.driver = {
569		.name = "sirf-audio-codec",
570		.of_match_table = sirf_audio_codec_of_match,
571		.pm = &sirf_audio_codec_pm_ops,
572	},
573	.probe = sirf_audio_codec_driver_probe,
574	.remove = sirf_audio_codec_driver_remove,
575};
576
577module_platform_driver(sirf_audio_codec_driver);
578
579MODULE_DESCRIPTION("SiRF audio codec driver");
580MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
581MODULE_LICENSE("GPL v2");