aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorJanusz Krzysztofik <jkrzyszt@tis.icnet.pl>2009-07-29 06:24:46 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-07-31 17:38:44 -0400
commitad120dae127f5cb14b4c4ed0b98313fb13b9c846 (patch)
treeb48926e3052008eddf60ff68ccaf0d5f24345031 /sound
parent78ed73e84d132e2d556eda90e5b76620f4390ff2 (diff)
ASoC: CX20442: push down machine independent line discipline bits
This corrected patch adds machine independent line discipline code, prevoiusly exsiting inside my Amstrad Delta ASoC machine dirver, to the Conexant CX20442 codec driver. The code can be used as a standalone line discipline, or as a set of codec specific functions called from machine's line discipline callbacks. Anyway, the line discipline itself must be registered by a machine driver. Applies on top of the followup to my initial driver version: http://mailman.alsa-project.org/pipermail/alsa-devel/2009-July/019757.html Suggested by ASoC manintainer Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/cx20442.c116
-rw-r--r--sound/soc/codecs/cx20442.h1
2 files changed, 111 insertions, 6 deletions
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index 7bbb77baa23..f33245510c3 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -13,6 +13,8 @@
13 * option) any later version. 13 * option) any later version.
14 */ 14 */
15 15
16#include <linux/tty.h>
17
16#include <sound/core.h> 18#include <sound/core.h>
17#include <sound/initval.h> 19#include <sound/initval.h>
18#include <sound/soc-dapm.h> 20#include <sound/soc-dapm.h>
@@ -172,8 +174,7 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
172 return -EINVAL; 174 return -EINVAL;
173 175
174 /* hw_write and control_data pointers required for talking to the modem 176 /* hw_write and control_data pointers required for talking to the modem
175 * are expected to be set by the machine driver's line discipline 177 * are expected to be set by the line discipline initialization code */
176 * initialization code */
177 if (!codec->hw_write || !codec->control_data) 178 if (!codec->hw_write || !codec->control_data)
178 return -EIO; 179 return -EIO;
179 180
@@ -208,6 +209,111 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
208 return 0; 209 return 0;
209} 210}
210 211
212
213/* Moved up here as line discipline referres it during initialization */
214static struct snd_soc_codec *cx20442_codec;
215
216
217/*
218 * Line discpline related code
219 *
220 * Any of the callback functions below can be used in two ways:
221 * 1) registerd by a machine driver as one of line discipline operations,
222 * 2) called from a machine's provided line discipline callback function
223 * in case when extra machine specific code must be run as well.
224 */
225
226/* Modem init: echo off, digital speaker off, quiet off, voice mode */
227static const char *v253_init = "ate0m0q0+fclass=8\r";
228
229/* Line discipline .open() */
230static int v253_open(struct tty_struct *tty)
231{
232 struct snd_soc_codec *codec = cx20442_codec;
233 int ret, len = strlen(v253_init);
234
235 /* Doesn't make sense without write callback */
236 if (!tty->ops->write)
237 return -EINVAL;
238
239 /* Pass the codec structure address for use by other ldisc callbacks */
240 tty->disc_data = codec;
241
242 if (tty->ops->write(tty, v253_init, len) != len) {
243 ret = -EIO;
244 goto err;
245 }
246 /* Actual setup will be performed after the modem responds. */
247 return 0;
248err:
249 tty->disc_data = NULL;
250 return ret;
251}
252
253/* Line discipline .close() */
254static void v253_close(struct tty_struct *tty)
255{
256 struct snd_soc_codec *codec = tty->disc_data;
257
258 tty->disc_data = NULL;
259
260 if (!codec)
261 return;
262
263 /* Prevent the codec driver from further accessing the modem */
264 codec->hw_write = NULL;
265 codec->control_data = NULL;
266 codec->pop_time = 0;
267}
268
269/* Line discipline .hangup() */
270static int v253_hangup(struct tty_struct *tty)
271{
272 v253_close(tty);
273 return 0;
274}
275
276/* Line discipline .receive_buf() */
277static void v253_receive(struct tty_struct *tty,
278 const unsigned char *cp, char *fp, int count)
279{
280 struct snd_soc_codec *codec = tty->disc_data;
281
282 if (!codec)
283 return;
284
285 if (!codec->control_data) {
286 /* First modem response, complete setup procedure */
287
288 /* Set up codec driver access to modem controls */
289 codec->control_data = tty;
290 codec->hw_write = (hw_write_t)tty->ops->write;
291 codec->pop_time = 1;
292 }
293}
294
295/* Line discipline .write_wakeup() */
296static void v253_wakeup(struct tty_struct *tty)
297{
298}
299
300struct tty_ldisc_ops v253_ops = {
301 .magic = TTY_LDISC_MAGIC,
302 .name = "cx20442",
303 .owner = THIS_MODULE,
304 .open = v253_open,
305 .close = v253_close,
306 .hangup = v253_hangup,
307 .receive_buf = v253_receive,
308 .write_wakeup = v253_wakeup,
309};
310EXPORT_SYMBOL_GPL(v253_ops);
311
312
313/*
314 * Codec DAI
315 */
316
211struct snd_soc_dai cx20442_dai = { 317struct snd_soc_dai cx20442_dai = {
212 .name = "CX20442", 318 .name = "CX20442",
213 .playback = { 319 .playback = {
@@ -227,8 +333,6 @@ struct snd_soc_dai cx20442_dai = {
227}; 333};
228EXPORT_SYMBOL_GPL(cx20442_dai); 334EXPORT_SYMBOL_GPL(cx20442_dai);
229 335
230static struct snd_soc_codec *cx20442_codec;
231
232static int cx20442_codec_probe(struct platform_device *pdev) 336static int cx20442_codec_probe(struct platform_device *pdev)
233{ 337{
234 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 338 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -313,13 +417,13 @@ static int cx20442_register(struct cx20442_priv *cx20442)
313 417
314 ret = snd_soc_register_codec(codec); 418 ret = snd_soc_register_codec(codec);
315 if (ret != 0) { 419 if (ret != 0) {
316 dev_err(&codec->dev, "Failed to register codec: %d\n", ret); 420 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
317 goto err; 421 goto err;
318 } 422 }
319 423
320 ret = snd_soc_register_dai(&cx20442_dai); 424 ret = snd_soc_register_dai(&cx20442_dai);
321 if (ret != 0) { 425 if (ret != 0) {
322 dev_err(&codec->dev, "Failed to register DAI: %d\n", ret); 426 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
323 goto err_codec; 427 goto err_codec;
324 } 428 }
325 429
diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h
index d0a4f297aef..688a5eb62e1 100644
--- a/sound/soc/codecs/cx20442.h
+++ b/sound/soc/codecs/cx20442.h
@@ -15,5 +15,6 @@
15 15
16extern struct snd_soc_dai cx20442_dai; 16extern struct snd_soc_dai cx20442_dai;
17extern struct snd_soc_codec_device cx20442_codec_dev; 17extern struct snd_soc_codec_device cx20442_codec_dev;
18extern struct tty_ldisc_ops v253_ops;
18 19
19#endif 20#endif