aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/stac9766.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/stac9766.c')
-rw-r--r--sound/soc/codecs/stac9766.c118
1 files changed, 50 insertions, 68 deletions
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index ee86568545c2..00d67cc8e206 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -25,7 +25,6 @@
25#include <sound/pcm_params.h> 25#include <sound/pcm_params.h>
26#include <sound/soc.h> 26#include <sound/soc.h>
27#include <sound/tlv.h> 27#include <sound/tlv.h>
28#include <sound/soc-of-simple.h>
29 28
30#include "stac9766.h" 29#include "stac9766.h"
31 30
@@ -257,20 +256,15 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
257 return 0; 256 return 0;
258} 257}
259 258
260static int stac9766_codec_suspend(struct platform_device *pdev, 259static int stac9766_codec_suspend(struct snd_soc_codec *codec,
261 pm_message_t state) 260 pm_message_t state)
262{ 261{
263 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
264 struct snd_soc_codec *codec = socdev->card->codec;
265
266 stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF); 262 stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);
267 return 0; 263 return 0;
268} 264}
269 265
270static int stac9766_codec_resume(struct platform_device *pdev) 266static int stac9766_codec_resume(struct snd_soc_codec *codec)
271{ 267{
272 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
273 struct snd_soc_codec *codec = socdev->card->codec;
274 u16 id, reset; 268 u16 id, reset;
275 269
276 reset = 0; 270 reset = 0;
@@ -300,10 +294,9 @@ static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
300 .prepare = ac97_digital_prepare, 294 .prepare = ac97_digital_prepare,
301}; 295};
302 296
303struct snd_soc_dai stac9766_dai[] = { 297static struct snd_soc_dai_driver stac9766_dai[] = {
304{ 298{
305 .name = "stac9766 analog", 299 .name = "stac9766-hifi-analog",
306 .id = 0,
307 .ac97_control = 1, 300 .ac97_control = 1,
308 301
309 /* stream cababilities */ 302 /* stream cababilities */
@@ -325,8 +318,7 @@ struct snd_soc_dai stac9766_dai[] = {
325 .ops = &stac9766_dai_ops_analog, 318 .ops = &stac9766_dai_ops_analog,
326}, 319},
327{ 320{
328 .name = "stac9766 IEC958", 321 .name = "stac9766-hifi-IEC958",
329 .id = 1,
330 .ac97_control = 1, 322 .ac97_control = 1,
331 323
332 /* stream cababilities */ 324 /* stream cababilities */
@@ -342,57 +334,24 @@ struct snd_soc_dai stac9766_dai[] = {
342 .ops = &stac9766_dai_ops_digital, 334 .ops = &stac9766_dai_ops_digital,
343} 335}
344}; 336};
345EXPORT_SYMBOL_GPL(stac9766_dai);
346 337
347static int stac9766_codec_probe(struct platform_device *pdev) 338static int stac9766_codec_probe(struct snd_soc_codec *codec)
348{ 339{
349 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
350 struct snd_soc_codec *codec;
351 int ret = 0; 340 int ret = 0;
352 341
353 printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); 342 printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION);
354 343
355 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
356 if (socdev->card->codec == NULL)
357 return -ENOMEM;
358 codec = socdev->card->codec;
359 mutex_init(&codec->mutex);
360
361 codec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg),
362 GFP_KERNEL);
363 if (codec->reg_cache == NULL) {
364 ret = -ENOMEM;
365 goto cache_err;
366 }
367 codec->reg_cache_size = sizeof(stac9766_reg);
368 codec->reg_cache_step = 2;
369
370 codec->name = "STAC9766";
371 codec->owner = THIS_MODULE;
372 codec->dai = stac9766_dai;
373 codec->num_dai = ARRAY_SIZE(stac9766_dai);
374 codec->write = stac9766_ac97_write;
375 codec->read = stac9766_ac97_read;
376 codec->set_bias_level = stac9766_set_bias_level;
377 INIT_LIST_HEAD(&codec->dapm_widgets);
378 INIT_LIST_HEAD(&codec->dapm_paths);
379
380 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); 344 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
381 if (ret < 0) 345 if (ret < 0)
382 goto codec_err; 346 goto codec_err;
383 347
384 /* register pcms */
385 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
386 if (ret < 0)
387 goto pcm_err;
388
389 /* do a cold reset for the controller and then try 348 /* do a cold reset for the controller and then try
390 * a warm reset followed by an optional cold reset for codec */ 349 * a warm reset followed by an optional cold reset for codec */
391 stac9766_reset(codec, 0); 350 stac9766_reset(codec, 0);
392 ret = stac9766_reset(codec, 1); 351 ret = stac9766_reset(codec, 1);
393 if (ret < 0) { 352 if (ret < 0) {
394 printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n"); 353 printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n");
395 goto reset_err; 354 goto codec_err;
396 } 355 }
397 356
398 stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 357 stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -402,40 +361,63 @@ static int stac9766_codec_probe(struct platform_device *pdev)
402 361
403 return 0; 362 return 0;
404 363
405reset_err:
406 snd_soc_free_pcms(socdev);
407pcm_err:
408 snd_soc_free_ac97_codec(codec);
409codec_err: 364codec_err:
410 kfree(snd_soc_codec_get_drvdata(codec)); 365 snd_soc_free_ac97_codec(codec);
411cache_err:
412 kfree(socdev->card->codec);
413 socdev->card->codec = NULL;
414 return ret; 366 return ret;
415} 367}
416 368
417static int stac9766_codec_remove(struct platform_device *pdev) 369static int stac9766_codec_remove(struct snd_soc_codec *codec)
418{ 370{
419 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
420 struct snd_soc_codec *codec = socdev->card->codec;
421
422 if (codec == NULL)
423 return 0;
424
425 snd_soc_free_pcms(socdev);
426 snd_soc_free_ac97_codec(codec); 371 snd_soc_free_ac97_codec(codec);
427 kfree(codec->reg_cache);
428 kfree(codec);
429 return 0; 372 return 0;
430} 373}
431 374
432struct snd_soc_codec_device soc_codec_dev_stac9766 = { 375static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
376 .write = stac9766_ac97_write,
377 .read = stac9766_ac97_read,
378 .set_bias_level = stac9766_set_bias_level,
433 .probe = stac9766_codec_probe, 379 .probe = stac9766_codec_probe,
434 .remove = stac9766_codec_remove, 380 .remove = stac9766_codec_remove,
435 .suspend = stac9766_codec_suspend, 381 .suspend = stac9766_codec_suspend,
436 .resume = stac9766_codec_resume, 382 .resume = stac9766_codec_resume,
383 .reg_cache_size = sizeof(stac9766_reg),
384 .reg_word_size = sizeof(u16),
385 .reg_cache_step = 2,
386};
387
388static __devinit int stac9766_probe(struct platform_device *pdev)
389{
390 return snd_soc_register_codec(&pdev->dev,
391 &soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai));
392}
393
394static int __devexit stac9766_remove(struct platform_device *pdev)
395{
396 snd_soc_unregister_codec(&pdev->dev);
397 return 0;
398}
399
400static struct platform_driver stac9766_codec_driver = {
401 .driver = {
402 .name = "stac9766-codec",
403 .owner = THIS_MODULE,
404 },
405
406 .probe = stac9766_probe,
407 .remove = __devexit_p(stac9766_remove),
437}; 408};
438EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766); 409
410static int __init stac9766_init(void)
411{
412 return platform_driver_register(&stac9766_codec_driver);
413}
414module_init(stac9766_init);
415
416static void __exit stac9766_exit(void)
417{
418 platform_driver_unregister(&stac9766_codec_driver);
419}
420module_exit(stac9766_exit);
439 421
440MODULE_DESCRIPTION("ASoC stac9766 driver"); 422MODULE_DESCRIPTION("ASoC stac9766 driver");
441MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); 423MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");