~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to sound/soc/samsung/smartq_wm8987.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* sound/soc/samsung/smartq_wm8987.c
 
2
 *
 
3
 * Copyright 2010 Maurus Cuelenaere <mcuelenaere@gmail.com>
 
4
 *
 
5
 * Based on smdk6410_wm8987.c
 
6
 *     Copyright 2007 Wolfson Microelectronics PLC. - linux@wolfsonmicro.com
 
7
 *     Graeme Gregory - graeme.gregory@wolfsonmicro.com
 
8
 *
 
9
 *  This program is free software; you can redistribute  it and/or modify it
 
10
 *  under  the terms of  the GNU General  Public License as published by the
 
11
 *  Free Software Foundation;  either version 2 of the  License, or (at your
 
12
 *  option) any later version.
 
13
 *
 
14
 */
 
15
 
 
16
#include <linux/gpio.h>
 
17
#include <linux/module.h>
 
18
 
 
19
#include <sound/soc.h>
 
20
#include <sound/jack.h>
 
21
 
 
22
#include <asm/mach-types.h>
 
23
 
 
24
#include "i2s.h"
 
25
#include "../codecs/wm8750.h"
 
26
 
 
27
/*
 
28
 * WM8987 is register compatible with WM8750, so using that as base driver.
 
29
 */
 
30
 
 
31
static struct snd_soc_card snd_soc_smartq;
 
32
 
 
33
static int smartq_hifi_hw_params(struct snd_pcm_substream *substream,
 
34
        struct snd_pcm_hw_params *params)
 
35
{
 
36
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 
37
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
38
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
39
        unsigned int clk = 0;
 
40
        int ret;
 
41
 
 
42
        switch (params_rate(params)) {
 
43
        case 8000:
 
44
        case 16000:
 
45
        case 32000:
 
46
        case 48000:
 
47
        case 96000:
 
48
                clk = 12288000;
 
49
                break;
 
50
        case 11025:
 
51
        case 22050:
 
52
        case 44100:
 
53
        case 88200:
 
54
                clk = 11289600;
 
55
                break;
 
56
        }
 
57
 
 
58
        /* set codec DAI configuration */
 
59
        ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
 
60
                                             SND_SOC_DAIFMT_NB_NF |
 
61
                                             SND_SOC_DAIFMT_CBS_CFS);
 
62
        if (ret < 0)
 
63
                return ret;
 
64
 
 
65
        /* set cpu DAI configuration */
 
66
        ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
 
67
                                           SND_SOC_DAIFMT_NB_NF |
 
68
                                           SND_SOC_DAIFMT_CBS_CFS);
 
69
        if (ret < 0)
 
70
                return ret;
 
71
 
 
72
        /* Use PCLK for I2S signal generation */
 
73
        ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0,
 
74
                                        0, SND_SOC_CLOCK_IN);
 
75
        if (ret < 0)
 
76
                return ret;
 
77
 
 
78
        /* Gate the RCLK output on PAD */
 
79
        ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK,
 
80
                                        0, SND_SOC_CLOCK_IN);
 
81
        if (ret < 0)
 
82
                return ret;
 
83
 
 
84
        /* set the codec system clock for DAC and ADC */
 
85
        ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
 
86
                                     SND_SOC_CLOCK_IN);
 
87
        if (ret < 0)
 
88
                return ret;
 
89
 
 
90
        return 0;
 
91
}
 
92
 
 
93
/*
 
94
 * SmartQ WM8987 HiFi DAI operations.
 
95
 */
 
96
static struct snd_soc_ops smartq_hifi_ops = {
 
97
        .hw_params = smartq_hifi_hw_params,
 
98
};
 
99
 
 
100
static struct snd_soc_jack smartq_jack;
 
101
 
 
102
static struct snd_soc_jack_pin smartq_jack_pins[] = {
 
103
        /* Disable speaker when headphone is plugged in */
 
104
        {
 
105
                .pin    = "Internal Speaker",
 
106
                .mask   = SND_JACK_HEADPHONE,
 
107
        },
 
108
};
 
