diff options
Diffstat (limited to 'sound/soc/codecs/ak4535.c')
-rw-r--r-- | sound/soc/codecs/ak4535.c | 236 |
1 files changed, 61 insertions, 175 deletions
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index d4253675b2d3..cd88c8f32a38 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -31,11 +31,11 @@ | |||
31 | 31 | ||
32 | #define AK4535_VERSION "0.3" | 32 | #define AK4535_VERSION "0.3" |
33 | 33 | ||
34 | struct snd_soc_codec_device soc_codec_dev_ak4535; | ||
35 | |||
36 | /* codec private data */ | 34 | /* codec private data */ |
37 | struct ak4535_priv { | 35 | struct ak4535_priv { |
38 | unsigned int sysclk; | 36 | unsigned int sysclk; |
37 | enum snd_soc_control_type control_type; | ||
38 | void *control_data; | ||
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* | 41 | /* |
@@ -313,8 +313,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, | |||
313 | struct snd_soc_dai *dai) | 313 | struct snd_soc_dai *dai) |
314 | { | 314 | { |
315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
316 | struct snd_soc_device *socdev = rtd->socdev; | 316 | struct snd_soc_codec *codec = rtd->codec; |
317 | struct snd_soc_codec *codec = socdev->card->codec; | ||
318 | struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); | 317 | struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); |
319 | u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); | 318 | u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); |
320 | int rate = params_rate(params), fs = 256; | 319 | int rate = params_rate(params), fs = 256; |
@@ -378,14 +377,16 @@ static int ak4535_mute(struct snd_soc_dai *dai, int mute) | |||
378 | static int ak4535_set_bias_level(struct snd_soc_codec *codec, | 377 | static int ak4535_set_bias_level(struct snd_soc_codec *codec, |
379 | enum snd_soc_bias_level level) | 378 | enum snd_soc_bias_level level) |
380 | { | 379 | { |
381 | u16 i; | 380 | u16 i, mute_reg; |
382 | 381 | ||
383 | switch (level) { | 382 | switch (level) { |
384 | case SND_SOC_BIAS_ON: | 383 | case SND_SOC_BIAS_ON: |
385 | ak4535_mute(codec->dai, 0); | 384 | mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf; |
385 | ak4535_write(codec, AK4535_DAC, mute_reg); | ||
386 | break; | 386 | break; |
387 | case SND_SOC_BIAS_PREPARE: | 387 | case SND_SOC_BIAS_PREPARE: |
388 | ak4535_mute(codec->dai, 1); | 388 | mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf; |
389 | ak4535_write(codec, AK4535_DAC, mute_reg | 0x20); | ||
389 | break; | 390 | break; |
390 | case SND_SOC_BIAS_STANDBY: | 391 | case SND_SOC_BIAS_STANDBY: |
391 | i = ak4535_read_reg_cache(codec, AK4535_PM1); | 392 | i = ak4535_read_reg_cache(codec, AK4535_PM1); |
@@ -413,8 +414,8 @@ static struct snd_soc_dai_ops ak4535_dai_ops = { | |||
413 | .set_sysclk = ak4535_set_dai_sysclk, | 414 | .set_sysclk = ak4535_set_dai_sysclk, |
414 | }; | 415 | }; |
415 | 416 | ||
416 | struct snd_soc_dai ak4535_dai = { | 417 | static struct snd_soc_dai_driver ak4535_dai = { |
417 | .name = "AK4535", | 418 | .name = "ak4535-hifi", |
418 | .playback = { | 419 | .playback = { |
419 | .stream_name = "Playback", | 420 | .stream_name = "Playback", |
420 | .channels_min = 1, | 421 | .channels_min = 1, |
@@ -429,54 +430,27 @@ struct snd_soc_dai ak4535_dai = { | |||
429 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 430 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
430 | .ops = &ak4535_dai_ops, | 431 | .ops = &ak4535_dai_ops, |
431 | }; | 432 | }; |
432 | EXPORT_SYMBOL_GPL(ak4535_dai); | ||
433 | 433 | ||
434 | static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) | 434 | static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state) |
435 | { | 435 | { |
436 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
437 | struct snd_soc_codec *codec = socdev->card->codec; | ||
438 | |||
439 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | 436 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); |
440 | return 0; | 437 | return 0; |
441 | } | 438 | } |
442 | 439 | ||
443 | static int ak4535_resume(struct platform_device *pdev) | 440 | static int ak4535_resume(struct snd_soc_codec *codec) |
444 | { | 441 | { |
445 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
446 | struct snd_soc_codec *codec = socdev->card->codec; | ||
447 | ak4535_sync(codec); | 442 | ak4535_sync(codec); |
448 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 443 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
449 | return 0; | 444 | return 0; |
450 | } | 445 | } |
451 | 446 | ||
452 | /* | 447 | static int ak4535_probe(struct snd_soc_codec *codec) |
453 | * initialise the AK4535 driver | ||
454 | * register the mixer and dsp interfaces with the kernel | ||
455 | */ | ||
456 | static int ak4535_init(struct snd_soc_device *socdev) | ||
457 | { | 448 | { |
458 | struct snd_soc_codec *codec = socdev->card->codec; | 449 | struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); |
459 | int ret = 0; | ||
460 | 450 | ||
461 | codec->name = "AK4535"; | 451 | printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); |
462 | codec->owner = THIS_MODULE; | ||
463 | codec->read = ak4535_read_reg_cache; | ||
464 | codec->write = ak4535_write; | ||
465 | codec->set_bias_level = ak4535_set_bias_level; | ||
466 | codec->dai = &ak4535_dai; | ||
467 | codec->num_dai = 1; | ||
468 | codec->reg_cache_size = ARRAY_SIZE(ak4535_reg); | ||
469 | codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL); | ||
470 | |||
471 | if (codec->reg_cache == NULL) | ||
472 | return -ENOMEM; | ||
473 | 452 | ||
474 | /* register pcms */ | 453 | codec->control_data = ak4535->control_data; |
475 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
476 | if (ret < 0) { | ||
477 | printk(KERN_ERR "ak4535: failed to create pcms\n"); | ||
478 | goto pcm_err; | ||
479 | } | ||
480 | 454 | ||
481 | /* power on device */ | 455 | /* power on device */ |
482 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 456 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -485,39 +459,55 @@ static int ak4535_init(struct snd_soc_device *socdev) | |||
485 | ARRAY_SIZE(ak4535_snd_controls)); | 459 | ARRAY_SIZE(ak4535_snd_controls)); |
486 | ak4535_add_widgets(codec); | 460 | ak4535_add_widgets(codec); |
487 | 461 | ||
488 | return ret; | 462 | return 0; |
489 | 463 | } | |
490 | pcm_err: | ||
491 | kfree(codec->reg_cache); | ||
492 | 464 | ||
493 | return ret; | 465 | /* power down chip */ |
466 | static int ak4535_remove(struct snd_soc_codec *codec) | ||
467 | { | ||
468 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
469 | return 0; | ||
494 | } | 470 | } |
495 | 471 | ||
496 | static struct snd_soc_device *ak4535_socdev; | 472 | static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { |
473 | .probe = ak4535_probe, | ||
474 | .remove = ak4535_remove, | ||
475 | .suspend = ak4535_suspend, | ||
476 | .resume = ak4535_resume, | ||
477 | .read = ak4535_read_reg_cache, | ||
478 | .write = ak4535_write, | ||
479 | .set_bias_level = ak4535_set_bias_level, | ||
480 | .reg_cache_size = ARRAY_SIZE(ak4535_reg), | ||
481 | .reg_word_size = sizeof(u8), | ||
482 | .reg_cache_default = ak4535_reg, | ||
483 | }; | ||
497 | 484 | ||
498 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 485 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
499 | 486 | static __devinit int ak4535_i2c_probe(struct i2c_client *i2c, | |
500 | static int ak4535_i2c_probe(struct i2c_client *i2c, | 487 | const struct i2c_device_id *id) |
501 | const struct i2c_device_id *id) | ||
502 | { | 488 | { |
503 | struct snd_soc_device *socdev = ak4535_socdev; | 489 | struct ak4535_priv *ak4535; |
504 | struct snd_soc_codec *codec = socdev->card->codec; | ||
505 | int ret; | 490 | int ret; |
506 | 491 | ||
507 | i2c_set_clientdata(i2c, codec); | 492 | ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL); |
508 | codec->control_data = i2c; | 493 | if (ak4535 == NULL) |
494 | return -ENOMEM; | ||
509 | 495 | ||
510 | ret = ak4535_init(socdev); | 496 | i2c_set_clientdata(i2c, ak4535); |
511 | if (ret < 0) | 497 | ak4535->control_data = i2c; |
512 | printk(KERN_ERR "failed to initialise AK4535\n"); | 498 | ak4535->control_type = SND_SOC_I2C; |
513 | 499 | ||
500 | ret = snd_soc_register_codec(&i2c->dev, | ||
501 | &soc_codec_dev_ak4535, &ak4535_dai, 1); | ||
502 | if (ret < 0) | ||
503 | kfree(ak4535); | ||
514 | return ret; | 504 | return ret; |
515 | } | 505 | } |
516 | 506 | ||
517 | static int ak4535_i2c_remove(struct i2c_client *client) | 507 | static __devexit int ak4535_i2c_remove(struct i2c_client *client) |
518 | { | 508 | { |
519 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 509 | snd_soc_unregister_codec(&client->dev); |
520 | kfree(codec->reg_cache); | 510 | kfree(i2c_get_clientdata(client)); |
521 | return 0; | 511 | return 0; |
522 | } | 512 | } |
523 | 513 | ||
@@ -529,138 +519,34 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id); | |||
529 | 519 | ||
530 | static struct i2c_driver ak4535_i2c_driver = { | 520 | static struct i2c_driver ak4535_i2c_driver = { |
531 | .driver = { | 521 | .driver = { |
532 | .name = "AK4535 I2C Codec", | 522 | .name = "ak4535-codec", |
533 | .owner = THIS_MODULE, | 523 | .owner = THIS_MODULE, |
534 | }, | 524 | }, |
535 | .probe = ak4535_i2c_probe, | 525 | .probe = ak4535_i2c_probe, |
536 | .remove = ak4535_i2c_remove, | 526 | .remove = __devexit_p(ak4535_i2c_remove), |
537 | .id_table = ak4535_i2c_id, | 527 | .id_table = ak4535_i2c_id, |
538 | }; | 528 | }; |
539 | |||
540 | static int ak4535_add_i2c_device(struct platform_device *pdev, | ||
541 | const struct ak4535_setup_data *setup) | ||
542 | { | ||
543 | struct i2c_board_info info; | ||
544 | struct i2c_adapter *adapter; | ||
545 | struct i2c_client *client; | ||
546 | int ret; | ||
547 | |||
548 | ret = i2c_add_driver(&ak4535_i2c_driver); | ||
549 | if (ret != 0) { | ||
550 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
555 | info.addr = setup->i2c_address; | ||
556 | strlcpy(info.type, "ak4535", I2C_NAME_SIZE); | ||
557 | |||
558 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
559 | if (!adapter) { | ||
560 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
561 | setup->i2c_bus); | ||
562 | goto err_driver; | ||
563 | } | ||
564 | |||
565 | client = i2c_new_device(adapter, &info); | ||
566 | i2c_put_adapter(adapter); | ||
567 | if (!client) { | ||
568 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
569 | (unsigned int)info.addr); | ||
570 | goto err_driver; | ||
571 | } | ||
572 | |||
573 | return 0; | ||
574 | |||
575 | err_driver: | ||
576 | i2c_del_driver(&ak4535_i2c_driver); | ||
577 | return -ENODEV; | ||
578 | } | ||
579 | #endif | 529 | #endif |
580 | 530 | ||
581 | static int ak4535_probe(struct platform_device *pdev) | 531 | static int __init ak4535_modinit(void) |
582 | { | 532 | { |
583 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 533 | int ret = 0; |
584 | struct ak4535_setup_data *setup; | ||
585 | struct snd_soc_codec *codec; | ||
586 | struct ak4535_priv *ak4535; | ||
587 | int ret; | ||
588 | |||
589 | printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); | ||
590 | |||
591 | setup = socdev->codec_data; | ||
592 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
593 | if (codec == NULL) | ||
594 | return -ENOMEM; | ||
595 | |||
596 | ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL); | ||
597 | if (ak4535 == NULL) { | ||
598 | kfree(codec); | ||
599 | return -ENOMEM; | ||
600 | } | ||
601 | |||
602 | snd_soc_codec_set_drvdata(codec, ak4535); | ||
603 | socdev->card->codec = codec; | ||
604 | mutex_init(&codec->mutex); | ||
605 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
606 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
607 | |||
608 | ak4535_socdev = socdev; | ||
609 | ret = -ENODEV; | ||
610 | |||
611 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 534 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
612 | if (setup->i2c_address) { | 535 | ret = i2c_add_driver(&ak4535_i2c_driver); |
613 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
614 | ret = ak4535_add_i2c_device(pdev, setup); | ||
615 | } | ||
616 | #endif | ||
617 | |||
618 | if (ret != 0) { | 536 | if (ret != 0) { |
619 | kfree(snd_soc_codec_get_drvdata(codec)); | 537 | printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n", |
620 | kfree(codec); | 538 | ret); |
621 | } | 539 | } |
540 | #endif | ||
622 | return ret; | 541 | return ret; |
623 | } | 542 | } |
543 | module_init(ak4535_modinit); | ||
624 | 544 | ||
625 | /* power down chip */ | 545 | static void __exit ak4535_exit(void) |
626 | static int ak4535_remove(struct platform_device *pdev) | ||
627 | { | 546 | { |
628 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
629 | struct snd_soc_codec *codec = socdev->card->codec; | ||
630 | |||
631 | if (codec->control_data) | ||
632 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
633 | |||
634 | snd_soc_free_pcms(socdev); | ||
635 | snd_soc_dapm_free(socdev); | ||
636 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 547 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
637 | if (codec->control_data) | ||
638 | i2c_unregister_device(codec->control_data); | ||
639 | i2c_del_driver(&ak4535_i2c_driver); | 548 | i2c_del_driver(&ak4535_i2c_driver); |
640 | #endif | 549 | #endif |
641 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
642 | kfree(codec); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | struct snd_soc_codec_device soc_codec_dev_ak4535 = { | ||
648 | .probe = ak4535_probe, | ||
649 | .remove = ak4535_remove, | ||
650 | .suspend = ak4535_suspend, | ||
651 | .resume = ak4535_resume, | ||
652 | }; | ||
653 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535); | ||
654 | |||
655 | static int __init ak4535_modinit(void) | ||
656 | { | ||
657 | return snd_soc_register_dai(&ak4535_dai); | ||
658 | } | ||
659 | module_init(ak4535_modinit); | ||
660 | |||
661 | static void __exit ak4535_exit(void) | ||
662 | { | ||
663 | snd_soc_unregister_dai(&ak4535_dai); | ||
664 | } | 550 | } |
665 | module_exit(ak4535_exit); | 551 | module_exit(ak4535_exit); |
666 | 552 | ||