2
* SoC audio for HP iPAQ hx4700
4
* Copyright (c) 2009 Philipp Zabel
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
8
* Free Software Foundation; either version 2 of the License, or (at your
9
* option) any later version.
13
#include <linux/module.h>
14
#include <linux/timer.h>
15
#include <linux/interrupt.h>
16
#include <linux/platform_device.h>
17
#include <linux/delay.h>
18
#include <linux/gpio.h>
20
#include <sound/core.h>
21
#include <sound/jack.h>
22
#include <sound/pcm.h>
23
#include <sound/pcm_params.h>
24
#include <sound/soc.h>
26
#include <mach/hx4700.h>
27
#include <asm/mach-types.h>
28
#include "pxa2xx-i2s.h"
30
#include "../codecs/ak4641.h"
32
static struct snd_soc_jack hs_jack;
34
/* Headphones jack detection DAPM pin */
35
static struct snd_soc_jack_pin hs_jack_pin[] = {
37
.pin = "Headphone Jack",
38
.mask = SND_JACK_HEADPHONE,
42
/* disable speaker when hp jack is inserted */
43
.mask = SND_JACK_HEADPHONE,
48
/* Headphones jack detection GPIO */
49
static struct snd_soc_jack_gpio hs_jack_gpio = {
50
.gpio = GPIO75_HX4700_EARPHONE_nDET,
53
.report = SND_JACK_HEADPHONE,
58
* iPAQ hx4700 uses I2S for capture and playback.
60
static int hx4700_hw_params(struct snd_pcm_substream *substream,
61
struct snd_pcm_hw_params *params)
63
struct snd_soc_pcm_runtime *rtd = substream->private_data;
64
struct snd_soc_dai *codec_dai = rtd->codec_dai;
65
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
68
/* set codec DAI configuration */
69
ret = snd_soc_dai_set_fmt(codec_dai,
70
SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF |
71
SND_SOC_DAIFMT_CBS_CFS);
75
/* set cpu DAI configuration */
76
ret = snd_soc_dai_set_fmt(cpu_dai,
77
SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF |
78
SND_SOC_DAIFMT_CBS_CFS);
82
/* set the I2S system clock as output */
83
ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
88
/* inform codec driver about clock freq *
89
* (PXA I2S always uses divider 256) */
90
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 256 * params_rate(params),
98
static struct snd_soc_ops hx4700_ops = {
99
.hw_params = hx4700_hw_params,
102
static int hx4700_spk_power(struct snd_soc_dapm_widget *w,
103
struct snd_kcontrol *k, int event)
105
gpio_set_value(GPIO107_HX4700_SPK_nSD, !!SND_SOC_DAPM_EVENT_ON(event));
109
static int hx4700_hp_power(struct snd_soc_dapm_widget *w,
110
struct snd_kcontrol *k, int event)
112
gpio_set_value(GPIO92_HX4700_HP_DRIVER, !!SND_SOC_DAPM_EVENT_ON(event));
116
/* hx4700 machine dapm widgets */
117
static const struct snd_soc_dapm_widget hx4700_dapm_widgets[] = {
118
SND_SOC_DAPM_HP("Headphone Jack", hx4700_hp_power),
119
SND_SOC_DAPM_SPK("Speaker", hx4700_spk_power),
120
SND_SOC_DAPM_MIC("Built-in Microphone", NULL),
123
/* hx4700 machine audio_map */
124
static const struct snd_soc_dapm_route hx4700_audio_map[] = {
126
/* Headphone connected to LOUT, ROUT */
127
{"Headphone Jack", NULL, "LOUT"},
128
{"Headphone Jack", NULL, "ROUT"},
130
/* Speaker connected to MOUT2 */
131
{"Speaker", NULL, "MOUT2"},
133
/* Microphone connected to MICIN */
134
{"MICIN", NULL, "Built-in Microphone"},
135
{"AIN", NULL, "MICOUT"},
139
* Logic for a ak4641 as connected on a HP iPAQ hx4700
141
static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd)
143
struct snd_soc_codec *codec = rtd->codec;
144
struct snd_soc_dapm_context *dapm = &codec->dapm;
148
/* FIXME: is anything connected here? */
149
snd_soc_dapm_nc_pin(dapm, "MOUT1");
150
snd_soc_dapm_nc_pin(dapm, "MICEXT");
151
snd_soc_dapm_nc_pin(dapm, "AUX");
153
/* Jack detection API stuff */
154
err = snd_soc_jack_new(codec, "Headphone Jack",
155
SND_JACK_HEADPHONE, &hs_jack);
159
err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pin),
164
err = snd_soc_jack_add_gpios(&hs_jack, 1, &hs_jack_gpio);
169
/* hx4700 digital audio interface glue - connects codec <--> CPU */
170
static struct snd_soc_dai_link hx4700_dai = {
172
.stream_name = "AK4641",
173
.cpu_dai_name = "pxa2xx-i2s",
174
.codec_dai_name = "ak4641-hifi",
175
.platform_name = "pxa-pcm-audio",
176
.codec_name = "ak4641.0-0012",
177
.init = hx4700_ak4641_init,
181
/* hx4700 audio machine driver */
182
static struct snd_soc_card snd_soc_card_hx4700 = {
183
.name = "iPAQ hx4700",
184
.dai_link = &hx4700_dai,
186
.dapm_widgets = hx4700_dapm_widgets,
187
.num_dapm_widgets = ARRAY_SIZE(hx4700_dapm_widgets),
188
.dapm_routes = hx4700_audio_map,
189
.num_dapm_routes = ARRAY_SIZE(hx4700_audio_map),
192
static struct gpio hx4700_audio_gpios[] = {
193
{ GPIO107_HX4700_SPK_nSD, GPIOF_OUT_INIT_HIGH, "SPK_POWER" },
194
{ GPIO92_HX4700_HP_DRIVER, GPIOF_OUT_INIT_LOW, "EP_POWER" },
197
static int __devinit hx4700_audio_probe(struct platform_device *pdev)
201
if (!machine_is_h4700())
204
ret = gpio_request_array(hx4700_audio_gpios,
205
ARRAY_SIZE(hx4700_audio_gpios));
209
snd_soc_card_hx4700.dev = &pdev->dev;
210
ret = snd_soc_register_card(&snd_soc_card_hx4700);
217
static int __devexit hx4700_audio_remove(struct platform_device *pdev)
219
snd_soc_jack_free_gpios(&hs_jack, 1, &hs_jack_gpio);
220
snd_soc_unregister_card(&snd_soc_card_hx4700);
222
gpio_set_value(GPIO92_HX4700_HP_DRIVER, 0);
223
gpio_set_value(GPIO107_HX4700_SPK_nSD, 0);
225
gpio_free_array(hx4700_audio_gpios, ARRAY_SIZE(hx4700_audio_gpios));
229
static struct platform_driver hx4700_audio_driver = {
231
.name = "hx4700-audio",
232
.owner = THIS_MODULE,
233
.pm = &snd_soc_pm_ops,
235
.probe = hx4700_audio_probe,
236
.remove = __devexit_p(hx4700_audio_remove),
239
static int __init hx4700_modinit(void)
241
return platform_driver_register(&hx4700_audio_driver);
243
module_init(hx4700_modinit);
245
static void __exit hx4700_modexit(void)
247
platform_driver_unregister(&hx4700_audio_driver);
250
module_exit(hx4700_modexit);
252
MODULE_AUTHOR("Philipp Zabel");
253
MODULE_DESCRIPTION("ALSA SoC iPAQ hx4700");
254
MODULE_LICENSE("GPL");
255
MODULE_ALIAS("platform:hx4700-audio");