Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * SiRF audio codec driver
  4 *
  5 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
  6 */
  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,
111			codec_enable_bits);
112	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)
122	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);
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
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)
145	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);
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, 0);
155		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
281static 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
331static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
332		int cmd,
333		struct snd_soc_dai *dai)
334{
335	struct snd_soc_component *component = dai->component;
336	struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
337	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
338
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:
347		if (playback) {
348			snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
349				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);
353		break;
354	case SNDRV_PCM_TRIGGER_START:
355	case SNDRV_PCM_TRIGGER_RESUME:
356	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
357		if (playback) {
358			sirf_audio_codec_tx_enable(sirf_audio_codec);
359			snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
360				IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN);
361		} else
362			sirf_audio_codec_rx_enable(sirf_audio_codec,
363				substream->runtime->channels);
364		break;
365	default:
366		return -EINVAL;
367	}
368
369	return 0;
370}
371
372static const struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
373	.trigger = sirf_audio_codec_trigger,
374};
375
376static struct snd_soc_dai_driver sirf_audio_codec_dai = {
377	.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
395static int sirf_audio_codec_probe(struct snd_soc_component *component)
396{
397	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
398
399	pm_runtime_enable(component->dev);
400
401	if (of_device_is_compatible(component->dev->of_node, "sirf,prima2-audio-codec")) {
402		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);
407		return snd_soc_add_component_controls(component,
408			volume_controls_prima2,
409			ARRAY_SIZE(volume_controls_prima2));
410	}
411	if (of_device_is_compatible(component->dev->of_node, "sirf,atlas6-audio-codec")) {
412		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);
417		return snd_soc_add_component_controls(component,
418			volume_controls_atlas6,
419			ARRAY_SIZE(volume_controls_atlas6));
420	}
421
422	return -EINVAL;
423}
424
425static void sirf_audio_codec_remove(struct snd_soc_component *component)
426{
427	pm_runtime_disable(component->dev);
428}
429
430static 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,
440};
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,
453	.max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
454	.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;
462
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
470	base = devm_platform_ioremap_resource(pdev, 0);
471	if (IS_ERR(base))
472		return PTR_ERR(base);
473
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
491	ret = devm_snd_soc_register_component(&(pdev->dev),
492			&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);
521
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",
564		.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");