~ctf/alsa-driver/tiwai-trunk2.bazooka_dock

« back to all changes in this revision

Viewing changes to soc/samsung/smartq_wm8987.c

  • Committer: Canonistack server
  • Date: 2015-01-22 13:04:34 UTC
  • Revision ID: david.henningsson@canonical.com-20150122130434-q48cfdp8ovzgqhe7
Test run of 623 machines: 3 failing with 3 errors and 0 warnings.

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