~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to sound/soc/pxa/hx4700.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * SoC audio for HP iPAQ hx4700
 
3
 *
 
4
 * Copyright (c) 2009 Philipp Zabel
 
5
 *
 
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.
 
10
 *
 
11
 */
 
12
 
 
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>
 
19
 
 
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>
 
25
 
 
26
#include <mach/hx4700.h>
 
27
#include <asm/mach-types.h>
 
28
#include "pxa2xx-i2s.h"
 
29
 
 
30
#include "../codecs/ak4641.h"
 
31
 
 
32
static struct snd_soc_jack hs_jack;
 
33
 
 
34
/* Headphones jack detection DAPM pin */
 
35
static struct snd_soc_jack_pin hs_jack_pin[] = {
 
36
        {
 
37
                .pin    = "Headphone Jack",
 
38
                .mask   = SND_JACK_HEADPHONE,
 
39
        },
 
40
        {
 
41
                .pin    = "Speaker",
 
42
                /* disable speaker when hp jack is inserted */
 
43
                .mask   = SND_JACK_HEADPHONE,
 
44
                .invert = 1,
 
45
        },
 
46
};
 
47
 
 
48
/* Headphones jack detection GPIO */
 
49
static struct snd_soc_jack_gpio hs_jack_gpio = {
 
50
        .gpio           = GPIO75_HX4700_EARPHONE_nDET,
 
51
        .invert         = true,
 
52
        .name           = "hp-gpio",
 
53
        .report         = SND_JACK_HEADPHONE,
 
54
        .debounce_time  = 200,
 
55
};
 
56
 
 
57
/*
 
58
 * iPAQ hx4700 uses I2S for capture and playback.
 
59
 */
 
60
static int hx4700_hw_params(struct snd_pcm_substream *substream,
 
61
                            struct snd_pcm_hw_params *params)
 
62
{
 
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;
 
66
        int ret = 0;
 
67
 
 
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);
 
72
        if (ret < 0)
 
73
                return ret;
 
74
 
 
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);
 
79
        if (ret < 0)
 
80
                return ret;
 
81
 
 
82
        /* set the I2S system clock as output */
 
83
        ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
 
84
                        SND_SOC_CLOCK_OUT);
 
85
        if (ret < 0)
 
86
                return ret;
 
87
 
 
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),
 
91
                        SND_SOC_CLOCK_IN);
 
92
        if (ret < 0)
 
93
                return ret;
 
94
 
 
95
        return 0;
 
96
}
 
97
 
 
98
static struct snd_soc_ops hx4700_ops = {
 
99
        .hw_params = hx4700_hw_params,
 
100
};
 
101
 
 
102
static int hx4700_spk_power(struct snd_soc_dapm_widget *w,
 
103
                            struct snd_kcontrol *k, int event)
 
104
{
 
105
        gpio_set_value(GPIO107_HX4700_SPK_nSD, !!SND_SOC_DAPM_EVENT_ON(event));
 
106
        return 0;
 
107
}
 
108
 
 
109
static int hx4700_hp_power(struct snd_soc_dapm_widget *w,
 
110
                           struct snd_kcontrol *k, int event)
 
111
{
 
112
        gpio_set_value(GPIO92_HX4700_HP_DRIVER, !!SND_SOC_DAPM_EVENT_ON(event));
 
113
        return 0;
 
114
}
 
115
 
 
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),
 
121
};
 
122
 
 
123
/* hx4700 machine audio_map */
 
124
static const struct snd_soc_dapm_route hx4700_audio_map[] = {
 
125
 
 
126
        /* Headphone connected to LOUT, ROUT */
 
127
        {"Headphone Jack", NULL, "LOUT"},
 
128
        {"Headphone Jack", NULL, "ROUT"},
 
129
 
 
130
        /* Speaker connected to MOUT2 */
 
131
        {"Speaker", NULL, "MOUT2"},
 
132
 
 
133
        /* Microphone connected to MICIN */
 
134
        {"MICIN", NULL, "Built-in Microphone"},
 
135
        {"AIN", NULL, "MICOUT"},
 
136
};
 
