aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/imx/mx27vis-aic32x4.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/imx/mx27vis-aic32x4.c')
-rw-r--r--sound/soc/imx/mx27vis-aic32x4.c159
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
49static int mx27vis_amp_gain;
50static int mx27vis_amp_mute;
51
52static 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
38static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, 59static 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
98static 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
125static 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 */
144static const DECLARE_TLV_DB_SCALE(mx27vis_amp_tlv, 600, 600, 0);
145
146static 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
154static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
155 SND_SOC_DAPM_MIC("External Mic", NULL),
156};
157
158static 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
77static struct snd_soc_dai_link mx27vis_aic32x4_dai = { 168static 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
94static struct platform_device *mx27vis_aic32x4_snd_device; 191static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
95
96static 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
128static void __exit mx27vis_aic32x4_exit(void) 224static 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
133module_init(mx27vis_aic32x4_init); 231static struct platform_driver mx27vis_aic32x4_audio_driver = {
134module_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
240module_platform_driver(mx27vis_aic32x4_audio_driver);
135 241
136MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); 242MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
137MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim"); 243MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim");
138MODULE_LICENSE("GPL"); 244MODULE_LICENSE("GPL");
245MODULE_ALIAS("platform:mx27vis");