Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/samsung/midas_wm1811.c
26428 views
1
// SPDX-License-Identifier: GPL-2.0+
2
//
3
// Midas audio support
4
//
5
// Copyright (C) 2018 Simon Shields <[email protected]>
6
// Copyright (C) 2020 Samsung Electronics Co., Ltd.
7
8
#include <linux/clk.h>
9
#include <linux/gpio/consumer.h>
10
#include <linux/iio/consumer.h>
11
#include <linux/mfd/wm8994/registers.h>
12
#include <linux/input-event-codes.h>
13
#include <linux/module.h>
14
#include <linux/of.h>
15
#include <sound/jack.h>
16
#include <sound/soc.h>
17
#include <sound/soc-dapm.h>
18
19
#include "i2s.h"
20
#include "../codecs/wm8994.h"
21
22
/*
23
* The MCLK1 clock source is XCLKOUT with its mux set to the external fixed rate
24
* oscillator (XXTI).
25
*/
26
#define MCLK1_RATE 24000000U
27
#define MCLK2_RATE 32768U
28
#define DEFAULT_FLL1_RATE 11289600U
29
30
struct midas_priv {
31
struct gpio_desc *gpio_fm_sel;
32
struct gpio_desc *gpio_lineout_sel;
33
struct gpio_desc *gpio_headset_detect;
34
struct gpio_desc *gpio_headset_key;
35
struct iio_channel *adc_headset_detect;
36
unsigned int fll1_rate;
37
38
struct snd_soc_jack headset_jack;
39
};
40
41
static struct snd_soc_jack_pin headset_jack_pins[] = {
42
{
43
.pin = "Headphone",
44
.mask = SND_JACK_HEADPHONE,
45
},
46
{
47
.pin = "Headset Mic",
48
.mask = SND_JACK_MICROPHONE,
49
},
50
};
51
52
/*
53
* min_mv/max_mv values in this struct are set up based on DT values.
54
*/
55
static struct snd_soc_jack_zone headset_jack_zones[] = {
56
{ .jack_type = SND_JACK_HEADPHONE, },
57
{ .jack_type = SND_JACK_HEADSET, },
58
{ .jack_type = SND_JACK_HEADPHONE, },
59
};
60
61
/*
62
* This is used for manual detection in headset_key_check, we reuse the
63
* structure since it's convenient.
64
*
65
* min_mv/max_mv values in this struct are set up based on DT values.
66
*/
67
static struct snd_soc_jack_zone headset_key_zones[] = {
68
{ .jack_type = SND_JACK_BTN_0, }, /* Media */
69
{ .jack_type = SND_JACK_BTN_1, }, /* Volume Up */
70
{ .jack_type = SND_JACK_BTN_2, }, /* Volume Down */
71
};
72
73
static int headset_jack_check(void *data)
74
{
75
struct snd_soc_component *codec = data;
76
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
77
struct midas_priv *priv = snd_soc_card_get_drvdata(codec->card);
78
int adc, ret;
79
int jack_type = 0;
80
81
if (!gpiod_get_value_cansleep(priv->gpio_headset_detect))
82
return 0;
83
84
/* Enable headset mic bias regulator so that the ADC reading works */
85
ret = snd_soc_dapm_force_enable_pin(dapm, "headset-mic-bias");
86
if (ret < 0) {
87
pr_err("%s: Failed to enable headset mic bias regulator (%d), assuming headphones\n",
88
__func__, ret);
89
return SND_JACK_HEADPHONE;
90
}
91
snd_soc_dapm_sync(dapm);
92
93
/* Sleep for a small amount of time to get the value to stabilize */
94
msleep(20);
95
96
ret = iio_read_channel_processed(priv->adc_headset_detect, &adc);
97
if (ret) {
98
pr_err("%s: Failed to read ADC (%d), assuming headphones\n",
99
__func__, ret);
100
jack_type = SND_JACK_HEADPHONE;
101
goto out;
102
}
103
pr_debug("%s: ADC value is %d\n", __func__, adc);
104
105
jack_type = snd_soc_jack_get_type(&priv->headset_jack, adc);
106
107
out:
108
ret = snd_soc_dapm_disable_pin(dapm, "headset-mic-bias");
109
if (ret < 0)
110
pr_err("%s: Failed to disable headset mic bias regulator (%d)\n",
111
__func__, ret);
112
snd_soc_dapm_sync(dapm);
113
114
return jack_type;
115
}
116
117
static int headset_key_check(void *data)
118
{
119
struct snd_soc_component *codec = data;
120
struct midas_priv *priv = snd_soc_card_get_drvdata(codec->card);
121
int adc, i, ret;
122
123
if (!gpiod_get_value_cansleep(priv->gpio_headset_key))
124
return 0;
125
126
/* Filter out keypresses when 4 pole jack not detected */
127
if (!(priv->headset_jack.status & SND_JACK_MICROPHONE))
128
return 0;
129
130
ret = iio_read_channel_processed(priv->adc_headset_detect, &adc);
131
if (ret) {
132
pr_err("%s: Failed to read ADC (%d), can't detect key type\n",
133
__func__, ret);
134
return 0;
135
}
136
pr_debug("%s: ADC value is %d\n", __func__, adc);
137
138
for (i = 0; i < ARRAY_SIZE(headset_key_zones); i++) {
139
if (adc >= headset_key_zones[i].min_mv &&
140
adc <= headset_key_zones[i].max_mv) {
141
return headset_key_zones[i].jack_type;
142
}
143
}
144
145
return 0;
146
}
147
148
static struct snd_soc_jack_gpio headset_gpio[] = {
149
{
150
.name = "Headset Jack",
151
.report = SND_JACK_HEADSET,
152
.debounce_time = 150,
153
.jack_status_check = headset_jack_check,
154
},
155
{
156
.name = "Headset Key",
157
.report = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
158
.debounce_time = 30,
159
.jack_status_check = headset_key_check,
160
},
161
};
162
163
static int midas_start_fll1(struct snd_soc_pcm_runtime *rtd, unsigned int rate)
164
{
165
struct snd_soc_card *card = rtd->card;
166
struct midas_priv *priv = snd_soc_card_get_drvdata(card);
167
struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
168
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
169
int ret;
170
171
if (!rate)
172
rate = priv->fll1_rate;
173
/*
174
* If no new rate is requested, set FLL1 to a sane default for jack
175
* detection.
176
*/
177
if (!rate)
178
rate = DEFAULT_FLL1_RATE;
179
180
if (rate != priv->fll1_rate && priv->fll1_rate) {
181
/* while reconfiguring, switch to MCLK2 for SYSCLK */
182
ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
183
MCLK2_RATE, SND_SOC_CLOCK_IN);
184
if (ret < 0) {
185
dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret);
186
return ret;
187
}
188
}
189
190
ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
191
MCLK1_RATE, rate);
192
if (ret < 0) {
193
dev_err(card->dev, "Failed to set FLL1 rate: %d\n", ret);
194
return ret;
195
}
196
priv->fll1_rate = rate;
197
198
ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_FLL1,
199
priv->fll1_rate, SND_SOC_CLOCK_IN);
200
if (ret < 0) {
201
dev_err(card->dev, "Failed to set SYSCLK source: %d\n", ret);
202
return ret;
203
}
204
205
ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK, 0,
206
SAMSUNG_I2S_OPCLK_PCLK);
207
if (ret < 0) {
208
dev_err(card->dev, "Failed to set OPCLK source: %d\n", ret);
209
return ret;
210
}
211
212
return 0;
213
}
214
215
static int midas_stop_fll1(struct snd_soc_pcm_runtime *rtd)
216
{
217
struct snd_soc_card *card = rtd->card;
218
struct midas_priv *priv = snd_soc_card_get_drvdata(card);
219
struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
220
int ret;
221
222
ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
223
MCLK2_RATE, SND_SOC_CLOCK_IN);
224
if (ret < 0) {
225
dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret);
226
return ret;
227
}
228
229
ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, 0, 0, 0);
230
if (ret < 0) {
231
dev_err(card->dev, "Unable to stop FLL1: %d\n", ret);
232
return ret;
233
}
234
235
priv->fll1_rate = 0;
236
237
return 0;
238
}
239
240
static int midas_aif1_hw_params(struct snd_pcm_substream *substream,
241
struct snd_pcm_hw_params *params)
242
{
243
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
244
unsigned int pll_out;
245
246
/* AIF1CLK should be at least 3MHz for "optimal performance" */
247
if (params_rate(params) == 8000 || params_rate(params) == 11025)
248
pll_out = params_rate(params) * 512;
249
else
250
pll_out = params_rate(params) * 256;
251
252
return midas_start_fll1(rtd, pll_out);
253
}
254
255
static const struct snd_soc_ops midas_aif1_ops = {
256
.hw_params = midas_aif1_hw_params,
257
};
258
259
/*
260
* We only have a single external speaker, so mix stereo data
261
* to a single mono stream.
262
*/
263
static int midas_ext_spkmode(struct snd_soc_dapm_widget *w,
264
struct snd_kcontrol *kcontrol, int event)
265
{
266
struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
267
int ret = 0;
268
269
switch (event) {
270
case SND_SOC_DAPM_PRE_PMU:
271
ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS,
272
WM8994_SPKMIXR_TO_SPKOUTL_MASK,
273
WM8994_SPKMIXR_TO_SPKOUTL);
274
break;
275
case SND_SOC_DAPM_POST_PMD:
276
ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS,
277
WM8994_SPKMIXR_TO_SPKOUTL_MASK,
278
0);
279
break;
280
}
281
282
return ret;
283
}
284
285
static int midas_fm_set(struct snd_soc_dapm_widget *w,
286
struct snd_kcontrol *kcontrol, int event)
287
{
288
struct snd_soc_card *card = w->dapm->card;
289
struct midas_priv *priv = snd_soc_card_get_drvdata(card);
290
291
if (!priv->gpio_fm_sel)
292
return 0;
293
294
switch (event) {
295
case SND_SOC_DAPM_PRE_PMU:
296
gpiod_set_value_cansleep(priv->gpio_fm_sel, 1);
297
break;
298
case SND_SOC_DAPM_POST_PMD:
299
gpiod_set_value_cansleep(priv->gpio_fm_sel, 0);
300
break;
301
}
302
303
return 0;
304
}
305
306
static int midas_line_set(struct snd_soc_dapm_widget *w,
307
struct snd_kcontrol *kcontrol, int event)
308
{
309
struct snd_soc_card *card = w->dapm->card;
310
struct midas_priv *priv = snd_soc_card_get_drvdata(card);
311
312
if (!priv->gpio_lineout_sel)
313
return 0;
314
315
switch (event) {
316
case SND_SOC_DAPM_PRE_PMU:
317
gpiod_set_value_cansleep(priv->gpio_lineout_sel, 1);
318
break;
319
case SND_SOC_DAPM_POST_PMD:
320
gpiod_set_value_cansleep(priv->gpio_lineout_sel, 0);
321
break;
322
}
323
324
return 0;
325
}
326
327
static const struct snd_kcontrol_new midas_controls[] = {
328
SOC_DAPM_PIN_SWITCH("HP"),
329
330
SOC_DAPM_PIN_SWITCH("SPK"),
331
SOC_DAPM_PIN_SWITCH("RCV"),
332
333
SOC_DAPM_PIN_SWITCH("LINE"),
334
SOC_DAPM_PIN_SWITCH("HDMI"),
335
336
SOC_DAPM_PIN_SWITCH("Main Mic"),
337
SOC_DAPM_PIN_SWITCH("Sub Mic"),
338
SOC_DAPM_PIN_SWITCH("Headset Mic"),
339
340
SOC_DAPM_PIN_SWITCH("FM In"),
341
};
342
343
static const struct snd_soc_dapm_widget midas_dapm_widgets[] = {
344
SND_SOC_DAPM_HP("HP", NULL),
345
346
SND_SOC_DAPM_SPK("SPK", midas_ext_spkmode),
347
SND_SOC_DAPM_SPK("RCV", NULL),
348
349
/* FIXME: toggle MAX77693 on i9300/i9305 */
350
SND_SOC_DAPM_LINE("LINE", midas_line_set),
351
SND_SOC_DAPM_LINE("HDMI", NULL),
352
SND_SOC_DAPM_LINE("FM In", midas_fm_set),
353
354
SND_SOC_DAPM_HP("Headphone", NULL),
355
SND_SOC_DAPM_MIC("Headset Mic", NULL),
356
SND_SOC_DAPM_REGULATOR_SUPPLY("headset-mic-bias", 0, 0),
357
SND_SOC_DAPM_MIC("Main Mic", NULL),
358
SND_SOC_DAPM_REGULATOR_SUPPLY("mic-bias", 0, 0),
359
SND_SOC_DAPM_MIC("Sub Mic", NULL),
360
SND_SOC_DAPM_REGULATOR_SUPPLY("submic-bias", 0, 0),
361
};
362
363
/* Default routing; supplemented by audio-routing DT property */
364
static const struct snd_soc_dapm_route midas_dapm_routes[] = {
365
/* Bind microphones with their respective regulator supplies */
366
{"Main Mic", NULL, "mic-bias"},
367
{"Sub Mic", NULL, "submic-bias"},
368
{"Headset Mic", NULL, "headset-mic-bias"},
369
};
370
371
static int midas_set_bias_level(struct snd_soc_card *card,
372
struct snd_soc_dapm_context *dapm,
373
enum snd_soc_bias_level level)
374
{
375
struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card,
376
&card->dai_link[0]);
377
struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
378
379
if (dapm->dev != aif1_dai->dev)
380
return 0;
381
382
switch (level) {
383
case SND_SOC_BIAS_STANDBY:
384
return midas_stop_fll1(rtd);
385
case SND_SOC_BIAS_PREPARE:
386
return midas_start_fll1(rtd, 0);
387
default:
388
break;
389
}
390
391
return 0;
392
}
393
394
static int midas_late_probe(struct snd_soc_card *card)
395
{
396
struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card,
397
&card->dai_link[0]);
398
struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
399
struct midas_priv *priv = snd_soc_card_get_drvdata(card);
400
int ret;
401
402
/* Use MCLK2 as SYSCLK for boot */
403
ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, MCLK2_RATE,
404
SND_SOC_CLOCK_IN);
405
if (ret < 0) {
406
dev_err(aif1_dai->dev, "Failed to switch to MCLK2: %d\n", ret);
407
return ret;
408
}
409
410
if (!priv->gpio_headset_detect) {
411
ret = snd_soc_card_jack_new_pins(card, "Headset",
412
SND_JACK_HEADSET | SND_JACK_MECHANICAL |
413
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
414
SND_JACK_BTN_2 | SND_JACK_BTN_3 |
415
SND_JACK_BTN_4 | SND_JACK_BTN_5,
416
&priv->headset_jack,
417
headset_jack_pins,
418
ARRAY_SIZE(headset_jack_pins));
419
if (ret)
420
return ret;
421
422
wm8958_mic_detect(aif1_dai->component, &priv->headset_jack,
423
NULL, NULL, NULL, NULL);
424
} else {
425
/* Some devices (n8000, t310) use a GPIO to detect the jack. */
426
ret = snd_soc_card_jack_new_pins(card, "Headset",
427
SND_JACK_HEADSET | SND_JACK_BTN_0 |
428
SND_JACK_BTN_1 | SND_JACK_BTN_2,
429
&priv->headset_jack,
430
headset_jack_pins,
431
ARRAY_SIZE(headset_jack_pins));
432
if (ret) {
433
dev_err(card->dev,
434
"Failed to set up headset pins: %d\n", ret);
435
return ret;
436
}
437
438
ret = snd_soc_jack_add_zones(&priv->headset_jack,
439
ARRAY_SIZE(headset_jack_zones),
440
headset_jack_zones);
441
if (ret) {
442
dev_err(card->dev,
443
"Failed to set up headset zones: %d\n", ret);
444
return ret;
445
}
446
447
headset_gpio[0].data = aif1_dai->component;
448
headset_gpio[0].desc = priv->gpio_headset_detect;
449
450
headset_gpio[1].data = aif1_dai->component;
451
headset_gpio[1].desc = priv->gpio_headset_key;
452
453
snd_jack_set_key(priv->headset_jack.jack,
454
SND_JACK_BTN_0, KEY_MEDIA);
455
snd_jack_set_key(priv->headset_jack.jack,
456
SND_JACK_BTN_1, KEY_VOLUMEUP);
457
snd_jack_set_key(priv->headset_jack.jack,
458
SND_JACK_BTN_2, KEY_VOLUMEDOWN);
459
460
ret = snd_soc_jack_add_gpios(&priv->headset_jack,
461
ARRAY_SIZE(headset_gpio),
462
headset_gpio);
463
if (ret)
464
dev_err(card->dev,
465
"Failed to set up headset jack GPIOs: %d\n",
466
ret);
467
468
return ret;
469
}
470
471
return 0;
472
}
473
474
static struct snd_soc_dai_driver midas_ext_dai[] = {
475
{
476
.name = "Voice call",
477
.playback = {
478
.channels_min = 1,
479
.channels_max = 2,
480
.rate_min = 8000,
481
.rate_max = 16000,
482
.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
483
.formats = SNDRV_PCM_FMTBIT_S16_LE,
484
},
485
.capture = {
486
.channels_min = 1,
487
.channels_max = 2,
488
.rate_min = 8000,
489
.rate_max = 16000,
490
.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
491
.formats = SNDRV_PCM_FMTBIT_S16_LE,
492
},
493
},
494
{
495
.name = "Bluetooth",
496
.playback = {
497
.channels_min = 1,
498
.channels_max = 2,
499
.rate_min = 8000,
500
.rate_max = 16000,
501
.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
502
.formats = SNDRV_PCM_FMTBIT_S16_LE,
503
},
504
.capture = {
505
.channels_min = 1,
506
.channels_max = 2,
507
.rate_min = 8000,
508
.rate_max = 16000,
509
.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
510
.formats = SNDRV_PCM_FMTBIT_S16_LE,
511
},
512
},
513
};
514
515
static const struct snd_soc_component_driver midas_component = {
516
.name = "midas-audio",
517
};
518
519
SND_SOC_DAILINK_DEFS(wm1811_hifi,
520
DAILINK_COMP_ARRAY(COMP_EMPTY()),
521
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")),
522
DAILINK_COMP_ARRAY(COMP_EMPTY()));
523
524
SND_SOC_DAILINK_DEFS(wm1811_voice,
525
DAILINK_COMP_ARRAY(COMP_EMPTY()),
526
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif2")),
527
DAILINK_COMP_ARRAY(COMP_EMPTY()));
528
529
SND_SOC_DAILINK_DEFS(wm1811_bt,
530
DAILINK_COMP_ARRAY(COMP_EMPTY()),
531
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif3")),
532
DAILINK_COMP_ARRAY(COMP_EMPTY()));
533
534
static struct snd_soc_dai_link midas_dai[] = {
535
{
536
.name = "WM8994 AIF1",
537
.stream_name = "HiFi Primary",
538
.ops = &midas_aif1_ops,
539
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
540
SND_SOC_DAIFMT_CBP_CFP,
541
SND_SOC_DAILINK_REG(wm1811_hifi),
542
}, {
543
.name = "WM1811 Voice",
544
.stream_name = "Voice call",
545
.ignore_suspend = 1,
546
SND_SOC_DAILINK_REG(wm1811_voice),
547
}, {
548
.name = "WM1811 BT",
549
.stream_name = "Bluetooth",
550
.ignore_suspend = 1,
551
SND_SOC_DAILINK_REG(wm1811_bt),
552
},
553
};
554
555
static struct snd_soc_card midas_card = {
556
.name = "Midas WM1811",
557
.owner = THIS_MODULE,
558
559
.dai_link = midas_dai,
560
.num_links = ARRAY_SIZE(midas_dai),
561
.controls = midas_controls,
562
.num_controls = ARRAY_SIZE(midas_controls),
563
.dapm_widgets = midas_dapm_widgets,
564
.num_dapm_widgets = ARRAY_SIZE(midas_dapm_widgets),
565
.dapm_routes = midas_dapm_routes,
566
.num_dapm_routes = ARRAY_SIZE(midas_dapm_routes),
567
568
.set_bias_level = midas_set_bias_level,
569
.late_probe = midas_late_probe,
570
};
571
572
static int midas_probe(struct platform_device *pdev)
573
{
574
struct device_node *cpu_dai_node = NULL, *codec_dai_node = NULL;
575
struct device_node *cpu = NULL, *codec = NULL;
576
struct snd_soc_card *card = &midas_card;
577
struct device *dev = &pdev->dev;
578
static struct snd_soc_dai_link *dai_link;
579
enum iio_chan_type channel_type;
580
u32 fourpole_threshold[2];
581
u32 button_threshold[3];
582
struct midas_priv *priv;
583
int ret, i;
584
585
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
586
if (!priv)
587
return -ENOMEM;
588
589
snd_soc_card_set_drvdata(card, priv);
590
card->dev = dev;
591
592
priv->gpio_fm_sel = devm_gpiod_get_optional(dev, "fm-sel", GPIOD_OUT_HIGH);
593
if (IS_ERR(priv->gpio_fm_sel))
594
return dev_err_probe(dev, PTR_ERR(priv->gpio_fm_sel),
595
"Failed to get FM selection GPIO\n");
596
597
priv->gpio_lineout_sel = devm_gpiod_get_optional(dev, "lineout-sel",
598
GPIOD_OUT_HIGH);
599
if (IS_ERR(priv->gpio_lineout_sel))
600
return dev_err_probe(dev, PTR_ERR(priv->gpio_lineout_sel),
601
"Failed to get line out selection GPIO\n");
602
603
priv->gpio_headset_detect = devm_gpiod_get_optional(dev,
604
"headset-detect", GPIOD_IN);
605
if (IS_ERR(priv->gpio_headset_detect))
606
return dev_err_probe(dev, PTR_ERR(priv->gpio_headset_detect),
607
"Failed to get headset jack detect GPIO\n");
608
609
if (priv->gpio_headset_detect) {
610
priv->adc_headset_detect = devm_iio_channel_get(dev,
611
"headset-detect");
612
if (IS_ERR(priv->adc_headset_detect))
613
return dev_err_probe(dev,
614
PTR_ERR(priv->adc_headset_detect),
615
"Failed to get ADC channel\n");
616
617
ret = iio_get_channel_type(priv->adc_headset_detect,
618
&channel_type);
619
if (ret) {
620
dev_err(dev, "Failed to get ADC channel type\n");
621
return ret;
622
}
623
624
if (channel_type != IIO_VOLTAGE) {
625
dev_err(dev, "ADC channel is not voltage\n");
626
return -EINVAL;
627
}
628
629
priv->gpio_headset_key = devm_gpiod_get(dev, "headset-key",
630
GPIOD_IN);
631
if (IS_ERR(priv->gpio_headset_key))
632
return dev_err_probe(dev,
633
PTR_ERR(priv->gpio_headset_key),
634
"Failed to get headset key GPIO\n");
635
636
ret = of_property_read_u32_array(dev->of_node,
637
"samsung,headset-4pole-threshold-microvolt",
638
fourpole_threshold,
639
ARRAY_SIZE(fourpole_threshold));
640
if (ret) {
641
dev_err(dev, "Failed to get 4-pole jack detection threshold\n");
642
return ret;
643
}
644
645
if (fourpole_threshold[0] > fourpole_threshold[1]) {
646
dev_err(dev, "Invalid 4-pole jack detection threshold value\n");
647
return -EINVAL;
648
}
649
650
headset_jack_zones[0].max_mv = (fourpole_threshold[0]);
651
headset_jack_zones[1].min_mv = (fourpole_threshold[0] + 1);
652
653
headset_jack_zones[1].max_mv = (fourpole_threshold[1]);
654
headset_jack_zones[2].min_mv = (fourpole_threshold[1] + 1);
655
656
ret = of_property_read_u32_array(dev->of_node,
657
"samsung,headset-button-threshold-microvolt",
658
button_threshold,
659
ARRAY_SIZE(button_threshold));
660
if (ret) {
661
dev_err(dev, "Failed to get headset button detection threshold\n");
662
return ret;
663
}
664
665
if (button_threshold[0] > button_threshold[1] ||
666
button_threshold[1] > button_threshold[2]) {
667
dev_err(dev, "Invalid headset button detection threshold value\n");
668
return -EINVAL;
669
}
670
671
for (i = 0; i < 3; i++) {
672
if (i != 0 && button_threshold[i] <= 0) {
673
dev_err(dev, "Invalid headset button detection threshold value\n");
674
return -EINVAL;
675
}
676
677
headset_key_zones[i].min_mv = button_threshold[i];
678
679
if (i == 2)
680
headset_key_zones[i].max_mv = UINT_MAX;
681
else
682
headset_key_zones[i].max_mv = \
683
(button_threshold[i+1] - 1);
684
}
685
}
686
687
ret = snd_soc_of_parse_card_name(card, "model");
688
if (ret < 0) {
689
dev_err(dev, "Card name is not specified\n");
690
return ret;
691
}
692
693
ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
694
if (ret < 0) {
695
/* Backwards compatible way */
696
ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
697
if (ret < 0) {
698
dev_err(dev, "Audio routing invalid/unspecified\n");
699
return ret;
700
}
701
}
702
703
cpu = of_get_child_by_name(dev->of_node, "cpu");
704
if (!cpu)
705
return -EINVAL;
706
707
codec = of_get_child_by_name(dev->of_node, "codec");
708
if (!codec) {
709
of_node_put(cpu);
710
return -EINVAL;
711
}
712
713
cpu_dai_node = of_parse_phandle(cpu, "sound-dai", 0);
714
of_node_put(cpu);
715
if (!cpu_dai_node) {
716
dev_err(dev, "parsing cpu/sound-dai failed\n");
717
of_node_put(codec);
718
return -EINVAL;
719
}
720
721
codec_dai_node = of_parse_phandle(codec, "sound-dai", 0);
722
of_node_put(codec);
723
if (!codec_dai_node) {
724
dev_err(dev, "audio-codec property invalid/missing\n");
725
ret = -EINVAL;
726
goto put_cpu_dai_node;
727
}
728
729
for_each_card_prelinks(card, i, dai_link) {
730
dai_link->codecs->of_node = codec_dai_node;
731
dai_link->cpus->of_node = cpu_dai_node;
732
dai_link->platforms->of_node = cpu_dai_node;
733
}
734
735
ret = devm_snd_soc_register_component(dev, &midas_component,
736
midas_ext_dai, ARRAY_SIZE(midas_ext_dai));
737
if (ret < 0) {
738
dev_err(dev, "Failed to register component: %d\n", ret);
739
goto put_codec_dai_node;
740
}
741
742
ret = devm_snd_soc_register_card(dev, card);
743
if (ret < 0) {
744
dev_err(dev, "Failed to register card: %d\n", ret);
745
goto put_codec_dai_node;
746
}
747
748
return 0;
749
750
put_codec_dai_node:
751
of_node_put(codec_dai_node);
752
put_cpu_dai_node:
753
of_node_put(cpu_dai_node);
754
return ret;
755
}
756
757
static const struct of_device_id midas_of_match[] = {
758
{ .compatible = "samsung,midas-audio" },
759
{ },
760
};
761
MODULE_DEVICE_TABLE(of, midas_of_match);
762
763
static struct platform_driver midas_driver = {
764
.driver = {
765
.name = "midas-audio",
766
.of_match_table = midas_of_match,
767
.pm = &snd_soc_pm_ops,
768
},
769
.probe = midas_probe,
770
};
771
module_platform_driver(midas_driver);
772
773
MODULE_AUTHOR("Simon Shields <[email protected]>");
774
MODULE_DESCRIPTION("ASoC support for Midas");
775
MODULE_LICENSE("GPL v2");
776
777