2 * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * You should have received a copy of the GNU General Public License along
9 * with this program; if not, write to the Free Software Foundation, Inc.,
10 * 675 Mass Ave, Cambridge, MA 02139, USA.
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/timer.h>
17 #include <linux/interrupt.h>
18 #include <linux/platform_device.h>
19 #include <sound/core.h>
20 #include <sound/pcm.h>
21 #include <sound/soc.h>
22 #include <sound/soc-dapm.h>
23 #include <linux/gpio.h>
25 #include "../codecs/jzcodec.h"
26 #include "jz4740-pcm.h"
27 #include "jz4740-i2s.h"
29 #define N526_AMP_EN_GPIO JZ_GPIO_PORTD(4)
31 static int n526_spk_event(struct snd_soc_dapm_widget
*widget
,
32 struct snd_kcontrol
*ctrl
, int event
)
34 gpio_set_value(N526_AMP_EN_GPIO
, !SND_SOC_DAPM_EVENT_OFF(event
));
38 static const struct snd_soc_dapm_widget n526_widgets
[] = {
39 SND_SOC_DAPM_SPK("Speaker", n526_spk_event
),
40 SND_SOC_DAPM_HP("Headphone", NULL
),
41 SND_SOC_DAPM_MIC("Mic", NULL
),
44 static const struct snd_soc_dapm_route n526_routes
[] = {
46 {"Speaker", NULL
, "LOUT"},
47 {"Speaker", NULL
, "ROUT"},
48 {"Headphone", NULL
, "LOUT"},
49 {"Headphone", NULL
, "ROUT"},
52 static const struct snd_kcontrol_new n526_controls
[] = {
53 SOC_DAPM_PIN_SWITCH("Speaker"),
56 #define N526_DAIFMT (SND_SOC_DAIFMT_I2S | \
57 SND_SOC_DAIFMT_NB_NF | \
58 SND_SOC_DAIFMT_CBM_CFM)
60 static int n526_codec_init(struct snd_soc_codec
*codec
)
63 struct snd_soc_dai
*cpu_dai
= codec
->socdev
->card
->dai_link
->cpu_dai
;
64 struct snd_soc_dai
*codec_dai
= codec
->socdev
->card
->dai_link
->codec_dai
;
66 snd_soc_dapm_nc_pin(codec
, "LIN");
67 snd_soc_dapm_nc_pin(codec
, "RIN");
69 ret
= snd_soc_dai_set_fmt(codec_dai
, N526_DAIFMT
);
71 dev_err(codec
->dev
, "Failed to set codec dai format: %d\n", ret
);
75 ret
= snd_soc_dai_set_fmt(cpu_dai
, N526_DAIFMT
);
77 dev_err(codec
->dev
, "Failed to set cpu dai format: %d\n", ret
);
81 ret
= snd_soc_dai_set_sysclk(codec_dai
, JZCODEC_SYSCLK
, 111,
84 dev_err(codec
->dev
, "Failed to set codec dai sysclk: %d\n", ret
);
88 snd_soc_dapm_new_controls(codec
, n526_widgets
, ARRAY_SIZE(n526_widgets
));
90 snd_soc_add_controls(codec
, n526_controls
,
91 ARRAY_SIZE(n526_controls
));
93 snd_soc_dapm_add_routes(codec
, n526_routes
, ARRAY_SIZE(n526_routes
));
95 snd_soc_dapm_sync(codec
);
100 static struct snd_soc_dai_link n526_dai
= {
102 .stream_name
= "JZCODEC",
103 .cpu_dai
= &jz4740_i2s_dai
,
104 .codec_dai
= &jz_codec_dai
,
105 .init
= n526_codec_init
,
108 static struct snd_soc_card n526
= {
110 .dai_link
= &n526_dai
,
112 .platform
= &jz4740_soc_platform
,
115 static struct snd_soc_device n526_snd_devdata
= {
117 .codec_dev
= &soc_codec_dev_jzcodec
,
120 static struct platform_device
*n526_snd_device
;
122 static int __init
n526_init(void)
126 n526_snd_device
= platform_device_alloc("soc-audio", -1);
128 if (!n526_snd_device
)
131 ret
= gpio_request(N526_AMP_EN_GPIO
, "AMP");
133 pr_err("n526 snd: Failed to request AMP GPIO(%d): %d\n",
134 N526_AMP_EN_GPIO
, ret
);
138 gpio_direction_output(JZ_GPIO_PORTD(4), 0);
140 platform_set_drvdata(n526_snd_device
, &n526_snd_devdata
);
141 n526_snd_devdata
.dev
= &n526_snd_device
->dev
;
142 ret
= platform_device_add(n526_snd_device
);
144 pr_err("n526 snd: Failed to add snd soc device: %d\n", ret
);
145 goto err_unset_pdata
;
151 platform_set_drvdata(n526_snd_device
, NULL
);
152 gpio_free(N526_AMP_EN_GPIO
);
154 platform_device_put(n526_snd_device
);
158 module_init(n526_init
);
160 static void __exit
n526_exit(void)
162 gpio_free(N526_AMP_EN_GPIO
);
163 platform_device_unregister(n526_snd_device
);
165 module_exit(n526_exit
);
167 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
168 MODULE_DESCRIPTION("ALSA SoC N526 audio support");
169 MODULE_LICENSE("GPL v2");