109
 
 
110
static struct snd_soc_jack_gpio smartq_jack_gpios[] = {
 
111
        {
 
112
                .gpio           = S3C64XX_GPL(12),
 
113
                .name           = "headphone detect",
 
114
                .report         = SND_JACK_HEADPHONE,
 
115
                .debounce_time  = 200,
 
116
        },
 
117
};
 
118
 
 
119
static const struct snd_kcontrol_new wm8987_smartq_controls[] = {
 
120
        SOC_DAPM_PIN_SWITCH("Internal Speaker"),
 
121
        SOC_DAPM_PIN_SWITCH("Headphone Jack"),
 
122
        SOC_DAPM_PIN_SWITCH("Internal Mic"),
 
123
};
 
124
 
 
125
static int smartq_speaker_event(struct snd_soc_dapm_widget *w,
 
126
                                struct snd_kcontrol *k,
 
127
                                int event)
 
128
{
 
129
        gpio_set_value(S3C64XX_GPK(12), SND_SOC_DAPM_EVENT_OFF(event));
 
130
 
 
131
        return 0;
 
132
}
 
133
 
 
134
static const struct snd_soc_dapm_widget wm8987_dapm_widgets[] = {
 
135
        SND_SOC_DAPM_SPK("Internal Speaker", smartq_speaker_event),
 
136
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
 
137
        SND_SOC_DAPM_MIC("Internal Mic", NULL),
 
138
};
 
139
 
 
140
static const struct snd_soc_dapm_route audio_map[] = {
 
141
        {"Headphone Jack", NULL, "LOUT2"},
 
142
        {"Headphone Jack", NULL, "ROUT2"},
 
143
 
 
144
        {"Internal Speaker", NULL, "LOUT2"},
 
145
        {"Internal Speaker", NULL, "ROUT2"},
 
146
 
 
147
        {"Mic Bias", NULL, "Internal Mic"},
 
148
        {"LINPUT2", NULL, "Mic Bias"},
 
149
};
 
150
 
 
151
static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd)
 
152
{
 
153
        struct snd_soc_codec *codec = rtd->codec;
 
154
        struct snd_soc_dapm_context *dapm = &codec->dapm;
 
155
        int err = 0;
 
156
 
 
157
        /* set endpoints to not connected */
 
158
        snd_soc_dapm_nc_pin(dapm, "LINPUT1");
 
159
        snd_soc_dapm_nc_pin(dapm, "RINPUT1");
 
160
        snd_soc_dapm_nc_pin(dapm, "OUT3");
 
161
        snd_soc_dapm_nc_pin(dapm, "ROUT1");
 
162
 
 
163
        /* set endpoints to default off mode */
 
164
        snd_soc_dapm_enable_pin(dapm, "Internal Speaker");
 
165
        snd_soc_dapm_enable_pin(dapm, "Internal Mic");
 
166
        snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
 
167
 
 
168
        /* Headphone jack detection */
 
169
        err = snd_soc_jack_new(codec, "Headphone Jack",
 
170
                               SND_JACK_HEADPHONE, &smartq_jack);
 
171
        if (err)
 
172
                return err;
 
173
 
 
174
        err = snd_soc_jack_add_pins(&smartq_jack, ARRAY_SIZE(smartq_jack_pins),
 
175
                                    smartq_jack_pins);
 
176
        if (err)
 
177
                return err;
 
178
 
 
179
        err = snd_soc_jack_add_gpios(&smartq_jack,
 
180
                                     ARRAY_SIZE(smartq_jack_gpios),
 
181
                                     smartq_jack_gpios);
 
182
 
 
183
        return err;
 
184
}
 
