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

Side by Side Diff: sound/soc/codecs/wm8580.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/wm8523.c ('k') | sound/soc/codecs/wm8711.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 * wm8580.c -- WM8580 ALSA Soc Audio driver 2 * wm8580.c -- WM8580 ALSA Soc Audio driver
3 * 3 *
4 * Copyright 2008, 2009 Wolfson Microelectronics PLC. 4 * Copyright 2008, 2009 Wolfson Microelectronics PLC.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your 8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. 9 * option) any later version.
10 * 10 *
(...skipping 13 matching lines...) Expand all
24 #include <linux/pm.h> 24 #include <linux/pm.h>
25 #include <linux/i2c.h> 25 #include <linux/i2c.h>
26 #include <linux/platform_device.h> 26 #include <linux/platform_device.h>
27 #include <linux/regulator/consumer.h> 27 #include <linux/regulator/consumer.h>
28 #include <linux/slab.h> 28 #include <linux/slab.h>
29 29
30 #include <sound/core.h> 30 #include <sound/core.h>
31 #include <sound/pcm.h> 31 #include <sound/pcm.h>
32 #include <sound/pcm_params.h> 32 #include <sound/pcm_params.h>
33 #include <sound/soc.h> 33 #include <sound/soc.h>
34 #include <sound/soc-dapm.h>
35 #include <sound/tlv.h> 34 #include <sound/tlv.h>
36 #include <sound/initval.h> 35 #include <sound/initval.h>
37 #include <asm/div64.h> 36 #include <asm/div64.h>
38 37
39 #include "wm8580.h" 38 #include "wm8580.h"
40 39
41 /* WM8580 register space */ 40 /* WM8580 register space */
42 #define WM8580_PLLA1 0x00 41 #define WM8580_PLLA1 0x00
43 #define WM8580_PLLA2 0x01 42 #define WM8580_PLLA2 0x01
44 #define WM8580_PLLA3 0x02 43 #define WM8580_PLLA3 0x02
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { 183 static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
185 "AVDD", 184 "AVDD",
186 "DVDD", 185 "DVDD",
187 "PVDD", 186 "PVDD",
188 }; 187 };
189 188
190 /* codec private data */ 189 /* codec private data */
191 struct wm8580_priv { 190 struct wm8580_priv {
192 enum snd_soc_control_type control_type; 191 enum snd_soc_control_type control_type;
193 struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; 192 struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
194 u16 reg_cache[WM8580_MAX_REGISTER + 1];
195 struct pll_state a; 193 struct pll_state a;
196 struct pll_state b; 194 struct pll_state b;
197 int sysclk[2]; 195 int sysclk[2];
198 }; 196 };
199 197
200 static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); 198 static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
201 199
202 static int wm8580_out_vu(struct snd_kcontrol *kcontrol, 200 static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
203 struct snd_ctl_elem_value *ucontrol) 201 struct snd_ctl_elem_value *ucontrol)
204 { 202 {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 293
296 { "VOUT3L", NULL, "DAC3" }, 294 { "VOUT3L", NULL, "DAC3" },
297 { "VOUT3R", NULL, "DAC3" }, 295 { "VOUT3R", NULL, "DAC3" },
298 296
299 { "ADC", NULL, "AINL" }, 297 { "ADC", NULL, "AINL" },
300 { "ADC", NULL, "AINR" }, 298 { "ADC", NULL, "AINR" },
301 }; 299 };
302 300
303 static int wm8580_add_widgets(struct snd_soc_codec *codec) 301 static int wm8580_add_widgets(struct snd_soc_codec *codec)
304 { 302 {
305 » snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets, 303 » struct snd_soc_dapm_context *dapm = &codec->dapm;
304
305 » snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets,
306 ARRAY_SIZE(wm8580_dapm_widgets)); 306 ARRAY_SIZE(wm8580_dapm_widgets));
307 307 » snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
308 » snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
309 308
310 return 0; 309 return 0;
311 } 310 }
312 311
313 /* PLL divisors */ 312 /* PLL divisors */
314 struct _pll_div { 313 struct _pll_div {
315 u32 prescale:1; 314 u32 prescale:1;
316 u32 postscale:1; 315 u32 postscale:1;
317 u32 freqmode:2; 316 u32 freqmode:2;
318 u32 n:4; 317 u32 n:4;
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 break; 499 break;
501 case SNDRV_PCM_FORMAT_S32_LE: 500 case SNDRV_PCM_FORMAT_S32_LE:
502 paifa |= 0x0; 501 paifa |= 0x0;
503 paifb |= WM8580_AIF_LENGTH_32; 502 paifb |= WM8580_AIF_LENGTH_32;
504 break; 503 break;
505 default: 504 default:
506 return -EINVAL; 505 return -EINVAL;
507 } 506 }
508 507
509 /* Look up the SYSCLK ratio; accept only exact matches */ 508 /* Look up the SYSCLK ratio; accept only exact matches */
510 » ratio = wm8580->sysclk[dai->id] / params_rate(params); 509 » ratio = wm8580->sysclk[dai->driver->id] / params_rate(params);
511 for (i = 0; i < ARRAY_SIZE(wm8580_sysclk_ratios); i++) 510 for (i = 0; i < ARRAY_SIZE(wm8580_sysclk_ratios); i++)
512 if (ratio == wm8580_sysclk_ratios[i]) 511 if (ratio == wm8580_sysclk_ratios[i])
513 break; 512 break;
514 if (i == ARRAY_SIZE(wm8580_sysclk_ratios)) { 513 if (i == ARRAY_SIZE(wm8580_sysclk_ratios)) {
515 dev_err(codec->dev, "Invalid clock ratio %d/%d\n", 514 dev_err(codec->dev, "Invalid clock ratio %d/%d\n",
516 » » » wm8580->sysclk[dai->id], params_rate(params)); 515 » » » wm8580->sysclk[dai->driver->id], params_rate(params));
517 return -EINVAL; 516 return -EINVAL;
518 } 517 }
519 paifa |= i; 518 paifa |= i;
520 dev_dbg(codec->dev, "Running at %dfs with %dHz clock\n", 519 dev_dbg(codec->dev, "Running at %dfs with %dHz clock\n",
521 wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]); 520 wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]);
522 521
523 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 522 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
524 switch (ratio) { 523 switch (ratio) {
525 case 128: 524 case 128:
526 case 192: 525 case 192:
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 sel_shift = 2; 708 sel_shift = 2;
710 break; 709 break;
711 710
712 default: 711 default:
713 BUG_ON("Unknown DAI driver ID\n"); 712 BUG_ON("Unknown DAI driver ID\n");
714 return -EINVAL; 713 return -EINVAL;
715 } 714 }
716 715
717 switch (clk_id) { 716 switch (clk_id) {
718 case WM8580_CLKSRC_ADCMCLK: 717 case WM8580_CLKSRC_ADCMCLK:
719 » » if (dai->id != WM8580_DAI_PAIFTX) 718 » » if (dai->driver->id != WM8580_DAI_PAIFTX)
720 return -EINVAL; 719 return -EINVAL;
721 sel = 0 << sel_shift; 720 sel = 0 << sel_shift;
722 break; 721 break;
723 case WM8580_CLKSRC_PLLA: 722 case WM8580_CLKSRC_PLLA:
724 sel = 1 << sel_shift; 723 sel = 1 << sel_shift;
725 break; 724 break;
726 case WM8580_CLKSRC_PLLB: 725 case WM8580_CLKSRC_PLLB:
727 sel = 2 << sel_shift; 726 sel = 2 << sel_shift;
728 break; 727 break;
729 case WM8580_CLKSRC_MCLK: 728 case WM8580_CLKSRC_MCLK:
730 sel = 3 << sel_shift; 729 sel = 3 << sel_shift;
731 break; 730 break;
732 default: 731 default:
733 dev_err(codec->dev, "Unknown clock %d\n", clk_id); 732 dev_err(codec->dev, "Unknown clock %d\n", clk_id);
734 return -EINVAL; 733 return -EINVAL;
735 } 734 }
736 735
737 /* We really should validate PLL settings but not yet */ 736 /* We really should validate PLL settings but not yet */
738 » wm8580->sysclk[dai->id] = freq; 737 » wm8580->sysclk[dai->driver->id] = freq;
739 738
740 return snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel); 739 return snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel);
741 } 740 }
742 741
743 static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) 742 static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
744 { 743 {
745 struct snd_soc_codec *codec = codec_dai->codec; 744 struct snd_soc_codec *codec = codec_dai->codec;
746 unsigned int reg; 745 unsigned int reg;
747 746
748 reg = snd_soc_read(codec, WM8580_DAC_CONTROL5); 747 reg = snd_soc_read(codec, WM8580_DAC_CONTROL5);
(...skipping 11 matching lines...) Expand all
760 static int wm8580_set_bias_level(struct snd_soc_codec *codec, 759 static int wm8580_set_bias_level(struct snd_soc_codec *codec,
761 enum snd_soc_bias_level level) 760 enum snd_soc_bias_level level)
762 { 761 {
763 u16 reg; 762 u16 reg;
764 switch (level) { 763 switch (level) {
765 case SND_SOC_BIAS_ON: 764 case SND_SOC_BIAS_ON:
766 case SND_SOC_BIAS_PREPARE: 765 case SND_SOC_BIAS_PREPARE:
767 break; 766 break;
768 767
769 case SND_SOC_BIAS_STANDBY: 768 case SND_SOC_BIAS_STANDBY:
770 » » if (codec->bias_level == SND_SOC_BIAS_OFF) { 769 » » if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
771 /* Power up and get individual control of the DACs */ 770 /* Power up and get individual control of the DACs */
772 reg = snd_soc_read(codec, WM8580_PWRDN1); 771 reg = snd_soc_read(codec, WM8580_PWRDN1);
773 reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); 772 reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
774 snd_soc_write(codec, WM8580_PWRDN1, reg); 773 snd_soc_write(codec, WM8580_PWRDN1, reg);
775 774
776 /* Make VMID high impedence */ 775 /* Make VMID high impedence */
777 reg = snd_soc_read(codec, WM8580_ADC_CONTROL1); 776 reg = snd_soc_read(codec, WM8580_ADC_CONTROL1);
778 reg &= ~0x100; 777 reg &= ~0x100;
779 snd_soc_write(codec, WM8580_ADC_CONTROL1, reg); 778 snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
780 } 779 }
781 break; 780 break;
782 781
783 case SND_SOC_BIAS_OFF: 782 case SND_SOC_BIAS_OFF:
784 reg = snd_soc_read(codec, WM8580_PWRDN1); 783 reg = snd_soc_read(codec, WM8580_PWRDN1);
785 snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); 784 snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
786 break; 785 break;
787 } 786 }
788 » codec->bias_level = level; 787 » codec->dapm.bias_level = level;
789 return 0; 788 return 0;
790 } 789 }
791 790
792 #define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 791 #define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
793 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 792 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
794 793
795 static struct snd_soc_dai_ops wm8580_dai_ops_playback = { 794 static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
796 .set_sysclk = wm8580_set_sysclk, 795 .set_sysclk = wm8580_set_sysclk,
797 .hw_params = wm8580_paif_hw_params, 796 .hw_params = wm8580_paif_hw_params,
798 .set_fmt = wm8580_set_paif_dai_fmt, 797 .set_fmt = wm8580_set_paif_dai_fmt,
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 897
899 return 0; 898 return 0;
900 } 899 }
901 900
902 static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { 901 static struct snd_soc_codec_driver soc_codec_dev_wm8580 = {
903 .probe = wm8580_probe, 902 .probe = wm8580_probe,
904 .remove = wm8580_remove, 903 .remove = wm8580_remove,
905 .set_bias_level = wm8580_set_bias_level, 904 .set_bias_level = wm8580_set_bias_level,
906 .reg_cache_size = ARRAY_SIZE(wm8580_reg), 905 .reg_cache_size = ARRAY_SIZE(wm8580_reg),
907 .reg_word_size = sizeof(u16), 906 .reg_word_size = sizeof(u16),
908 » .reg_cache_default = &wm8580_reg, 907 » .reg_cache_default = wm8580_reg,
909 }; 908 };
910 909
911 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 910 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
912 static int wm8580_i2c_probe(struct i2c_client *i2c, 911 static int wm8580_i2c_probe(struct i2c_client *i2c,
913 const struct i2c_device_id *id) 912 const struct i2c_device_id *id)
914 { 913 {
915 struct wm8580_priv *wm8580; 914 struct wm8580_priv *wm8580;
916 int ret; 915 int ret;
917 916
918 wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); 917 wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 { 971 {
973 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 972 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
974 i2c_del_driver(&wm8580_i2c_driver); 973 i2c_del_driver(&wm8580_i2c_driver);
975 #endif 974 #endif
976 } 975 }
977 module_exit(wm8580_exit); 976 module_exit(wm8580_exit);
978 977
979 MODULE_DESCRIPTION("ASoC WM8580 driver"); 978 MODULE_DESCRIPTION("ASoC WM8580 driver");
980 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 979 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
981 MODULE_LICENSE("GPL"); 980 MODULE_LICENSE("GPL");
OLDNEW
« no previous file with comments | « sound/soc/codecs/wm8523.c ('k') | sound/soc/codecs/wm8711.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698