2
* mfld_machine.c - ASoc Machine driver for Intel Medfield MID platform
4
* Copyright (C) 2010 Intel Corp
5
* Author: Vinod Koul <vinod.koul@intel.com>
6
* Author: Harsha Priya <priya.harsha@intel.com>
7
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; version 2 of the License.
13
* This program is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public License along
19
* with this program; if not, write to the Free Software Foundation, Inc.,
20
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
#include <linux/init.h>
28
#include <linux/device.h>
29
#include <linux/slab.h>
31
#include <linux/module.h>
32
#include <sound/pcm.h>
33
#include <sound/pcm_params.h>
34
#include <sound/soc.h>
35
#include <sound/jack.h>
36
#include "../codecs/sn95031.h"
41
#define MFLD_JACK_INSERT 0x04
43
enum soc_mic_bias_zones {
45
/* mic bias volutage range for Headphones*/
47
/* mic bias volutage range for American Headset*/
49
/* mic bias volutage range for Headset*/
54
static unsigned int hs_switch;
55
static unsigned int lo_dac;
57
struct mfld_mc_private {
58
void __iomem *int_base;
62
struct snd_soc_jack mfld_jack;
64
/*Headset jack detection DAPM pins */
65
static struct snd_soc_jack_pin mfld_jack_pins[] = {
68
.mask = SND_JACK_HEADPHONE,
72
.mask = SND_JACK_MICROPHONE,
76
/* jack detection voltage zones */
77
static struct snd_soc_jack_zone mfld_zones[] = {
78
{MFLD_MV_START, MFLD_MV_AM_HS, SND_JACK_HEADPHONE},
79
{MFLD_MV_AM_HS, MFLD_MV_HS, SND_JACK_HEADSET},
82
/* sound card controls */
83
static const char *headset_switch_text[] = {"Earpiece", "Headset"};
85
static const char *lo_text[] = {"Vibra", "Headset", "IHF", "None"};
87
static const struct soc_enum headset_enum =
88
SOC_ENUM_SINGLE_EXT(2, headset_switch_text);
90
static const struct soc_enum lo_enum =
91
SOC_ENUM_SINGLE_EXT(4, lo_text);
93
static int headset_get_switch(struct snd_kcontrol *kcontrol,
94
struct snd_ctl_elem_value *ucontrol)
96
ucontrol->value.integer.value[0] = hs_switch;
100
static int headset_set_switch(struct snd_kcontrol *kcontrol,
101
struct snd_ctl_elem_value *ucontrol)
103
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
105
if (ucontrol->value.integer.value[0] == hs_switch)
108
if (ucontrol->value.integer.value[0]) {
109
pr_debug("hs_set HS path\n");
110
snd_soc_dapm_enable_pin(&codec->dapm, "Headphones");
111
snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
113
pr_debug("hs_set EP path\n");
114
snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
115
snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT");
117
snd_soc_dapm_sync(&codec->dapm);
118
hs_switch = ucontrol->value.integer.value[0];
123
static void lo_enable_out_pins(struct snd_soc_codec *codec)
125
snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL");
126
snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR");
127
snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL");
128
snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR");
129
snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT");
130
snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT");
132
snd_soc_dapm_enable_pin(&codec->dapm, "Headphones");
133
snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
135
snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
136
snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT");
140
static int lo_get_switch(struct snd_kcontrol *kcontrol,
141
struct snd_ctl_elem_value *ucontrol)
143
ucontrol->value.integer.value[0] = lo_dac;
147
static int lo_set_switch(struct snd_kcontrol *kcontrol,
148
struct snd_ctl_elem_value *ucontrol)
150
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
152
if (ucontrol->value.integer.value[0] == lo_dac)
155
/* we dont want to work with last state of lineout so just enable all
156
* pins and then disable pins not required
158
lo_enable_out_pins(codec);
159
switch (ucontrol->value.integer.value[0]) {
161
pr_debug("set vibra path\n");
162
snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT");
163
snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT");
164
snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0);
168
pr_debug("set hs path\n");
169
snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
170
snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
171
snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22);
175
pr_debug("set spkr path\n");
176
snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL");
177
snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR");
178
snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44);
182
pr_debug("set null path\n");
183
snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL");
184
snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR");
185
snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66);
188
snd_soc_dapm_sync(&codec->dapm);
189
lo_dac = ucontrol->value.integer.value[0];
193
static const struct snd_kcontrol_new mfld_snd_controls[] = {
194
SOC_ENUM_EXT("Playback Switch", headset_enum,
195
headset_get_switch, headset_set_switch),
196
SOC_ENUM_EXT("Lineout Mux", lo_enum,
197
lo_get_switch, lo_set_switch),
200
static const struct snd_soc_dapm_widget mfld_widgets[] = {
201
SND_SOC_DAPM_HP("Headphones", NULL),
202
SND_SOC_DAPM_MIC("Mic", NULL),
205
static const struct snd_soc_dapm_route mfld_map[] = {
206
{"Headphones", NULL, "HPOUTR"},
207
{"Headphones", NULL, "HPOUTL"},
208
{"Mic", NULL, "AMIC1"},
211
static void mfld_jack_check(unsigned int intr_status)
213
struct mfld_jack_data jack_data;
215
jack_data.mfld_jack = &mfld_jack;
216
jack_data.intr_id = intr_status;
218
sn95031_jack_detection(&jack_data);
219
/* TODO: add american headset detection post gpiolib support */
222
static int mfld_init(struct snd_soc_pcm_runtime *runtime)
224
struct snd_soc_codec *codec = runtime->codec;
225
struct snd_soc_dapm_context *dapm = &codec->dapm;
228
/* Add jack sense widgets */
229
snd_soc_dapm_new_controls(dapm, mfld_widgets, ARRAY_SIZE(mfld_widgets));
232
snd_soc_dapm_add_routes(dapm, mfld_map, ARRAY_SIZE(mfld_map));
234
/* always connected */
235
snd_soc_dapm_enable_pin(dapm, "Headphones");
236
snd_soc_dapm_enable_pin(dapm, "Mic");
238
ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
239
ARRAY_SIZE(mfld_snd_controls));
241
pr_err("soc_add_controls failed %d", ret_val);
244
/* default is earpiece pin, userspace sets it explcitly */
245
snd_soc_dapm_disable_pin(dapm, "Headphones");
246
/* default is lineout NC, userspace sets it explcitly */
247
snd_soc_dapm_disable_pin(dapm, "LINEOUTL");
248
snd_soc_dapm_disable_pin(dapm, "LINEOUTR");
251
/* we dont use linein in this so set to NC */
252
snd_soc_dapm_disable_pin(dapm, "LINEINL");
253
snd_soc_dapm_disable_pin(dapm, "LINEINR");
255
/* Headset and button jack detection */
256
ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack",
257
SND_JACK_HEADSET | SND_JACK_BTN_0 |
258
SND_JACK_BTN_1, &mfld_jack);
260
pr_err("jack creation failed\n");
264
ret_val = snd_soc_jack_add_pins(&mfld_jack,
265
ARRAY_SIZE(mfld_jack_pins), mfld_jack_pins);
267
pr_err("adding jack pins failed\n");
270
ret_val = snd_soc_jack_add_zones(&mfld_jack,
271
ARRAY_SIZE(mfld_zones), mfld_zones);
273
pr_err("adding jack zones failed\n");
277
/* we want to check if anything is inserted at boot,
278
* so send a fake event to codec and it will read adc
279
* to find if anything is there or not */
280
mfld_jack_check(MFLD_JACK_INSERT);
284
struct snd_soc_dai_link mfld_msic_dailink[] = {
286
.name = "Medfield Headset",
287
.stream_name = "Headset",
288
.cpu_dai_name = "Headset-cpu-dai",
289
.codec_dai_name = "SN95031 Headset",
290
.codec_name = "sn95031",
291
.platform_name = "sst-platform",
295
.name = "Medfield Speaker",
296
.stream_name = "Speaker",
297
.cpu_dai_name = "Speaker-cpu-dai",
298
.codec_dai_name = "SN95031 Speaker",
299
.codec_name = "sn95031",
300
.platform_name = "sst-platform",
304
.name = "Medfield Vibra",
305
.stream_name = "Vibra1",
306
.cpu_dai_name = "Vibra1-cpu-dai",
307
.codec_dai_name = "SN95031 Vibra1",
308
.codec_name = "sn95031",
309
.platform_name = "sst-platform",
313
.name = "Medfield Haptics",
314
.stream_name = "Vibra2",
315
.cpu_dai_name = "Vibra2-cpu-dai",
316
.codec_dai_name = "SN95031 Vibra2",
317
.codec_name = "sn95031",
318
.platform_name = "sst-platform",
324
static struct snd_soc_card snd_soc_card_mfld = {
325
.name = "medfield_audio",
326
.dai_link = mfld_msic_dailink,
327
.num_links = ARRAY_SIZE(mfld_msic_dailink),
330
static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev)
332
struct mfld_mc_private *mc_private = (struct mfld_mc_private *) dev;
334
memcpy_fromio(&mc_private->interrupt_status,
335
((void *)(mc_private->int_base)),
337
return IRQ_WAKE_THREAD;
340
static irqreturn_t snd_mfld_jack_detection(int irq, void *data)
342
struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data;
344
if (mfld_jack.codec == NULL)
346
mfld_jack_check(mc_drv_ctx->interrupt_status);
351
static int __devinit snd_mfld_mc_probe(struct platform_device *pdev)
353
int ret_val = 0, irq;
354
struct mfld_mc_private *mc_drv_ctx;
355
struct resource *irq_mem;
357
pr_debug("snd_mfld_mc_probe called\n");
359
/* retrive the irq number */
360
irq = platform_get_irq(pdev, 0);
362
/* audio interrupt base of SRAM location where
363
* interrupts are stored by System FW */
364
mc_drv_ctx = kzalloc(sizeof(*mc_drv_ctx), GFP_ATOMIC);
366
pr_err("allocation failed\n");
370
irq_mem = platform_get_resource_byname(
371
pdev, IORESOURCE_MEM, "IRQ_BASE");
373
pr_err("no mem resource given\n");
377
mc_drv_ctx->int_base = ioremap_nocache(irq_mem->start,
378
resource_size(irq_mem));
379
if (!mc_drv_ctx->int_base) {
380
pr_err("Mapping of cache failed\n");
384
/* register for interrupt */
385
ret_val = request_threaded_irq(irq, snd_mfld_jack_intr_handler,
386
snd_mfld_jack_detection,
387
IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx);
389
pr_err("cannot register IRQ\n");
392
/* register the soc card */
393
snd_soc_card_mfld.dev = &pdev->dev;
394
ret_val = snd_soc_register_card(&snd_soc_card_mfld);
396
pr_debug("snd_soc_register_card failed %d\n", ret_val);
399
platform_set_drvdata(pdev, mc_drv_ctx);
400
pr_debug("successfully exited probe\n");
404
free_irq(irq, mc_drv_ctx);
410
static int __devexit snd_mfld_mc_remove(struct platform_device *pdev)
412
struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev);
414
pr_debug("snd_mfld_mc_remove called\n");
415
free_irq(platform_get_irq(pdev, 0), mc_drv_ctx);
416
snd_soc_unregister_card(&snd_soc_card_mfld);
418
platform_set_drvdata(pdev, NULL);
422
static struct platform_driver snd_mfld_mc_driver = {
424
.owner = THIS_MODULE,
425
.name = "msic_audio",
427
.probe = snd_mfld_mc_probe,
428
.remove = __devexit_p(snd_mfld_mc_remove),
431
static int __init snd_mfld_driver_init(void)
433
pr_debug("snd_mfld_driver_init called\n");
434
return platform_driver_register(&snd_mfld_mc_driver);
436
module_init(snd_mfld_driver_init);
438
static void __exit snd_mfld_driver_exit(void)
440
pr_debug("snd_mfld_driver_exit called\n");
441
platform_driver_unregister(&snd_mfld_mc_driver);
443
module_exit(snd_mfld_driver_exit);
445
MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver");
446
MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
447
MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
448
MODULE_LICENSE("GPL v2");
449
MODULE_ALIAS("platform:msic-audio");