diff options
Diffstat (limited to 'sound/soc/codecs/ak4642.c')
-rw-r--r-- | sound/soc/codecs/ak4642.c | 235 |
1 files changed, 82 insertions, 153 deletions
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 3d7dc55305ec..90c90b7f4a2e 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include <sound/initval.h> | 30 | #include <sound/initval.h> |
31 | #include <sound/tlv.h> | 31 | #include <sound/tlv.h> |
32 | 32 | ||
33 | #include "ak4642.h" | ||
34 | |||
35 | #define AK4642_VERSION "0.0.1" | 33 | #define AK4642_VERSION "0.0.1" |
36 | 34 | ||
37 | #define PW_MGMT1 0x00 | 35 | #define PW_MGMT1 0x00 |
@@ -74,6 +72,12 @@ | |||
74 | 72 | ||
75 | #define AK4642_CACHEREGNUM 0x25 | 73 | #define AK4642_CACHEREGNUM 0x25 |
76 | 74 | ||
75 | /* PW_MGMT1*/ | ||
76 | #define PMVCM (1 << 6) /* VCOM Power Management */ | ||
77 | #define PMMIN (1 << 5) /* MIN Input Power Management */ | ||
78 | #define PMDAC (1 << 2) /* DAC Power Management */ | ||
79 | #define PMADL (1 << 0) /* MIC Amp Lch and ADC Lch Power Management */ | ||
80 | |||
77 | /* PW_MGMT2 */ | 81 | /* PW_MGMT2 */ |
78 | #define HPMTN (1 << 6) | 82 | #define HPMTN (1 << 6) |
79 | #define PMHPL (1 << 5) | 83 | #define PMHPL (1 << 5) |
@@ -85,6 +89,23 @@ | |||
85 | #define PMHP_MASK (PMHPL | PMHPR) | 89 | #define PMHP_MASK (PMHPL | PMHPR) |
86 | #define PMHP PMHP_MASK | 90 | #define PMHP PMHP_MASK |
87 | 91 | ||
92 | /* PW_MGMT3 */ | ||
93 | #define PMADR (1 << 0) /* MIC L / ADC R Power Management */ | ||
94 | |||
95 | /* SG_SL1 */ | ||
96 | #define MINS (1 << 6) /* Switch from MIN to Speaker */ | ||
97 | #define DACL (1 << 4) /* Switch from DAC to Stereo or Receiver */ | ||
98 | #define PMMP (1 << 2) /* MPWR pin Power Management */ | ||
99 | #define MGAIN0 (1 << 0) /* MIC amp gain*/ | ||
100 | |||
101 | /* TIMER */ | ||
102 | #define ZTM(param) ((param & 0x3) << 4) /* ALC Zoro Crossing TimeOut */ | ||
103 | #define WTM(param) (((param & 0x4) << 4) | ((param & 0x3) << 2)) | ||
104 | |||
105 | /* ALC_CTL1 */ | ||
106 | #define ALC (1 << 5) /* ALC Enable */ | ||
107 | #define LMTH0 (1 << 0) /* ALC Limiter / Recovery Level */ | ||
108 | |||
88 | /* MD_CTL1 */ | 109 | /* MD_CTL1 */ |
89 | #define PLL3 (1 << 7) | 110 | #define PLL3 (1 << 7) |
90 | #define PLL2 (1 << 6) | 111 | #define PLL2 (1 << 6) |
@@ -102,7 +123,11 @@ | |||
102 | #define FS3 (1 << 5) | 123 | #define FS3 (1 << 5) |
103 | #define FS_MASK (FS0 | FS1 | FS2 | FS3) | 124 | #define FS_MASK (FS0 | FS1 | FS2 | FS3) |
104 | 125 | ||
105 | struct snd_soc_codec_device soc_codec_dev_ak4642; | 126 | /* MD_CTL3 */ |
127 | #define BST1 (1 << 3) | ||
128 | |||
129 | /* MD_CTL4 */ | ||
130 | #define DACH (1 << 0) | ||
106 | 131 | ||
107 | /* | 132 | /* |
108 | * Playback Volume (table 39) | 133 | * Playback Volume (table 39) |
@@ -123,11 +148,11 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { | |||
123 | 148 | ||
124 | /* codec private data */ | 149 | /* codec private data */ |
125 | struct ak4642_priv { | 150 | struct ak4642_priv { |
126 | struct snd_soc_codec codec; | 151 | unsigned int sysclk; |
152 | enum snd_soc_control_type control_type; | ||
153 | void *control_data; | ||
127 | }; | 154 | }; |
128 | 155 | ||
129 | static struct snd_soc_codec *ak4642_codec; | ||
130 | |||
131 | /* | 156 | /* |
132 | * ak4642 register cache | 157 | * ak4642 register cache |
133 | */ | 158 | */ |
@@ -219,11 +244,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, | |||
219 | * This operation came from example code of | 244 | * This operation came from example code of |
220 | * "ASAHI KASEI AK4642" (japanese) manual p97. | 245 | * "ASAHI KASEI AK4642" (japanese) manual p97. |
221 | */ | 246 | */ |
222 | ak4642_write(codec, 0x0f, 0x09); | 247 | snd_soc_update_bits(codec, MD_CTL4, DACH, DACH); |
223 | ak4642_write(codec, 0x0e, 0x19); | 248 | snd_soc_update_bits(codec, MD_CTL3, BST1, BST1); |
224 | ak4642_write(codec, 0x09, 0x91); | 249 | ak4642_write(codec, L_IVC, 0x91); /* volume */ |
225 | ak4642_write(codec, 0x0c, 0x91); | 250 | ak4642_write(codec, R_IVC, 0x91); /* volume */ |
226 | ak4642_write(codec, 0x00, 0x64); | 251 | snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC, |
252 | PMVCM | PMMIN | PMDAC); | ||
227 | snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP); | 253 | snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP); |
228 | snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN); | 254 | snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN); |
229 | } else { | 255 | } else { |
@@ -240,13 +266,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, | |||
240 | * This operation came from example code of | 266 | * This operation came from example code of |
241 | * "ASAHI KASEI AK4642" (japanese) manual p94. | 267 | * "ASAHI KASEI AK4642" (japanese) manual p94. |
242 | */ | 268 | */ |
243 | ak4642_write(codec, 0x02, 0x05); | 269 | ak4642_write(codec, SG_SL1, PMMP | MGAIN0); |
244 | ak4642_write(codec, 0x06, 0x3c); | 270 | ak4642_write(codec, TIMER, ZTM(0x3) | WTM(0x3)); |
245 | ak4642_write(codec, 0x08, 0xe1); | 271 | ak4642_write(codec, ALC_CTL1, ALC | LMTH0); |
246 | ak4642_write(codec, 0x0b, 0x00); | 272 | snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL, |
247 | ak4642_write(codec, 0x07, 0x21); | 273 | PMVCM | PMADL); |
248 | ak4642_write(codec, 0x00, 0x41); | 274 | snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR); |
249 | ak4642_write(codec, 0x10, 0x01); | ||
250 | } | 275 | } |
251 | 276 | ||
252 | return 0; | 277 | return 0; |
@@ -262,14 +287,14 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream, | |||
262 | /* stop headphone output */ | 287 | /* stop headphone output */ |
263 | snd_soc_update_bits(codec, PW_MGMT2, HPMTN, 0); | 288 | snd_soc_update_bits(codec, PW_MGMT2, HPMTN, 0); |
264 | snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0); | 289 | snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0); |
265 | ak4642_write(codec, 0x00, 0x40); | 290 | snd_soc_update_bits(codec, PW_MGMT1, PMMIN | PMDAC, 0); |
266 | ak4642_write(codec, 0x0e, 0x11); | 291 | snd_soc_update_bits(codec, MD_CTL3, BST1, 0); |
267 | ak4642_write(codec, 0x0f, 0x08); | 292 | snd_soc_update_bits(codec, MD_CTL4, DACH, 0); |
268 | } else { | 293 | } else { |
269 | /* stop stereo input */ | 294 | /* stop stereo input */ |
270 | ak4642_write(codec, 0x00, 0x40); | 295 | snd_soc_update_bits(codec, PW_MGMT1, PMADL, 0); |
271 | ak4642_write(codec, 0x10, 0x00); | 296 | snd_soc_update_bits(codec, PW_MGMT3, PMADR, 0); |
272 | ak4642_write(codec, 0x07, 0x01); | 297 | snd_soc_update_bits(codec, ALC_CTL1, ALC, 0); |
273 | } | 298 | } |
274 | } | 299 | } |
275 | 300 | ||
@@ -393,8 +418,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = { | |||
393 | .hw_params = ak4642_dai_hw_params, | 418 | .hw_params = ak4642_dai_hw_params, |
394 | }; | 419 | }; |
395 | 420 | ||
396 | struct snd_soc_dai ak4642_dai = { | 421 | static struct snd_soc_dai_driver ak4642_dai = { |
397 | .name = "AK4642", | 422 | .name = "ak4642-hifi", |
398 | .playback = { | 423 | .playback = { |
399 | .stream_name = "Playback", | 424 | .stream_name = "Playback", |
400 | .channels_min = 1, | 425 | .channels_min = 1, |
@@ -410,112 +435,65 @@ struct snd_soc_dai ak4642_dai = { | |||
410 | .ops = &ak4642_dai_ops, | 435 | .ops = &ak4642_dai_ops, |
411 | .symmetric_rates = 1, | 436 | .symmetric_rates = 1, |
412 | }; | 437 | }; |
413 | EXPORT_SYMBOL_GPL(ak4642_dai); | ||
414 | 438 | ||
415 | static int ak4642_resume(struct platform_device *pdev) | 439 | static int ak4642_resume(struct snd_soc_codec *codec) |
416 | { | 440 | { |
417 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
418 | struct snd_soc_codec *codec = socdev->card->codec; | ||
419 | |||
420 | ak4642_sync(codec); | 441 | ak4642_sync(codec); |
421 | return 0; | 442 | return 0; |
422 | } | 443 | } |
423 | 444 | ||
424 | /* | 445 | |
425 | * initialise the AK4642 driver | 446 | static int ak4642_probe(struct snd_soc_codec *codec) |
426 | * register the mixer and dsp interfaces with the kernel | ||
427 | */ | ||
428 | static int ak4642_init(struct ak4642_priv *ak4642) | ||
429 | { | 447 | { |
430 | struct snd_soc_codec *codec = &ak4642->codec; | 448 | struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec); |
431 | int ret = 0; | ||
432 | 449 | ||
433 | if (ak4642_codec) { | 450 | dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION); |
434 | dev_err(codec->dev, "Another ak4642 is registered\n"); | ||
435 | return -EINVAL; | ||
436 | } | ||
437 | 451 | ||
438 | mutex_init(&codec->mutex); | ||
439 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
440 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
441 | |||
442 | snd_soc_codec_set_drvdata(codec, ak4642); | ||
443 | codec->name = "AK4642"; | ||
444 | codec->owner = THIS_MODULE; | ||
445 | codec->read = ak4642_read_reg_cache; | ||
446 | codec->write = ak4642_write; | ||
447 | codec->dai = &ak4642_dai; | ||
448 | codec->num_dai = 1; | ||
449 | codec->hw_write = (hw_write_t)i2c_master_send; | 452 | codec->hw_write = (hw_write_t)i2c_master_send; |
450 | codec->reg_cache_size = ARRAY_SIZE(ak4642_reg); | 453 | codec->control_data = ak4642->control_data; |
451 | codec->reg_cache = kmemdup(ak4642_reg, | ||
452 | sizeof(ak4642_reg), GFP_KERNEL); | ||
453 | 454 | ||
454 | if (!codec->reg_cache) | 455 | snd_soc_add_controls(codec, ak4642_snd_controls, |
455 | return -ENOMEM; | 456 | ARRAY_SIZE(ak4642_snd_controls)); |
456 | |||
457 | ak4642_dai.dev = codec->dev; | ||
458 | ak4642_codec = codec; | ||
459 | |||
460 | ret = snd_soc_register_codec(codec); | ||
461 | if (ret) { | ||
462 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
463 | goto reg_cache_err; | ||
464 | } | ||
465 | |||
466 | ret = snd_soc_register_dai(&ak4642_dai); | ||
467 | if (ret) { | ||
468 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
469 | snd_soc_unregister_codec(codec); | ||
470 | goto reg_cache_err; | ||
471 | } | ||
472 | |||
473 | return ret; | ||
474 | |||
475 | reg_cache_err: | ||
476 | kfree(codec->reg_cache); | ||
477 | codec->reg_cache = NULL; | ||
478 | 457 | ||
479 | return ret; | 458 | return 0; |
480 | } | 459 | } |
481 | 460 | ||
461 | static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { | ||
462 | .probe = ak4642_probe, | ||
463 | .resume = ak4642_resume, | ||
464 | .read = ak4642_read_reg_cache, | ||
465 | .write = ak4642_write, | ||
466 | .reg_cache_size = ARRAY_SIZE(ak4642_reg), | ||
467 | .reg_word_size = sizeof(u8), | ||
468 | .reg_cache_default = ak4642_reg, | ||
469 | }; | ||
470 | |||
482 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 471 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
483 | static int ak4642_i2c_probe(struct i2c_client *i2c, | 472 | static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, |
484 | const struct i2c_device_id *id) | 473 | const struct i2c_device_id *id) |
485 | { | 474 | { |
486 | struct ak4642_priv *ak4642; | 475 | struct ak4642_priv *ak4642; |
487 | struct snd_soc_codec *codec; | ||
488 | int ret; | 476 | int ret; |
489 | 477 | ||
490 | ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); | 478 | ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); |
491 | if (!ak4642) | 479 | if (!ak4642) |
492 | return -ENOMEM; | 480 | return -ENOMEM; |
493 | 481 | ||
494 | codec = &ak4642->codec; | ||
495 | codec->dev = &i2c->dev; | ||
496 | |||
497 | i2c_set_clientdata(i2c, ak4642); | 482 | i2c_set_clientdata(i2c, ak4642); |
498 | codec->control_data = i2c; | 483 | ak4642->control_data = i2c; |
484 | ak4642->control_type = SND_SOC_I2C; | ||
499 | 485 | ||
500 | ret = ak4642_init(ak4642); | 486 | ret = snd_soc_register_codec(&i2c->dev, |
501 | if (ret < 0) { | 487 | &soc_codec_dev_ak4642, &ak4642_dai, 1); |
502 | printk(KERN_ERR "failed to initialise AK4642\n"); | 488 | if (ret < 0) |
503 | kfree(ak4642); | 489 | kfree(ak4642); |
504 | } | ||
505 | |||
506 | return ret; | 490 | return ret; |
507 | } | 491 | } |
508 | 492 | ||
509 | static int ak4642_i2c_remove(struct i2c_client *client) | 493 | static __devexit int ak4642_i2c_remove(struct i2c_client *client) |
510 | { | 494 | { |
511 | struct ak4642_priv *ak4642 = i2c_get_clientdata(client); | 495 | snd_soc_unregister_codec(&client->dev); |
512 | 496 | kfree(i2c_get_clientdata(client)); | |
513 | snd_soc_unregister_dai(&ak4642_dai); | ||
514 | snd_soc_unregister_codec(&ak4642->codec); | ||
515 | kfree(ak4642->codec.reg_cache); | ||
516 | kfree(ak4642); | ||
517 | ak4642_codec = NULL; | ||
518 | |||
519 | return 0; | 497 | return 0; |
520 | } | 498 | } |
521 | 499 | ||
@@ -528,64 +506,15 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); | |||
528 | 506 | ||
529 | static struct i2c_driver ak4642_i2c_driver = { | 507 | static struct i2c_driver ak4642_i2c_driver = { |
530 | .driver = { | 508 | .driver = { |
531 | .name = "AK4642 I2C Codec", | 509 | .name = "ak4642-codec", |
532 | .owner = THIS_MODULE, | 510 | .owner = THIS_MODULE, |
533 | }, | 511 | }, |
534 | .probe = ak4642_i2c_probe, | 512 | .probe = ak4642_i2c_probe, |
535 | .remove = ak4642_i2c_remove, | 513 | .remove = __devexit_p(ak4642_i2c_remove), |
536 | .id_table = ak4642_i2c_id, | 514 | .id_table = ak4642_i2c_id, |
537 | }; | 515 | }; |
538 | |||
539 | #endif | 516 | #endif |
540 | 517 | ||
541 | static int ak4642_probe(struct platform_device *pdev) | ||
542 | { | ||
543 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
544 | int ret; | ||
545 | |||
546 | if (!ak4642_codec) { | ||
547 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
548 | return -ENODEV; | ||
549 | } | ||
550 | |||
551 | socdev->card->codec = ak4642_codec; | ||
552 | |||
553 | /* register pcms */ | ||
554 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
555 | if (ret < 0) { | ||
556 | printk(KERN_ERR "ak4642: failed to create pcms\n"); | ||
557 | goto pcm_err; | ||
558 | } | ||
559 | |||
560 | snd_soc_add_controls(ak4642_codec, ak4642_snd_controls, | ||
561 | ARRAY_SIZE(ak4642_snd_controls)); | ||
562 | |||
563 | dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); | ||
564 | return ret; | ||
565 | |||
566 | pcm_err: | ||
567 | return ret; | ||
568 | |||
569 | } | ||
570 | |||
571 | /* power down chip */ | ||
572 | static int ak4642_remove(struct platform_device *pdev) | ||
573 | { | ||
574 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
575 | |||
576 | snd_soc_free_pcms(socdev); | ||
577 | snd_soc_dapm_free(socdev); | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | struct snd_soc_codec_device soc_codec_dev_ak4642 = { | ||
583 | .probe = ak4642_probe, | ||
584 | .remove = ak4642_remove, | ||
585 | .resume = ak4642_resume, | ||
586 | }; | ||
587 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642); | ||
588 | |||
589 | static int __init ak4642_modinit(void) | 518 | static int __init ak4642_modinit(void) |
590 | { | 519 | { |
591 | int ret = 0; | 520 | int ret = 0; |