Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
26488 views
1
// SPDX-License-Identifier: GPL-2.0
2
//
3
// mt8183-da7219-max98357.c
4
// -- MT8183-DA7219-MAX98357 ALSA SoC machine driver
5
//
6
// Copyright (c) 2018 MediaTek Inc.
7
// Author: Shunli Wang <[email protected]>
8
9
#include <linux/input.h>
10
#include <linux/module.h>
11
#include <linux/of.h>
12
#include <linux/pinctrl/consumer.h>
13
#include <sound/jack.h>
14
#include <sound/pcm_params.h>
15
#include <sound/soc.h>
16
17
#include "../../codecs/da7219.h"
18
#include "../../codecs/rt1015.h"
19
#include "../common/mtk-afe-platform-driver.h"
20
#include "mt8183-afe-common.h"
21
22
#define DA7219_CODEC_DAI "da7219-hifi"
23
#define DA7219_DEV_NAME "da7219.5-001a"
24
#define RT1015_CODEC_DAI "rt1015-aif"
25
#define RT1015_DEV0_NAME "rt1015.6-0028"
26
#define RT1015_DEV1_NAME "rt1015.6-0029"
27
28
struct mt8183_da7219_max98357_priv {
29
struct snd_soc_jack headset_jack, hdmi_jack;
30
};
31
32
static struct snd_soc_jack_pin mt8183_da7219_max98357_jack_pins[] = {
33
{
34
.pin = "Headphones",
35
.mask = SND_JACK_HEADPHONE,
36
},
37
{
38
.pin = "Headset Mic",
39
.mask = SND_JACK_MICROPHONE,
40
},
41
{
42
.pin = "Line Out",
43
.mask = SND_JACK_LINEOUT,
44
},
45
};
46
47
static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream,
48
struct snd_pcm_hw_params *params)
49
{
50
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
51
unsigned int rate = params_rate(params);
52
unsigned int mclk_fs_ratio = 128;
53
unsigned int mclk_fs = rate * mclk_fs_ratio;
54
55
return snd_soc_dai_set_sysclk(snd_soc_rtd_to_cpu(rtd, 0),
56
0, mclk_fs, SND_SOC_CLOCK_OUT);
57
}
58
59
static const struct snd_soc_ops mt8183_mt6358_i2s_ops = {
60
.hw_params = mt8183_mt6358_i2s_hw_params,
61
};
62
63
static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream,
64
struct snd_pcm_hw_params *params)
65
{
66
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
67
struct snd_soc_dai *codec_dai;
68
unsigned int rate = params_rate(params);
69
unsigned int mclk_fs_ratio = 256;
70
unsigned int mclk_fs = rate * mclk_fs_ratio;
71
unsigned int freq;
72
int ret = 0, j;
73
74
ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_cpu(rtd, 0), 0,
75
mclk_fs, SND_SOC_CLOCK_OUT);
76
if (ret < 0)
77
dev_err(rtd->dev, "failed to set cpu dai sysclk\n");
78
79
for_each_rtd_codec_dais(rtd, j, codec_dai) {
80
if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
81
ret = snd_soc_dai_set_sysclk(codec_dai,
82
DA7219_CLKSRC_MCLK,
83
mclk_fs,
84
SND_SOC_CLOCK_IN);
85
if (ret < 0)
86
dev_err(rtd->dev, "failed to set sysclk\n");
87
88
if ((rate % 8000) == 0)
89
freq = DA7219_PLL_FREQ_OUT_98304;
90
else
91
freq = DA7219_PLL_FREQ_OUT_90316;
92
93
ret = snd_soc_dai_set_pll(codec_dai, 0,
94
DA7219_SYSCLK_PLL_SRM,
95
0, freq);
96
if (ret)
97
dev_err(rtd->dev, "failed to start PLL: %d\n",
98
ret);
99
}
100
}
101
102
return ret;
103
}
104
105
static int mt8183_da7219_hw_free(struct snd_pcm_substream *substream)
106
{
107
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
108
struct snd_soc_dai *codec_dai;
109
int ret = 0, j;
110
111
for_each_rtd_codec_dais(rtd, j, codec_dai) {
112
if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
113
ret = snd_soc_dai_set_pll(codec_dai,
114
0, DA7219_SYSCLK_MCLK, 0, 0);
115
if (ret < 0) {
116
dev_err(rtd->dev, "failed to stop PLL: %d\n",
117
ret);
118
break;
119
}
120
}
121
}
122
123
return ret;
124
}
125
126
static const struct snd_soc_ops mt8183_da7219_i2s_ops = {
127
.hw_params = mt8183_da7219_i2s_hw_params,
128
.hw_free = mt8183_da7219_hw_free,
129
};
130
131
static int
132
mt8183_da7219_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
133
struct snd_pcm_hw_params *params)
134
{
135
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
136
unsigned int rate = params_rate(params);
137
struct snd_soc_dai *codec_dai;
138
int ret = 0, i;
139
140
for_each_rtd_codec_dais(rtd, i, codec_dai) {
141
if (!strcmp(codec_dai->component->name, RT1015_DEV0_NAME) ||
142
!strcmp(codec_dai->component->name, RT1015_DEV1_NAME)) {
143
ret = snd_soc_dai_set_pll(codec_dai, 0,
144
RT1015_PLL_S_BCLK,
145
rate * 64, rate * 256);
146
if (ret) {
147
dev_err(rtd->dev, "failed to set pll\n");
148
return ret;
149
}
150
151
ret = snd_soc_dai_set_sysclk(codec_dai,
152
RT1015_SCLK_S_PLL,
153
rate * 256,
154
SND_SOC_CLOCK_IN);
155
if (ret) {
156
dev_err(rtd->dev, "failed to set sysclk\n");
157
return ret;
158
}
159
}
160
}
161
162
return mt8183_da7219_i2s_hw_params(substream, params);
163
}
164
165
static const struct snd_soc_ops mt8183_da7219_rt1015_i2s_ops = {
166
.hw_params = mt8183_da7219_rt1015_i2s_hw_params,
167
.hw_free = mt8183_da7219_hw_free,
168
};
169
170
static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
171
struct snd_pcm_hw_params *params)
172
{
173
/* fix BE i2s format to S32_LE, clean param mask first */
174
snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
175
0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
176
177
params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);
178
179
return 0;
180
}
181
182
static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
183
struct snd_pcm_hw_params *params)
184
{
185
/* fix BE i2s format to S24_LE, clean param mask first */
186
snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
187
0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
188
189
params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
190
191
return 0;
192
}
193
194
static int
195
mt8183_da7219_max98357_startup(
196
struct snd_pcm_substream *substream)
197
{
198
static const unsigned int rates[] = {
199
48000,
200
};
201
static const struct snd_pcm_hw_constraint_list constraints_rates = {
202
.count = ARRAY_SIZE(rates),
203
.list = rates,
204
.mask = 0,
205
};
206
static const unsigned int channels[] = {
207
2,
208
};
209
static const struct snd_pcm_hw_constraint_list constraints_channels = {
210
.count = ARRAY_SIZE(channels),
211
.list = channels,
212
.mask = 0,
213
};
214
215
struct snd_pcm_runtime *runtime = substream->runtime;
216
217
snd_pcm_hw_constraint_list(runtime, 0,
218
SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
219
runtime->hw.channels_max = 2;
220
snd_pcm_hw_constraint_list(runtime, 0,
221
SNDRV_PCM_HW_PARAM_CHANNELS,
222
&constraints_channels);
223
224
runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
225
snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
226
227
return 0;
228
}
229
230
static const struct snd_soc_ops mt8183_da7219_max98357_ops = {
231
.startup = mt8183_da7219_max98357_startup,
232
};
233
234
static int
235
mt8183_da7219_max98357_bt_sco_startup(
236
struct snd_pcm_substream *substream)
237
{
238
static const unsigned int rates[] = {
239
8000, 16000
240
};
241
static const struct snd_pcm_hw_constraint_list constraints_rates = {
242
.count = ARRAY_SIZE(rates),
243
.list = rates,
244
.mask = 0,
245
};
246
static const unsigned int channels[] = {
247
1,
248
};
249
static const struct snd_pcm_hw_constraint_list constraints_channels = {
250
.count = ARRAY_SIZE(channels),
251
.list = channels,
252
.mask = 0,
253
};
254
255
struct snd_pcm_runtime *runtime = substream->runtime;
256
257
snd_pcm_hw_constraint_list(runtime, 0,
258
SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
259
runtime->hw.channels_max = 1;
260
snd_pcm_hw_constraint_list(runtime, 0,
261
SNDRV_PCM_HW_PARAM_CHANNELS,
262
&constraints_channels);
263
264
runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
265
snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
266
267
return 0;
268
}
269
270
static const struct snd_soc_ops mt8183_da7219_max98357_bt_sco_ops = {
271
.startup = mt8183_da7219_max98357_bt_sco_startup,
272
};
273
274
/* FE */
275
SND_SOC_DAILINK_DEFS(playback1,
276
DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
277
DAILINK_COMP_ARRAY(COMP_DUMMY()),
278
DAILINK_COMP_ARRAY(COMP_EMPTY()));
279
280
SND_SOC_DAILINK_DEFS(playback2,
281
DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
282
DAILINK_COMP_ARRAY(COMP_DUMMY()),
283
DAILINK_COMP_ARRAY(COMP_EMPTY()));
284
285
SND_SOC_DAILINK_DEFS(playback3,
286
DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
287
DAILINK_COMP_ARRAY(COMP_DUMMY()),
288
DAILINK_COMP_ARRAY(COMP_EMPTY()));
289
290
SND_SOC_DAILINK_DEFS(capture1,
291
DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
292
DAILINK_COMP_ARRAY(COMP_DUMMY()),
293
DAILINK_COMP_ARRAY(COMP_EMPTY()));
294
295
SND_SOC_DAILINK_DEFS(capture2,
296
DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
297
DAILINK_COMP_ARRAY(COMP_DUMMY()),
298
DAILINK_COMP_ARRAY(COMP_EMPTY()));
299
300
SND_SOC_DAILINK_DEFS(capture3,
301
DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
302
DAILINK_COMP_ARRAY(COMP_DUMMY()),
303
DAILINK_COMP_ARRAY(COMP_EMPTY()));
304
305
SND_SOC_DAILINK_DEFS(capture_mono,
306
DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")),
307
DAILINK_COMP_ARRAY(COMP_DUMMY()),
308
DAILINK_COMP_ARRAY(COMP_EMPTY()));
309
310
SND_SOC_DAILINK_DEFS(playback_hdmi,
311
DAILINK_COMP_ARRAY(COMP_CPU("HDMI")),
312
DAILINK_COMP_ARRAY(COMP_DUMMY()),
313
DAILINK_COMP_ARRAY(COMP_EMPTY()));
314
315
/* BE */
316
SND_SOC_DAILINK_DEFS(primary_codec,
317
DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
318
DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")),
319
DAILINK_COMP_ARRAY(COMP_EMPTY()));
320
321
SND_SOC_DAILINK_DEFS(pcm1,
322
DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
323
DAILINK_COMP_ARRAY(COMP_DUMMY()),
324
DAILINK_COMP_ARRAY(COMP_EMPTY()));
325
326
SND_SOC_DAILINK_DEFS(pcm2,
327
DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")),
328
DAILINK_COMP_ARRAY(COMP_DUMMY()),
329
DAILINK_COMP_ARRAY(COMP_EMPTY()));
330
331
SND_SOC_DAILINK_DEFS(i2s0,
332
DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
333
DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),
334
DAILINK_COMP_ARRAY(COMP_EMPTY()));
335
336
SND_SOC_DAILINK_DEFS(i2s1,
337
DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
338
DAILINK_COMP_ARRAY(COMP_DUMMY()),
339
DAILINK_COMP_ARRAY(COMP_EMPTY()));
340
341
SND_SOC_DAILINK_DEFS(i2s2,
342
DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
343
DAILINK_COMP_ARRAY(COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),
344
DAILINK_COMP_ARRAY(COMP_EMPTY()));
345
346
SND_SOC_DAILINK_DEFS(i2s3_max98357a,
347
DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
348
DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi"),
349
COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),
350
DAILINK_COMP_ARRAY(COMP_EMPTY()));
351
352
SND_SOC_DAILINK_DEFS(i2s3_rt1015,
353
DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
354
DAILINK_COMP_ARRAY(COMP_CODEC(RT1015_DEV0_NAME, RT1015_CODEC_DAI),
355
COMP_CODEC(RT1015_DEV1_NAME, RT1015_CODEC_DAI),
356
COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),
357
DAILINK_COMP_ARRAY(COMP_EMPTY()));
358
359
SND_SOC_DAILINK_DEFS(i2s3_rt1015p,
360
DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
361
DAILINK_COMP_ARRAY(COMP_CODEC("rt1015p", "HiFi"),
362
COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),
363
DAILINK_COMP_ARRAY(COMP_EMPTY()));
364
365
SND_SOC_DAILINK_DEFS(i2s5,
366
DAILINK_COMP_ARRAY(COMP_CPU("I2S5")),
367
DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),
368
DAILINK_COMP_ARRAY(COMP_EMPTY()));
369
370
SND_SOC_DAILINK_DEFS(tdm,
371
DAILINK_COMP_ARRAY(COMP_CPU("TDM")),
372
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")),
373
DAILINK_COMP_ARRAY(COMP_EMPTY()));
374
375
static int mt8183_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd)
376
{
377
struct mt8183_da7219_max98357_priv *priv =
378
snd_soc_card_get_drvdata(rtd->card);
379
int ret;
380
381
ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
382
&priv->hdmi_jack);
383
if (ret)
384
return ret;
385
386
return snd_soc_component_set_jack(snd_soc_rtd_to_codec(rtd, 0)->component,
387
&priv->hdmi_jack, NULL);
388
}
389
390
static int mt8183_bt_init(struct snd_soc_pcm_runtime *rtd)
391
{
392
struct snd_soc_component *cmpnt_afe =
393
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
394
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
395
int ret;
396
397
ret = mt8183_dai_i2s_set_share(afe, "I2S5", "I2S0");
398
if (ret) {
399
dev_err(rtd->dev, "Failed to set up shared clocks\n");
400
return ret;
401
}
402
return 0;
403
}
404
405
static int mt8183_da7219_init(struct snd_soc_pcm_runtime *rtd)
406
{
407
struct snd_soc_component *cmpnt_afe =
408
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
409
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
410
int ret;
411
412
ret = mt8183_dai_i2s_set_share(afe, "I2S2", "I2S3");
413
if (ret) {
414
dev_err(rtd->dev, "Failed to set up shared clocks\n");
415
return ret;
416
}
417
return 0;
418
}
419
420
static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
421
/* FE */
422
{
423
.name = "Playback_1",
424
.stream_name = "Playback_1",
425
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
426
SND_SOC_DPCM_TRIGGER_PRE},
427
.dynamic = 1,
428
.playback_only = 1,
429
.ops = &mt8183_da7219_max98357_ops,
430
SND_SOC_DAILINK_REG(playback1),
431
},
432
{
433
.name = "Playback_2",
434
.stream_name = "Playback_2",
435
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
436
SND_SOC_DPCM_TRIGGER_PRE},
437
.dynamic = 1,
438
.playback_only = 1,
439
.ops = &mt8183_da7219_max98357_bt_sco_ops,
440
SND_SOC_DAILINK_REG(playback2),
441
},
442
{
443
.name = "Playback_3",
444
.stream_name = "Playback_3",
445
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
446
SND_SOC_DPCM_TRIGGER_PRE},
447
.dynamic = 1,
448
.playback_only = 1,
449
SND_SOC_DAILINK_REG(playback3),
450
},
451
{
452
.name = "Capture_1",
453
.stream_name = "Capture_1",
454
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
455
SND_SOC_DPCM_TRIGGER_PRE},
456
.dynamic = 1,
457
.capture_only = 1,
458
.ops = &mt8183_da7219_max98357_bt_sco_ops,
459
SND_SOC_DAILINK_REG(capture1),
460
},
461
{
462
.name = "Capture_2",
463
.stream_name = "Capture_2",
464
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
465
SND_SOC_DPCM_TRIGGER_PRE},
466
.dynamic = 1,
467
.capture_only = 1,
468
SND_SOC_DAILINK_REG(capture2),
469
},
470
{
471
.name = "Capture_3",
472
.stream_name = "Capture_3",
473
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
474
SND_SOC_DPCM_TRIGGER_PRE},
475
.dynamic = 1,
476
.capture_only = 1,
477
.ops = &mt8183_da7219_max98357_ops,
478
SND_SOC_DAILINK_REG(capture3),
479
},
480
{
481
.name = "Capture_Mono_1",
482
.stream_name = "Capture_Mono_1",
483
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
484
SND_SOC_DPCM_TRIGGER_PRE},
485
.dynamic = 1,
486
.capture_only = 1,
487
SND_SOC_DAILINK_REG(capture_mono),
488
},
489
{
490
.name = "Playback_HDMI",
491
.stream_name = "Playback_HDMI",
492
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
493
SND_SOC_DPCM_TRIGGER_PRE},
494
.dynamic = 1,
495
.playback_only = 1,
496
SND_SOC_DAILINK_REG(playback_hdmi),
497
},
498
/* BE */
499
{
500
.name = "Primary Codec",
501
.no_pcm = 1,
502
.ignore_suspend = 1,
503
SND_SOC_DAILINK_REG(primary_codec),
504
},
505
{
506
.name = "PCM 1",
507
.no_pcm = 1,
508
.ignore_suspend = 1,
509
SND_SOC_DAILINK_REG(pcm1),
510
},
511
{
512
.name = "PCM 2",
513
.no_pcm = 1,
514
.ignore_suspend = 1,
515
SND_SOC_DAILINK_REG(pcm2),
516
},
517
{
518
.name = "I2S0",
519
.no_pcm = 1,
520
.capture_only = 1,
521
.ignore_suspend = 1,
522
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
523
.ops = &mt8183_mt6358_i2s_ops,
524
SND_SOC_DAILINK_REG(i2s0),
525
},
526
{
527
.name = "I2S1",
528
.no_pcm = 1,
529
.playback_only = 1,
530
.ignore_suspend = 1,
531
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
532
.ops = &mt8183_mt6358_i2s_ops,
533
SND_SOC_DAILINK_REG(i2s1),
534
},
535
{
536
.name = "I2S2",
537
.no_pcm = 1,
538
.capture_only = 1,
539
.ignore_suspend = 1,
540
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
541
.ops = &mt8183_da7219_i2s_ops,
542
.init = &mt8183_da7219_init,
543
SND_SOC_DAILINK_REG(i2s2),
544
},
545
{
546
.name = "I2S3",
547
.no_pcm = 1,
548
.playback_only = 1,
549
.ignore_suspend = 1,
550
},
551
{
552
.name = "I2S5",
553
.no_pcm = 1,
554
.playback_only = 1,
555
.ignore_suspend = 1,
556
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
557
.ops = &mt8183_mt6358_i2s_ops,
558
.init = &mt8183_bt_init,
559
SND_SOC_DAILINK_REG(i2s5),
560
},
561
{
562
.name = "TDM",
563
.no_pcm = 1,
564
.dai_fmt = SND_SOC_DAIFMT_I2S |
565
SND_SOC_DAIFMT_IB_IF |
566
SND_SOC_DAIFMT_CBP_CFP,
567
.playback_only = 1,
568
.ignore_suspend = 1,
569
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
570
.ignore = 1,
571
.init = mt8183_da7219_max98357_hdmi_init,
572
SND_SOC_DAILINK_REG(tdm),
573
},
574
};
575
576
static int
577
mt8183_da7219_max98357_headset_init(struct snd_soc_component *component)
578
{
579
int ret;
580
struct mt8183_da7219_max98357_priv *priv =
581
snd_soc_card_get_drvdata(component->card);
582
583
/* Enable Headset and 4 Buttons Jack detection */
584
ret = snd_soc_card_jack_new_pins(component->card,
585
"Headset Jack",
586
SND_JACK_HEADSET |
587
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
588
SND_JACK_BTN_2 | SND_JACK_BTN_3 |
589
SND_JACK_LINEOUT,
590
&priv->headset_jack,
591
mt8183_da7219_max98357_jack_pins,
592
ARRAY_SIZE(mt8183_da7219_max98357_jack_pins));
593
if (ret)
594
return ret;
595
596
snd_jack_set_key(
597
priv->headset_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
598
snd_jack_set_key(
599
priv->headset_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
600
snd_jack_set_key(
601
priv->headset_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
602
snd_jack_set_key(
603
priv->headset_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
604
605
snd_soc_component_set_jack(component, &priv->headset_jack, NULL);
606
607
return 0;
608
}
609
610
static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = {
611
.dlc = COMP_EMPTY(),
612
.init = mt8183_da7219_max98357_headset_init,
613
};
614
615
static struct snd_soc_codec_conf mt6358_codec_conf[] = {
616
{
617
.dlc = COMP_CODEC_CONF("mt6358-sound"),
618
.name_prefix = "Mt6358",
619
},
620
};
621
622
static const struct snd_kcontrol_new mt8183_da7219_max98357_snd_controls[] = {
623
SOC_DAPM_PIN_SWITCH("Headphones"),
624
SOC_DAPM_PIN_SWITCH("Headset Mic"),
625
SOC_DAPM_PIN_SWITCH("Speakers"),
626
SOC_DAPM_PIN_SWITCH("Line Out"),
627
};
628
629
static const
630
struct snd_soc_dapm_widget mt8183_da7219_max98357_dapm_widgets[] = {
631
SND_SOC_DAPM_HP("Headphones", NULL),
632
SND_SOC_DAPM_MIC("Headset Mic", NULL),
633
SND_SOC_DAPM_SPK("Speakers", NULL),
634
SND_SOC_DAPM_SPK("Line Out", NULL),
635
SND_SOC_DAPM_PINCTRL("TDM_OUT_PINCTRL",
636
"aud_tdm_out_on", "aud_tdm_out_off"),
637
};
638
639
static const struct snd_soc_dapm_route mt8183_da7219_max98357_dapm_routes[] = {
640
{"Speakers", NULL, "Speaker"},
641
{"I2S Playback", NULL, "TDM_OUT_PINCTRL"},
642
};
643
644
static struct snd_soc_card mt8183_da7219_max98357_card = {
645
.name = "mt8183_da7219_max98357",
646
.owner = THIS_MODULE,
647
.controls = mt8183_da7219_max98357_snd_controls,
648
.num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls),
649
.dapm_widgets = mt8183_da7219_max98357_dapm_widgets,
650
.num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets),
651
.dapm_routes = mt8183_da7219_max98357_dapm_routes,
652
.num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes),
653
.dai_link = mt8183_da7219_dai_links,
654
.num_links = ARRAY_SIZE(mt8183_da7219_dai_links),
655
.aux_dev = &mt8183_da7219_max98357_headset_dev,
656
.num_aux_devs = 1,
657
.codec_conf = mt6358_codec_conf,
658
.num_configs = ARRAY_SIZE(mt6358_codec_conf),
659
};
660
661
static struct snd_soc_codec_conf mt8183_da7219_rt1015_codec_conf[] = {
662
{
663
.dlc = COMP_CODEC_CONF("mt6358-sound"),
664
.name_prefix = "Mt6358",
665
},
666
{
667
.dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME),
668
.name_prefix = "Left",
669
},
670
{
671
.dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME),
672
.name_prefix = "Right",
673
},
674
};
675
676
static const struct snd_kcontrol_new mt8183_da7219_rt1015_snd_controls[] = {
677
SOC_DAPM_PIN_SWITCH("Headphones"),
678
SOC_DAPM_PIN_SWITCH("Headset Mic"),
679
SOC_DAPM_PIN_SWITCH("Left Spk"),
680
SOC_DAPM_PIN_SWITCH("Right Spk"),
681
SOC_DAPM_PIN_SWITCH("Line Out"),
682
};
683
684
static const
685
struct snd_soc_dapm_widget mt8183_da7219_rt1015_dapm_widgets[] = {
686
SND_SOC_DAPM_HP("Headphones", NULL),
687
SND_SOC_DAPM_MIC("Headset Mic", NULL),
688
SND_SOC_DAPM_SPK("Left Spk", NULL),
689
SND_SOC_DAPM_SPK("Right Spk", NULL),
690
SND_SOC_DAPM_LINE("Line Out", NULL),
691
SND_SOC_DAPM_PINCTRL("TDM_OUT_PINCTRL",
692
"aud_tdm_out_on", "aud_tdm_out_off"),
693
};
694
695
static const struct snd_soc_dapm_route mt8183_da7219_rt1015_dapm_routes[] = {
696
{"Left Spk", NULL, "Left SPO"},
697
{"Right Spk", NULL, "Right SPO"},
698
{"I2S Playback", NULL, "TDM_OUT_PINCTRL"},
699
};
700
701
static struct snd_soc_card mt8183_da7219_rt1015_card = {
702
.name = "mt8183_da7219_rt1015",
703
.owner = THIS_MODULE,
704
.controls = mt8183_da7219_rt1015_snd_controls,
705
.num_controls = ARRAY_SIZE(mt8183_da7219_rt1015_snd_controls),
706
.dapm_widgets = mt8183_da7219_rt1015_dapm_widgets,
707
.num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_rt1015_dapm_widgets),
708
.dapm_routes = mt8183_da7219_rt1015_dapm_routes,
709
.num_dapm_routes = ARRAY_SIZE(mt8183_da7219_rt1015_dapm_routes),
710
.dai_link = mt8183_da7219_dai_links,
711
.num_links = ARRAY_SIZE(mt8183_da7219_dai_links),
712
.aux_dev = &mt8183_da7219_max98357_headset_dev,
713
.num_aux_devs = 1,
714
.codec_conf = mt8183_da7219_rt1015_codec_conf,
715
.num_configs = ARRAY_SIZE(mt8183_da7219_rt1015_codec_conf),
716
};
717
718
static struct snd_soc_card mt8183_da7219_rt1015p_card = {
719
.name = "mt8183_da7219_rt1015p",
720
.owner = THIS_MODULE,
721
.controls = mt8183_da7219_max98357_snd_controls,
722
.num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls),
723
.dapm_widgets = mt8183_da7219_max98357_dapm_widgets,
724
.num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets),
725
.dapm_routes = mt8183_da7219_max98357_dapm_routes,
726
.num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes),
727
.dai_link = mt8183_da7219_dai_links,
728
.num_links = ARRAY_SIZE(mt8183_da7219_dai_links),
729
.aux_dev = &mt8183_da7219_max98357_headset_dev,
730
.num_aux_devs = 1,
731
.codec_conf = mt6358_codec_conf,
732
.num_configs = ARRAY_SIZE(mt6358_codec_conf),
733
};
734
735
static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev)
736
{
737
struct snd_soc_card *card;
738
struct device_node *platform_node, *hdmi_codec;
739
struct snd_soc_dai_link *dai_link;
740
struct mt8183_da7219_max98357_priv *priv;
741
struct pinctrl *pinctrl;
742
int ret, i;
743
744
platform_node = of_parse_phandle(pdev->dev.of_node,
745
"mediatek,platform", 0);
746
if (!platform_node) {
747
dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
748
return -EINVAL;
749
}
750
751
card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev);
752
if (!card) {
753
ret = -EINVAL;
754
goto put_platform_node;
755
}
756
757
card->dev = &pdev->dev;
758
759
hdmi_codec = of_parse_phandle(pdev->dev.of_node,
760
"mediatek,hdmi-codec", 0);
761
762
for_each_card_prelinks(card, i, dai_link) {
763
if (strcmp(dai_link->name, "I2S3") == 0) {
764
if (card == &mt8183_da7219_max98357_card) {
765
dai_link->be_hw_params_fixup =
766
mt8183_i2s_hw_params_fixup;
767
dai_link->ops = &mt8183_da7219_i2s_ops;
768
dai_link->cpus = i2s3_max98357a_cpus;
769
dai_link->num_cpus =
770
ARRAY_SIZE(i2s3_max98357a_cpus);
771
dai_link->codecs = i2s3_max98357a_codecs;
772
dai_link->num_codecs =
773
ARRAY_SIZE(i2s3_max98357a_codecs);
774
dai_link->platforms = i2s3_max98357a_platforms;
775
dai_link->num_platforms =
776
ARRAY_SIZE(i2s3_max98357a_platforms);
777
} else if (card == &mt8183_da7219_rt1015_card) {
778
dai_link->be_hw_params_fixup =
779
mt8183_rt1015_i2s_hw_params_fixup;
780
dai_link->ops = &mt8183_da7219_rt1015_i2s_ops;
781
dai_link->cpus = i2s3_rt1015_cpus;
782
dai_link->num_cpus =
783
ARRAY_SIZE(i2s3_rt1015_cpus);
784
dai_link->codecs = i2s3_rt1015_codecs;
785
dai_link->num_codecs =
786
ARRAY_SIZE(i2s3_rt1015_codecs);
787
dai_link->platforms = i2s3_rt1015_platforms;
788
dai_link->num_platforms =
789
ARRAY_SIZE(i2s3_rt1015_platforms);
790
} else if (card == &mt8183_da7219_rt1015p_card) {
791
dai_link->be_hw_params_fixup =
792
mt8183_rt1015_i2s_hw_params_fixup;
793
dai_link->ops = &mt8183_da7219_i2s_ops;
794
dai_link->cpus = i2s3_rt1015p_cpus;
795
dai_link->num_cpus =
796
ARRAY_SIZE(i2s3_rt1015p_cpus);
797
dai_link->codecs = i2s3_rt1015p_codecs;
798
dai_link->num_codecs =
799
ARRAY_SIZE(i2s3_rt1015p_codecs);
800
dai_link->platforms = i2s3_rt1015p_platforms;
801
dai_link->num_platforms =
802
ARRAY_SIZE(i2s3_rt1015p_platforms);
803
}
804
}
805
806
if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) {
807
dai_link->codecs->of_node = hdmi_codec;
808
dai_link->ignore = 0;
809
}
810
811
if (!dai_link->platforms->name)
812
dai_link->platforms->of_node = platform_node;
813
}
814
815
mt8183_da7219_max98357_headset_dev.dlc.of_node =
816
of_parse_phandle(pdev->dev.of_node,
817
"mediatek,headset-codec", 0);
818
if (!mt8183_da7219_max98357_headset_dev.dlc.of_node) {
819
dev_err(&pdev->dev,
820
"Property 'mediatek,headset-codec' missing/invalid\n");
821
ret = -EINVAL;
822
goto put_hdmi_codec;
823
}
824
825
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
826
if (!priv) {
827
ret = -ENOMEM;
828
goto put_hdmi_codec;
829
}
830
831
snd_soc_card_set_drvdata(card, priv);
832
833
pinctrl = devm_pinctrl_get_select(&pdev->dev, PINCTRL_STATE_DEFAULT);
834
if (IS_ERR(pinctrl)) {
835
ret = PTR_ERR(pinctrl);
836
dev_err(&pdev->dev, "%s failed to select default state %d\n",
837
__func__, ret);
838
goto put_hdmi_codec;
839
}
840
841
ret = devm_snd_soc_register_card(&pdev->dev, card);
842
843
844
put_hdmi_codec:
845
of_node_put(hdmi_codec);
846
put_platform_node:
847
of_node_put(platform_node);
848
return ret;
849
}
850
851
#ifdef CONFIG_OF
852
static const struct of_device_id mt8183_da7219_max98357_dt_match[] = {
853
{
854
.compatible = "mediatek,mt8183_da7219_max98357",
855
.data = &mt8183_da7219_max98357_card,
856
},
857
{
858
.compatible = "mediatek,mt8183_da7219_rt1015",
859
.data = &mt8183_da7219_rt1015_card,
860
},
861
{
862
.compatible = "mediatek,mt8183_da7219_rt1015p",
863
.data = &mt8183_da7219_rt1015p_card,
864
},
865
{}
866
};
867
MODULE_DEVICE_TABLE(of, mt8183_da7219_max98357_dt_match);
868
#endif
869
870
static struct platform_driver mt8183_da7219_max98357_driver = {
871
.driver = {
872
.name = "mt8183_da7219",
873
#ifdef CONFIG_OF
874
.of_match_table = mt8183_da7219_max98357_dt_match,
875
#endif
876
.pm = &snd_soc_pm_ops,
877
},
878
.probe = mt8183_da7219_max98357_dev_probe,
879
};
880
881
module_platform_driver(mt8183_da7219_max98357_driver);
882
883
/* Module information */
884
MODULE_DESCRIPTION("MT8183-DA7219-MAX98357 ALSA SoC machine driver");
885
MODULE_AUTHOR("Shunli Wang <[email protected]>");
886
MODULE_LICENSE("GPL v2");
887
MODULE_ALIAS("mt8183_da7219_max98357 soc card");
888
889