Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Side by Side Diff: sound/soc/codecs/wm9090.c

Issue 6577007: CHROMIUM: ASoC: Import entire upstream ASoC tree (Closed)
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sound/soc/codecs/wm9081.c ('k') | sound/soc/codecs/wm9705.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * ALSA SoC WM9090 driver 2 * ALSA SoC WM9090 driver
3 * 3 *
4 * Copyright 2009, 2010 Wolfson Microelectronics 4 * Copyright 2009, 2010 Wolfson Microelectronics
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation. 10 * version 2 as published by the Free Software Foundation.
(...skipping 10 matching lines...) Expand all
21 */ 21 */
22 22
23 #include <linux/module.h> 23 #include <linux/module.h>
24 #include <linux/errno.h> 24 #include <linux/errno.h>
25 #include <linux/device.h> 25 #include <linux/device.h>
26 #include <linux/i2c.h> 26 #include <linux/i2c.h>
27 #include <linux/delay.h> 27 #include <linux/delay.h>
28 #include <linux/slab.h> 28 #include <linux/slab.h>
29 #include <sound/initval.h> 29 #include <sound/initval.h>
30 #include <sound/soc.h> 30 #include <sound/soc.h>
31 #include <sound/soc-dapm.h>
32 #include <sound/tlv.h> 31 #include <sound/tlv.h>
33 #include <sound/wm9090.h> 32 #include <sound/wm9090.h>
34 33
35 #include "wm9090.h" 34 #include "wm9090.h"
36 35
37 static const u16 wm9090_reg_defaults[] = { 36 static const u16 wm9090_reg_defaults[] = {
38 0x9093, /* R0 - Software Reset */ 37 0x9093, /* R0 - Software Reset */
39 0x0006, /* R1 - Power Management (1) */ 38 0x0006, /* R1 - Power Management (1) */
40 0x6000, /* R2 - Power Management (2) */ 39 0x6000, /* R2 - Power Management (2) */
41 0x0000, /* R3 - Power Management (3) */ 40 0x0000, /* R3 - Power Management (3) */
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 0x0200, /* R100 - AGC Control 2 */ 137 0x0200, /* R100 - AGC Control 2 */
139 }; 138 };
140 139
141 /* This struct is used to save the context */ 140 /* This struct is used to save the context */
142 struct wm9090_priv { 141 struct wm9090_priv {
143 struct mutex mutex; 142 struct mutex mutex;
144 struct wm9090_platform_data pdata; 143 struct wm9090_platform_data pdata;
145 void *control_data; 144 void *control_data;
146 }; 145 };
147 146
148 static int wm9090_volatile(unsigned int reg) 147 static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
149 { 148 {
150 switch (reg) { 149 switch (reg) {
151 case WM9090_SOFTWARE_RESET: 150 case WM9090_SOFTWARE_RESET:
152 case WM9090_DC_SERVO_0: 151 case WM9090_DC_SERVO_0:
153 case WM9090_DC_SERVO_READBACK_0: 152 case WM9090_DC_SERVO_READBACK_0:
154 case WM9090_DC_SERVO_READBACK_1: 153 case WM9090_DC_SERVO_READBACK_1:
155 case WM9090_DC_SERVO_READBACK_2: 154 case WM9090_DC_SERVO_READBACK_2:
156 return 1; 155 return 1;
157 156
158 default: 157 default:
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 { "MIXOUTR", "IN2B Switch", "IN2B PGA" }, 434 { "MIXOUTR", "IN2B Switch", "IN2B PGA" },
436 }; 435 };
437 436
438 static const struct snd_soc_dapm_route audio_map_in2_diff[] = { 437 static const struct snd_soc_dapm_route audio_map_in2_diff[] = {
439 { "IN2A PGA", NULL, "IN2-" }, 438 { "IN2A PGA", NULL, "IN2-" },
440 }; 439 };
441 440
442 static int wm9090_add_controls(struct snd_soc_codec *codec) 441 static int wm9090_add_controls(struct snd_soc_codec *codec)
443 { 442 {
444 struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); 443 struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
444 struct snd_soc_dapm_context *dapm = &codec->dapm;
445 int i; 445 int i;
446 446
447 » snd_soc_dapm_new_controls(codec, wm9090_dapm_widgets, 447 » snd_soc_dapm_new_controls(dapm, wm9090_dapm_widgets,
448 ARRAY_SIZE(wm9090_dapm_widgets)); 448 ARRAY_SIZE(wm9090_dapm_widgets));
449 449
450 » snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 450 » snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
451 451
452 snd_soc_add_controls(codec, wm9090_controls, 452 snd_soc_add_controls(codec, wm9090_controls,
453 ARRAY_SIZE(wm9090_controls)); 453 ARRAY_SIZE(wm9090_controls));
454 454
455 if (wm9090->pdata.lin1_diff) { 455 if (wm9090->pdata.lin1_diff) {
456 » » snd_soc_dapm_add_routes(codec, audio_map_in1_diff, 456 » » snd_soc_dapm_add_routes(dapm, audio_map_in1_diff,
457 ARRAY_SIZE(audio_map_in1_diff)); 457 ARRAY_SIZE(audio_map_in1_diff));
458 } else { 458 } else {
459 » » snd_soc_dapm_add_routes(codec, audio_map_in1_se, 459 » » snd_soc_dapm_add_routes(dapm, audio_map_in1_se,
460 ARRAY_SIZE(audio_map_in1_se)); 460 ARRAY_SIZE(audio_map_in1_se));
461 snd_soc_add_controls(codec, wm9090_in1_se_controls, 461 snd_soc_add_controls(codec, wm9090_in1_se_controls,
462 ARRAY_SIZE(wm9090_in1_se_controls)); 462 ARRAY_SIZE(wm9090_in1_se_controls));
463 } 463 }
464 464
465 if (wm9090->pdata.lin2_diff) { 465 if (wm9090->pdata.lin2_diff) {
466 » » snd_soc_dapm_add_routes(codec, audio_map_in2_diff, 466 » » snd_soc_dapm_add_routes(dapm, audio_map_in2_diff,
467 ARRAY_SIZE(audio_map_in2_diff)); 467 ARRAY_SIZE(audio_map_in2_diff));
468 } else { 468 } else {
469 » » snd_soc_dapm_add_routes(codec, audio_map_in2_se, 469 » » snd_soc_dapm_add_routes(dapm, audio_map_in2_se,
470 ARRAY_SIZE(audio_map_in2_se)); 470 ARRAY_SIZE(audio_map_in2_se));
471 snd_soc_add_controls(codec, wm9090_in2_se_controls, 471 snd_soc_add_controls(codec, wm9090_in2_se_controls,
472 ARRAY_SIZE(wm9090_in2_se_controls)); 472 ARRAY_SIZE(wm9090_in2_se_controls));
473 } 473 }
474 474
475 if (wm9090->pdata.agc_ena) { 475 if (wm9090->pdata.agc_ena) {
476 for (i = 0; i < ARRAY_SIZE(wm9090->pdata.agc); i++) 476 for (i = 0; i < ARRAY_SIZE(wm9090->pdata.agc); i++)
477 snd_soc_write(codec, WM9090_AGC_CONTROL_0 + i, 477 snd_soc_write(codec, WM9090_AGC_CONTROL_0 + i,
478 wm9090->pdata.agc[i]); 478 wm9090->pdata.agc[i]);
479 snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_3, 479 snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_3,
(...skipping 26 matching lines...) Expand all
506 WM9090_VMID_ENA); 506 WM9090_VMID_ENA);
507 snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_1, 507 snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_1,
508 WM9090_BIAS_ENA | 508 WM9090_BIAS_ENA |
509 WM9090_VMID_RES_MASK, 509 WM9090_VMID_RES_MASK,
510 WM9090_BIAS_ENA | 510 WM9090_BIAS_ENA |
511 1 << WM9090_VMID_RES_SHIFT); 511 1 << WM9090_VMID_RES_SHIFT);
512 msleep(1); /* Probably an overestimate */ 512 msleep(1); /* Probably an overestimate */
513 break; 513 break;
514 514
515 case SND_SOC_BIAS_STANDBY: 515 case SND_SOC_BIAS_STANDBY:
516 » » if (codec->bias_level == SND_SOC_BIAS_OFF) { 516 » » if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
517 /* Restore the register cache */ 517 /* Restore the register cache */
518 for (i = 1; i < codec->driver->reg_cache_size; i++) { 518 for (i = 1; i < codec->driver->reg_cache_size; i++) {
519 if (reg_cache[i] == wm9090_reg_defaults[i]) 519 if (reg_cache[i] == wm9090_reg_defaults[i])
520 continue; 520 continue;
521 » » » » if (wm9090_volatile(i)) 521 » » » » if (wm9090_volatile(codec, i))
522 continue; 522 continue;
523 523
524 ret = snd_soc_write(codec, i, reg_cache[i]); 524 ret = snd_soc_write(codec, i, reg_cache[i]);
525 if (ret != 0) 525 if (ret != 0)
526 dev_warn(codec->dev, 526 dev_warn(codec->dev,
527 "Failed to restore register %d: %d\n", 527 "Failed to restore register %d: %d\n",
528 i, ret); 528 i, ret);
529 } 529 }
530 } 530 }
531 531
532 /* We keep VMID off during standby since the combination of 532 /* We keep VMID off during standby since the combination of
533 * ground referenced outputs and class D speaker mean that 533 * ground referenced outputs and class D speaker mean that
534 * latency is not an issue. 534 * latency is not an issue.
535 */ 535 */
536 snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_1, 536 snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_1,
537 WM9090_BIAS_ENA | WM9090_VMID_RES_MASK, 0); 537 WM9090_BIAS_ENA | WM9090_VMID_RES_MASK, 0);
538 snd_soc_update_bits(codec, WM9090_ANTIPOP2, 538 snd_soc_update_bits(codec, WM9090_ANTIPOP2,
539 WM9090_VMID_ENA, 0); 539 WM9090_VMID_ENA, 0);
540 break; 540 break;
541 541
542 case SND_SOC_BIAS_OFF: 542 case SND_SOC_BIAS_OFF:
543 break; 543 break;
544 } 544 }
545 545
546 » codec->bias_level = level; 546 » codec->dapm.bias_level = level;
547 547
548 return 0; 548 return 0;
549 } 549 }
550 550
551 static int wm9090_probe(struct snd_soc_codec *codec) 551 static int wm9090_probe(struct snd_soc_codec *codec)
552 { 552 {
553 struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); 553 struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
554 u16 *reg_cache = codec->reg_cache;
555 int ret; 554 int ret;
556 555
557 codec->control_data = wm9090->control_data; 556 codec->control_data = wm9090->control_data;
558 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); 557 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
559 if (ret != 0) { 558 if (ret != 0) {
560 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 559 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
561 return ret; 560 return ret;
562 } 561 }
563 562
564 ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET); 563 ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
565 if (ret < 0) 564 if (ret < 0)
566 return ret; 565 return ret;
567 if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) { 566 if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
568 dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret); 567 dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret);
569 return -EINVAL; 568 return -EINVAL;
570 } 569 }
571 570
572 ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0); 571 ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
573 if (ret < 0) 572 if (ret < 0)
574 return ret; 573 return ret;
575 574
576 /* Configure some defaults; they will be written out when we 575 /* Configure some defaults; they will be written out when we
577 * bring the bias up. 576 * bring the bias up.
578 */ 577 */
579 » reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU 578 » snd_soc_update_bits(codec, WM9090_IN1_LINE_INPUT_A_VOLUME,
580 » » | WM9090_IN1A_ZC; 579 » » » WM9090_IN1_VU | WM9090_IN1A_ZC,
581 » reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU 580 » » » WM9090_IN1_VU | WM9090_IN1A_ZC);
582 » » | WM9090_IN1B_ZC; 581 » snd_soc_update_bits(codec, WM9090_IN1_LINE_INPUT_B_VOLUME,
583 » reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU 582 » » » WM9090_IN1_VU | WM9090_IN1B_ZC,
584 » » | WM9090_IN2A_ZC; 583 » » » WM9090_IN1_VU | WM9090_IN1B_ZC);
585 » reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU 584 » snd_soc_update_bits(codec, WM9090_IN2_LINE_INPUT_A_VOLUME,
586 » » | WM9090_IN2B_ZC; 585 » » » WM9090_IN2_VU | WM9090_IN2A_ZC,
587 » reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= 586 » » » WM9090_IN2_VU | WM9090_IN2A_ZC);
588 » » WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; 587 » snd_soc_update_bits(codec, WM9090_IN2_LINE_INPUT_B_VOLUME,
589 » reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= 588 » » » WM9090_IN2_VU | WM9090_IN2B_ZC,
590 » » WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; 589 » » » WM9090_IN2_VU | WM9090_IN2B_ZC);
591 » reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= 590 » snd_soc_update_bits(codec, WM9090_SPEAKER_VOLUME_LEFT,
592 » » WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; 591 » » » WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC,
592 » » » WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC);
593 » snd_soc_update_bits(codec, WM9090_LEFT_OUTPUT_VOLUME,
594 » » » WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC,
595 » » » WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC);
596 » snd_soc_update_bits(codec, WM9090_RIGHT_OUTPUT_VOLUME,
597 » » » WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC,
598 » » » WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC);
593 599
594 » reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; 600 » snd_soc_update_bits(codec, WM9090_CLOCKING_1,
601 » » » WM9090_TOCLK_ENA, WM9090_TOCLK_ENA);
595 602
596 wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 603 wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
597 604
598 wm9090_add_controls(codec); 605 wm9090_add_controls(codec);
599 606
600 return 0; 607 return 0;
601 } 608 }
602 609
603 #ifdef CONFIG_PM 610 #ifdef CONFIG_PM
604 static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state) 611 static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state)
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 706
700 static void __exit wm9090_exit(void) 707 static void __exit wm9090_exit(void)
701 { 708 {
702 i2c_del_driver(&wm9090_i2c_driver); 709 i2c_del_driver(&wm9090_i2c_driver);
703 } 710 }
704 module_exit(wm9090_exit); 711 module_exit(wm9090_exit);
705 712
706 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 713 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
707 MODULE_DESCRIPTION("WM9090 ASoC driver"); 714 MODULE_DESCRIPTION("WM9090 ASoC driver");
708 MODULE_LICENSE("GPL"); 715 MODULE_LICENSE("GPL");
OLDNEW
« no previous file with comments | « sound/soc/codecs/wm9081.c ('k') | sound/soc/codecs/wm9705.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698