185
 
 
186
static struct snd_soc_dai_link smartq_dai[] = {
 
187
        {
 
188
                .name           = "wm8987",
 
189
                .stream_name    = "SmartQ Hi-Fi",
 
190
                .cpu_dai_name   = "samsung-i2s.0",
 
191
                .codec_dai_name = "wm8750-hifi",
 
192
                .platform_name  = "samsung-audio",
 
193
                .codec_name     = "wm8750.0-0x1a",
 
194
                .init           = smartq_wm8987_init,
 
195
                .ops            = &smartq_hifi_ops,
 
196
        },
 
197
};
 
198
 
 
199
static struct snd_soc_card snd_soc_smartq = {
 
200
        .name = "SmartQ",
 
201
        .dai_link = smartq_dai,
 
202
        .num_links = ARRAY_SIZE(smartq_dai),
 
203
 
 
204
        .dapm_widgets = wm8987_dapm_widgets,
 
205
        .num_dapm_widgets = ARRAY_SIZE(wm8987_dapm_widgets),
 
206
        .dapm_routes = audio_map,
 
207
        .num_dapm_routes = ARRAY_SIZE(audio_map),
 
208
        .controls = wm8987_smartq_controls,
 
209
        .num_controls = ARRAY_SIZE(wm8987_smartq_controls),
 
210
};
 
211
 
 
212
static struct platform_device *smartq_snd_device;
 
213
 
 
214
static int __init smartq_init(void)
 
215
{
 
216
        int ret;
 
217
 
 
218
        if (!machine_is_smartq7() && !machine_is_smartq5()) {
 
219
                pr_info("Only SmartQ is supported by this ASoC driver\n");
 
220
                return -ENODEV;
 
221
        }
 
222
 
 
223
        smartq_snd_device = platform_device_alloc("soc-audio", -1);
 
224
        if (!smartq_snd_device)
 
225
                return -ENOMEM;
 
226
 
 
227
        platform_set_drvdata(smartq_snd_device, &snd_soc_smartq);
 
228
 
 
229
        ret = platform_device_add(smartq_snd_device);
 
230
        if (ret) {
 
231
                platform_device_put(smartq_snd_device);
 
232
                return ret;
 
233
        }
 
234
 
 
235
        /* Initialise GPIOs used by amplifiers */
 
236
        ret = gpio_request(S3C64XX_GPK(12), "amplifiers shutdown");
 
237
        if (ret) {
 
238
                dev_err(&smartq_snd_device->dev, "Failed to register GPK12\n");
 
239
                goto err_unregister_device;
 
240
        }
 
241
 
 
242
        /* Disable amplifiers */
 
243
        ret = gpio_direction_output(S3C64XX_GPK(12), 1);
 
244
        if (ret) {
 
245
                dev_err(&smartq_snd_device->dev, "Failed to configure GPK12\n");
 
246
                goto err_free_gpio_amp_shut;
 
247
        }
 
248
 
 
249
        return 0;
 
250
 
 
251
err_free_gpio_amp_shut:
 
252
        gpio_free(S3C64XX_GPK(12));
 
253
err_unregister_device:
 
254
        platform_device_unregister(smartq_snd_device);
 
255
 
 
256
        return ret;
 
257
}
 
258
 
 
259
static void __exit smartq_exit(void)
 
260
{
 
261
        gpio_free(S3C64XX_GPK(12));
 
262
        snd_soc_jack_free_gpios(&smartq_jack, ARRAY_SIZE(smartq_jack_gpios),
 
263
                                smartq_jack_gpios);
 
264
 
 
265
        platform_device_unregister(smartq_snd_device);
 
266
}
 
267
 
 
268
module_init(smartq_init);
 
269
module_exit(smartq_exit);
 
270
 
 
271
/* Module information */
 
272
MODULE_AUTHOR("Maurus Cuelenaere <mcuelenaere@gmail.com>");
 
273
MODULE_DESCRIPTION("ALSA SoC SmartQ WM8987");
 
274
MODULE_LICENSE("GPL");