diff options
Diffstat (limited to 'sound/soc/imx/mx27vis-aic32x4.c')
-rw-r--r-- | sound/soc/imx/mx27vis-aic32x4.c | 159 |
1 files changed, 133 insertions, 26 deletions
diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/imx/mx27vis-aic32x4.c index 3c2eed9094d5..f6d04ad4bb39 100644 --- a/sound/soc/imx/mx27vis-aic32x4.c +++ b/sound/soc/imx/mx27vis-aic32x4.c | |||
@@ -25,15 +25,36 @@ | |||
25 | #include <linux/moduleparam.h> | 25 | #include <linux/moduleparam.h> |
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include <linux/gpio.h> | ||
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
29 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
30 | #include <sound/soc.h> | 31 | #include <sound/soc.h> |
31 | #include <sound/soc-dapm.h> | 32 | #include <sound/soc-dapm.h> |
33 | #include <sound/tlv.h> | ||
32 | #include <asm/mach-types.h> | 34 | #include <asm/mach-types.h> |
33 | #include <mach/audmux.h> | 35 | #include <mach/iomux-mx27.h> |
34 | 36 | ||
35 | #include "../codecs/tlv320aic32x4.h" | 37 | #include "../codecs/tlv320aic32x4.h" |
36 | #include "imx-ssi.h" | 38 | #include "imx-ssi.h" |
39 | #include "imx-audmux.h" | ||
40 | |||
41 | #define MX27VIS_AMP_GAIN 0 | ||
42 | #define MX27VIS_AMP_MUTE 1 | ||
43 | |||
44 | #define MX27VIS_PIN_G0 (GPIO_PORTF + 9) | ||
45 | #define MX27VIS_PIN_G1 (GPIO_PORTF + 8) | ||
46 | #define MX27VIS_PIN_SDL (GPIO_PORTE + 5) | ||
47 | #define MX27VIS_PIN_SDR (GPIO_PORTF + 7) | ||
48 | |||
49 | static int mx27vis_amp_gain; | ||
50 | static int mx27vis_amp_mute; | ||
51 | |||
52 | static const int mx27vis_amp_pins[] = { | ||
53 | MX27VIS_PIN_G0 | GPIO_GPIO | GPIO_OUT, | ||
54 | MX27VIS_PIN_G1 | GPIO_GPIO | GPIO_OUT, | ||
55 | MX27VIS_PIN_SDL | GPIO_GPIO | GPIO_OUT, | ||
56 | MX27VIS_PIN_SDR | GPIO_GPIO | GPIO_OUT, | ||
57 | }; | ||
37 | 58 | ||
38 | static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, | 59 | static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, |
39 | struct snd_pcm_hw_params *params) | 60 | struct snd_pcm_hw_params *params) |
@@ -74,6 +95,76 @@ static struct snd_soc_ops mx27vis_aic32x4_snd_ops = { | |||
74 | .hw_params = mx27vis_aic32x4_hw_params, | 95 | .hw_params = mx27vis_aic32x4_hw_params, |
75 | }; | 96 | }; |
76 | 97 | ||
98 | static int mx27vis_amp_set(struct snd_kcontrol *kcontrol, | ||
99 | struct snd_ctl_elem_value *ucontrol) | ||
100 | { | ||
101 | struct soc_mixer_control *mc = | ||
102 | (struct soc_mixer_control *)kcontrol->private_value; | ||
103 | int value = ucontrol->value.integer.value[0]; | ||
104 | unsigned int reg = mc->reg; | ||
105 | int max = mc->max; | ||
106 | |||
107 | if (value > max) | ||
108 | return -EINVAL; | ||
109 | |||
110 | switch (reg) { | ||
111 | case MX27VIS_AMP_GAIN: | ||
112 | gpio_set_value(MX27VIS_PIN_G0, value & 1); | ||
113 | gpio_set_value(MX27VIS_PIN_G1, value >> 1); | ||
114 | mx27vis_amp_gain = value; | ||
115 | break; | ||
116 | case MX27VIS_AMP_MUTE: | ||
117 | gpio_set_value(MX27VIS_PIN_SDL, value & 1); | ||
118 | gpio_set_value(MX27VIS_PIN_SDR, value >> 1); | ||
119 | mx27vis_amp_mute = value; | ||
120 | break; | ||
121 | } | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static int mx27vis_amp_get(struct snd_kcontrol *kcontrol, | ||
126 | struct snd_ctl_elem_value *ucontrol) | ||
127 | { | ||
128 | struct soc_mixer_control *mc = | ||
129 | (struct soc_mixer_control *)kcontrol->private_value; | ||
130 | unsigned int reg = mc->reg; | ||
131 | |||
132 | switch (reg) { | ||
133 | case MX27VIS_AMP_GAIN: | ||
134 | ucontrol->value.integer.value[0] = mx27vis_amp_gain; | ||
135 | break; | ||
136 | case MX27VIS_AMP_MUTE: | ||
137 | ucontrol->value.integer.value[0] = mx27vis_amp_mute; | ||
138 | break; | ||
139 | } | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | /* From 6dB to 24dB in steps of 6dB */ | ||
144 | static const DECLARE_TLV_DB_SCALE(mx27vis_amp_tlv, 600, 600, 0); | ||
145 | |||
146 | static const struct snd_kcontrol_new mx27vis_aic32x4_controls[] = { | ||
147 | SOC_DAPM_PIN_SWITCH("External Mic"), | ||
148 | SOC_SINGLE_EXT_TLV("LO Ext Boost", MX27VIS_AMP_GAIN, 0, 3, 0, | ||
149 | mx27vis_amp_get, mx27vis_amp_set, mx27vis_amp_tlv), | ||
150 | SOC_DOUBLE_EXT("LO Ext Mute Switch", MX27VIS_AMP_MUTE, 0, 1, 1, 0, | ||
151 | mx27vis_amp_get, mx27vis_amp_set), | ||
152 | }; | ||
153 | |||
154 | static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { | ||
155 | SND_SOC_DAPM_MIC("External Mic", NULL), | ||
156 | }; | ||
157 | |||
158 | static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = { | ||
159 | {"Mic Bias", NULL, "External Mic"}, | ||
160 | {"IN1_R", NULL, "Mic Bias"}, | ||
161 | {"IN2_R", NULL, "Mic Bias"}, | ||
162 | {"IN3_R", NULL, "Mic Bias"}, | ||
163 | {"IN1_L", NULL, "Mic Bias"}, | ||
164 | {"IN2_L", NULL, "Mic Bias"}, | ||
165 | {"IN3_L", NULL, "Mic Bias"}, | ||
166 | }; | ||
167 | |||
77 | static struct snd_soc_dai_link mx27vis_aic32x4_dai = { | 168 | static struct snd_soc_dai_link mx27vis_aic32x4_dai = { |
78 | .name = "tlv320aic32x4", | 169 | .name = "tlv320aic32x4", |
79 | .stream_name = "TLV320AIC32X4", | 170 | .stream_name = "TLV320AIC32X4", |
@@ -89,50 +180,66 @@ static struct snd_soc_card mx27vis_aic32x4 = { | |||
89 | .owner = THIS_MODULE, | 180 | .owner = THIS_MODULE, |
90 | .dai_link = &mx27vis_aic32x4_dai, | 181 | .dai_link = &mx27vis_aic32x4_dai, |
91 | .num_links = 1, | 182 | .num_links = 1, |
183 | .controls = mx27vis_aic32x4_controls, | ||
184 | .num_controls = ARRAY_SIZE(mx27vis_aic32x4_controls), | ||
185 | .dapm_widgets = aic32x4_dapm_widgets, | ||
186 | .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets), | ||
187 | .dapm_routes = aic32x4_dapm_routes, | ||
188 | .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), | ||
92 | }; | 189 | }; |
93 | 190 | ||
94 | static struct platform_device *mx27vis_aic32x4_snd_device; | 191 | static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) |
95 | |||
96 | static int __init mx27vis_aic32x4_init(void) | ||
97 | { | 192 | { |
98 | int ret; | 193 | int ret; |
99 | 194 | ||
100 | mx27vis_aic32x4_snd_device = platform_device_alloc("soc-audio", -1); | 195 | mx27vis_aic32x4.dev = &pdev->dev; |
101 | if (!mx27vis_aic32x4_snd_device) | 196 | ret = snd_soc_register_card(&mx27vis_aic32x4); |
102 | return -ENOMEM; | ||
103 | |||
104 | platform_set_drvdata(mx27vis_aic32x4_snd_device, &mx27vis_aic32x4); | ||
105 | ret = platform_device_add(mx27vis_aic32x4_snd_device); | ||
106 | |||
107 | if (ret) { | 197 | if (ret) { |
108 | printk(KERN_ERR "ASoC: Platform device allocation failed\n"); | 198 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", |
109 | platform_device_put(mx27vis_aic32x4_snd_device); | 199 | ret); |
200 | return ret; | ||
110 | } | 201 | } |
111 | 202 | ||
112 | /* Connect SSI0 as clock slave to SSI1 external pins */ | 203 | /* Connect SSI0 as clock slave to SSI1 external pins */ |
113 | mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, | 204 | imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, |
114 | MXC_AUDMUX_V1_PCR_SYN | | 205 | IMX_AUDMUX_V1_PCR_SYN | |
115 | MXC_AUDMUX_V1_PCR_TFSDIR | | 206 | IMX_AUDMUX_V1_PCR_TFSDIR | |
116 | MXC_AUDMUX_V1_PCR_TCLKDIR | | 207 | IMX_AUDMUX_V1_PCR_TCLKDIR | |
117 | MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) | | 208 | IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) | |
118 | MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) | 209 | IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) |
119 | ); | 210 | ); |
120 | mxc_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1, | 211 | imx_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1, |
121 | MXC_AUDMUX_V1_PCR_SYN | | 212 | IMX_AUDMUX_V1_PCR_SYN | |
122 | MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) | 213 | IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) |
123 | ); | 214 | ); |
124 | 215 | ||
216 | ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins, | ||
217 | ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP"); | ||
218 | if (ret) | ||
219 | printk(KERN_ERR "ASoC: unable to setup gpios\n"); | ||
220 | |||
125 | return ret; | 221 | return ret; |
126 | } | 222 | } |
127 | 223 | ||
128 | static void __exit mx27vis_aic32x4_exit(void) | 224 | static int __devexit mx27vis_aic32x4_remove(struct platform_device *pdev) |
129 | { | 225 | { |
130 | platform_device_unregister(mx27vis_aic32x4_snd_device); | 226 | snd_soc_unregister_card(&mx27vis_aic32x4); |
227 | |||
228 | return 0; | ||
131 | } | 229 | } |
132 | 230 | ||
133 | module_init(mx27vis_aic32x4_init); | 231 | static struct platform_driver mx27vis_aic32x4_audio_driver = { |
134 | module_exit(mx27vis_aic32x4_exit); | 232 | .driver = { |
233 | .name = "mx27vis", | ||
234 | .owner = THIS_MODULE, | ||
235 | }, | ||
236 | .probe = mx27vis_aic32x4_probe, | ||
237 | .remove = __devexit_p(mx27vis_aic32x4_remove), | ||
238 | }; | ||
239 | |||
240 | module_platform_driver(mx27vis_aic32x4_audio_driver); | ||
135 | 241 | ||
136 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); | 242 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); |
137 | MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim"); | 243 | MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim"); |
138 | MODULE_LICENSE("GPL"); | 244 | MODULE_LICENSE("GPL"); |
245 | MODULE_ALIAS("platform:mx27vis"); | ||