137
 
 
138
/*
 
139
 * Logic for a ak4641 as connected on a HP iPAQ hx4700
 
140
 */
 
141
static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd)
 
142
{
 
143
        struct snd_soc_codec *codec = rtd->codec;
 
144
        struct snd_soc_dapm_context *dapm = &codec->dapm;
 
145
        int err;
 
146
 
 
147
        /* NC codec pins */
 
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");
 
152
 
 
153
        /* Jack detection API stuff */
 
154
        err = snd_soc_jack_new(codec, "Headphone Jack",
 
155
                                SND_JACK_HEADPHONE, &hs_jack);
 
156
        if (err)
 
157
                return err;
 
158
 
 
159
        err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pin),
 
160
                                        hs_jack_pin);
 
161
        if (err)
 
162
                return err;
 
163
 
 
164
        err = snd_soc_jack_add_gpios(&hs_jack, 1, &hs_jack_gpio);
 
165
 
 
166
        return err;
 
167
}
 
168
 
 
169
/* hx4700 digital audio interface glue - connects codec <--> CPU */
 
170
static struct snd_soc_dai_link hx4700_dai = {
 
171
        .name = "ak4641",
 
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,
 
178
        .ops = &hx4700_ops,
 
179
};
 
180
 
 
181
/* hx4700 audio machine driver */
 
182
static struct snd_soc_card snd_soc_card_hx4700 = {
 
183
        .name                   = "iPAQ hx4700",
 
184
        .dai_link               = &hx4700_dai,
 
185
        .num_links              = 1,
 
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),
 
190
};
 
191
 
 
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" },
 
195
};
 
196
 
 
197
static int __devinit hx4700_audio_probe(struct platform_device *pdev)
 
198
{
 
199
        int ret;
 
200
 
 
201
        if (!machine_is_h4700())
 
202
                return -ENODEV;
 
203
 
 
204
        ret = gpio_request_array(hx4700_audio_gpios,
 
205
                                ARRAY_SIZE(hx4700_audio_gpios));
 
206
        if (ret)
 
207
                return ret;
 
208
 
 
209
        snd_soc_card_hx4700.dev = &pdev->dev;
 
210
        ret = snd_soc_register_card(&snd_soc_card_hx4700);
 
211
        if (ret)
 
212
                return ret;
 
213
 
 
214
        return 0;
 
215
}
 
216
 
 
217
static int __devexit hx4700_audio_remove(struct platform_device *pdev)
 
218
{
 
219
        snd_soc_jack_free_gpios(&hs_jack, 1, &hs_jack_gpio);
 
220
        snd_soc_unregister_card(&snd_soc_card_hx4700);
 
221
 
 
222
        gpio_set_value(GPIO92_HX4700_HP_DRIVER, 0);
 
223
        gpio_set_value(GPIO107_HX4700_SPK_nSD, 0);
 
224
 
 
225
        gpio_free_array(hx4700_audio_gpios, ARRAY_SIZE(hx4700_audio_gpios));
 
226
        return 0;
 
227
}
 
228
 
 
229
static struct platform_driver hx4700_audio_driver = {
 
230
        .driver = {
 
231
                .name = "hx4700-audio",
 
232
                .owner = THIS_MODULE,
 
233
                .pm = &snd_soc_pm_ops,
 
234
        },
 
235
        .probe  = hx4700_audio_probe,
 
236
        .remove = __devexit_p(hx4700_audio_remove),
 
237
};
 
238
 
 
239
static int __init hx4700_modinit(void)
 
240
{
 
241
        return platform_driver_register(&hx4700_audio_driver);
 
242
}
 
243
module_init(hx4700_modinit);
 
244
 
 
245
static void __exit hx4700_modexit(void)
 
246
{
 
247
        platform_driver_unregister(&hx4700_audio_driver);
 
248
}
 
249
 
 
250
module_exit(hx4700_modexit);
 
251
 
 
252
MODULE_AUTHOR("Philipp Zabel");
 
253
MODULE_DESCRIPTION("ALSA SoC iPAQ hx4700");
 
254
MODULE_LICENSE("GPL");
 
255
MODULE_ALIAS("platform:hx4700-audio");