2 * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
4 * Copyright (C) 2010 Texas Instruments, Inc
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/module.h>
23 #include <linux/moduleparam.h>
24 #include <linux/init.h>
26 #include <linux/delay.h>
28 #include <linux/platform_device.h>
29 #include <linux/device.h>
30 #include <linux/slab.h>
31 #include <linux/clk.h>
32 #include <linux/mfd/davinci_voicecodec.h>
34 #include <sound/core.h>
35 #include <sound/pcm.h>
36 #include <sound/pcm_params.h>
37 #include <sound/soc.h>
38 #include <sound/soc-dai.h>
39 #include <sound/soc-dapm.h>
40 #include <sound/initval.h>
42 #include <mach/dm365.h>
46 static inline unsigned int cq93vc_read(struct snd_soc_codec
*codec
,
49 struct davinci_vc
*davinci_vc
= codec
->control_data
;
51 return readl(davinci_vc
->base
+ reg
);
54 static inline int cq93vc_write(struct snd_soc_codec
*codec
, unsigned int reg
,
57 struct davinci_vc
*davinci_vc
= codec
->control_data
;
59 writel(value
, davinci_vc
->base
+ reg
);
64 static const struct snd_kcontrol_new cq93vc_snd_controls
[] = {
65 SOC_SINGLE("PGA Capture Volume", DAVINCI_VC_REG05
, 0, 0x03, 0),
66 SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09
, 0, 0x3f, 0),
69 static int cq93vc_mute(struct snd_soc_dai
*dai
, int mute
)
71 struct snd_soc_codec
*codec
= dai
->codec
;
72 u8 reg
= cq93vc_read(codec
, DAVINCI_VC_REG09
) & ~DAVINCI_VC_REG09_MUTE
;
75 cq93vc_write(codec
, DAVINCI_VC_REG09
,
76 reg
| DAVINCI_VC_REG09_MUTE
);
78 cq93vc_write(codec
, DAVINCI_VC_REG09
, reg
);
83 static int cq93vc_set_dai_sysclk(struct snd_soc_dai
*codec_dai
,
84 int clk_id
, unsigned int freq
, int dir
)
86 struct snd_soc_codec
*codec
= codec_dai
->codec
;
87 struct davinci_vc
*davinci_vc
= codec
->control_data
;
93 davinci_vc
->cq93vc
.sysclk
= freq
;
100 static int cq93vc_set_bias_level(struct snd_soc_codec
*codec
,
101 enum snd_soc_bias_level level
)
104 case SND_SOC_BIAS_ON
:
105 cq93vc_write(codec
, DAVINCI_VC_REG12
,
106 DAVINCI_VC_REG12_POWER_ALL_ON
);
108 case SND_SOC_BIAS_PREPARE
:
110 case SND_SOC_BIAS_STANDBY
:
111 cq93vc_write(codec
, DAVINCI_VC_REG12
,
112 DAVINCI_VC_REG12_POWER_ALL_OFF
);
114 case SND_SOC_BIAS_OFF
:
115 /* force all power off */
116 cq93vc_write(codec
, DAVINCI_VC_REG12
,
117 DAVINCI_VC_REG12_POWER_ALL_OFF
);
120 codec
->bias_level
= level
;
125 #define CQ93VC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
126 #define CQ93VC_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
128 static struct snd_soc_dai_ops cq93vc_dai_ops
= {
129 .digital_mute
= cq93vc_mute
,
130 .set_sysclk
= cq93vc_set_dai_sysclk
,
133 struct snd_soc_dai cq93vc_dai
= {
136 .stream_name
= "Playback",
139 .rates
= CQ93VC_RATES
,
140 .formats
= CQ93VC_FORMATS
,},
142 .stream_name
= "Capture",
145 .rates
= CQ93VC_RATES
,
146 .formats
= CQ93VC_FORMATS
,},
147 .ops
= &cq93vc_dai_ops
,
149 EXPORT_SYMBOL_GPL(cq93vc_dai
);
151 static int cq93vc_resume(struct platform_device
*pdev
)
153 struct snd_soc_device
*socdev
= platform_get_drvdata(pdev
);
154 struct snd_soc_codec
*codec
= socdev
->card
->codec
;
156 cq93vc_set_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
161 static struct snd_soc_codec
*cq93vc_codec
;
163 static int cq93vc_probe(struct platform_device
*pdev
)
165 struct snd_soc_device
*socdev
= platform_get_drvdata(pdev
);
166 struct device
*dev
= &pdev
->dev
;
167 struct snd_soc_codec
*codec
;
170 socdev
->card
->codec
= cq93vc_codec
;
171 codec
= socdev
->card
->codec
;
174 ret
= snd_soc_new_pcms(socdev
, SNDRV_DEFAULT_IDX1
, SNDRV_DEFAULT_STR1
);
176 dev_err(dev
, "%s: failed to create pcms\n", pdev
->name
);
181 snd_soc_add_controls(codec
, cq93vc_snd_controls
,
182 ARRAY_SIZE(cq93vc_snd_controls
));
184 /* Off, with power on */
185 cq93vc_set_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
190 static int cq93vc_remove(struct platform_device
*pdev
)
192 struct snd_soc_device
*socdev
= platform_get_drvdata(pdev
);
194 snd_soc_free_pcms(socdev
);
195 snd_soc_dapm_free(socdev
);
200 struct snd_soc_codec_device soc_codec_dev_cq93vc
= {
201 .probe
= cq93vc_probe
,
202 .remove
= cq93vc_remove
,
203 .resume
= cq93vc_resume
,
205 EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc
);
207 static __init
int cq93vc_codec_probe(struct platform_device
*pdev
)
209 struct davinci_vc
*davinci_vc
= platform_get_drvdata(pdev
);
210 struct snd_soc_codec
*codec
;
213 codec
= kzalloc(sizeof(struct snd_soc_codec
), GFP_KERNEL
);
215 dev_dbg(davinci_vc
->dev
,
216 "could not allocate memory for codec data\n");
220 davinci_vc
->cq93vc
.codec
= codec
;
222 cq93vc_dai
.dev
= &pdev
->dev
;
224 mutex_init(&codec
->mutex
);
225 INIT_LIST_HEAD(&codec
->dapm_widgets
);
226 INIT_LIST_HEAD(&codec
->dapm_paths
);
227 codec
->dev
= &pdev
->dev
;
228 codec
->name
= "CQ93VC";
229 codec
->owner
= THIS_MODULE
;
230 codec
->read
= cq93vc_read
;
231 codec
->write
= cq93vc_write
;
232 codec
->set_bias_level
= cq93vc_set_bias_level
;
233 codec
->dai
= &cq93vc_dai
;
235 codec
->control_data
= davinci_vc
;
237 cq93vc_codec
= codec
;
239 ret
= snd_soc_register_codec(codec
);
241 dev_err(davinci_vc
->dev
, "failed to register codec\n");
245 ret
= snd_soc_register_dai(&cq93vc_dai
);
247 dev_err(davinci_vc
->dev
, "could register dai\n");
253 snd_soc_unregister_codec(codec
);
262 static int __devexit
cq93vc_codec_remove(struct platform_device
*pdev
)
264 struct snd_soc_device
*socdev
= platform_get_drvdata(pdev
);
265 struct snd_soc_codec
*codec
= socdev
->card
->codec
;
267 snd_soc_unregister_dai(&cq93vc_dai
);
268 snd_soc_unregister_codec(&codec
);
276 static struct platform_driver cq93vc_codec_driver
= {
279 .owner
= THIS_MODULE
,
281 .probe
= cq93vc_codec_probe
,
282 .remove
= __devexit_p(cq93vc_codec_remove
),
285 static __init
int cq93vc_init(void)
287 return platform_driver_probe(&cq93vc_codec_driver
, cq93vc_codec_probe
);
289 module_init(cq93vc_init
);
291 static __exit
void cq93vc_exit(void)
293 platform_driver_unregister(&cq93vc_codec_driver
);
295 module_exit(cq93vc_exit
);
297 MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC CQ0093 Voice Codec Driver");
298 MODULE_AUTHOR("Miguel Aguilar");
299 MODULE_LICENSE("GPL");