Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/mediatek/common/mtk-afe-fe-dai.c
26450 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* mtk-afe-fe-dais.c -- Mediatek afe fe dai operator
4
*
5
* Copyright (c) 2016 MediaTek Inc.
6
* Author: Garlic Tseng <[email protected]>
7
*/
8
9
#include <linux/io.h>
10
#include <linux/module.h>
11
#include <linux/pm_runtime.h>
12
#include <linux/regmap.h>
13
#include <sound/soc.h>
14
#include "mtk-afe-platform-driver.h"
15
#include <sound/pcm_params.h>
16
#include "mtk-afe-fe-dai.h"
17
#include "mtk-base-afe.h"
18
19
#define AFE_BASE_END_OFFSET 8
20
21
static int mtk_regmap_update_bits(struct regmap *map, int reg,
22
unsigned int mask,
23
unsigned int val, int shift)
24
{
25
if (reg < 0 || WARN_ON_ONCE(shift < 0))
26
return 0;
27
return regmap_update_bits(map, reg, mask << shift, val << shift);
28
}
29
30
static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val)
31
{
32
if (reg < 0)
33
return 0;
34
return regmap_write(map, reg, val);
35
}
36
37
int mtk_afe_fe_startup(struct snd_pcm_substream *substream,
38
struct snd_soc_dai *dai)
39
{
40
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
41
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
42
struct snd_pcm_runtime *runtime = substream->runtime;
43
int memif_num = snd_soc_rtd_to_cpu(rtd, 0)->id;
44
struct mtk_base_afe_memif *memif = &afe->memif[memif_num];
45
const struct snd_pcm_hardware *mtk_afe_hardware = afe->mtk_afe_hardware;
46
int ret;
47
48
memif->substream = substream;
49
50
snd_pcm_hw_constraint_step(substream->runtime, 0,
51
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
52
/* enable agent */
53
mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg,
54
1, 0, memif->data->agent_disable_shift);
55
56
snd_soc_set_runtime_hwparams(substream, mtk_afe_hardware);
57
58
/*
59
* Capture cannot use ping-pong buffer since hw_ptr at IRQ may be
60
* smaller than period_size due to AFE's internal buffer.
61
* This easily leads to overrun when avail_min is period_size.
62
* One more period can hold the possible unread buffer.
63
*/
64
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
65
int periods_max = mtk_afe_hardware->periods_max;
66
67
ret = snd_pcm_hw_constraint_minmax(runtime,
68
SNDRV_PCM_HW_PARAM_PERIODS,
69
3, periods_max);
70
if (ret < 0) {
71
dev_err(afe->dev, "hw_constraint_minmax failed\n");
72
return ret;
73
}
74
}
75
76
ret = snd_pcm_hw_constraint_integer(runtime,
77
SNDRV_PCM_HW_PARAM_PERIODS);
78
if (ret < 0)
79
dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
80
81
/* dynamic allocate irq to memif */
82
if (memif->irq_usage < 0) {
83
int irq_id = mtk_dynamic_irq_acquire(afe);
84
85
if (irq_id != afe->irqs_size) {
86
/* link */
87
memif->irq_usage = irq_id;
88
} else {
89
dev_err(afe->dev, "%s() error: no more asys irq\n",
90
__func__);
91
ret = -EBUSY;
92
}
93
}
94
return ret;
95
}
96
EXPORT_SYMBOL_GPL(mtk_afe_fe_startup);
97
98
void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream,
99
struct snd_soc_dai *dai)
100
{
101
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
102
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
103
struct mtk_base_afe_memif *memif = &afe->memif[snd_soc_rtd_to_cpu(rtd, 0)->id];
104
int irq_id;
105
106
irq_id = memif->irq_usage;
107
108
mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg,
109
1, 1, memif->data->agent_disable_shift);
110
111
if (!memif->const_irq) {
112
mtk_dynamic_irq_release(afe, irq_id);
113
memif->irq_usage = -1;
114
memif->substream = NULL;
115
}
116
}
117
EXPORT_SYMBOL_GPL(mtk_afe_fe_shutdown);
118
119
int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
120
struct snd_pcm_hw_params *params,
121
struct snd_soc_dai *dai)
122
{
123
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
124
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
125
int id = snd_soc_rtd_to_cpu(rtd, 0)->id;
126
struct mtk_base_afe_memif *memif = &afe->memif[id];
127
int ret;
128
unsigned int channels = params_channels(params);
129
unsigned int rate = params_rate(params);
130
snd_pcm_format_t format = params_format(params);
131
132
if (afe->request_dram_resource)
133
afe->request_dram_resource(afe->dev);
134
135
dev_dbg(afe->dev, "%s(), %s, ch %d, rate %d, fmt %d, dma_addr %pad, dma_area %p, dma_bytes 0x%zx\n",
136
__func__, memif->data->name,
137
channels, rate, format,
138
&substream->runtime->dma_addr,
139
substream->runtime->dma_area,
140
substream->runtime->dma_bytes);
141
142
memset_io((void __force __iomem *)substream->runtime->dma_area, 0,
143
substream->runtime->dma_bytes);
144
145
/* set addr */
146
ret = mtk_memif_set_addr(afe, id,
147
substream->runtime->dma_area,
148
substream->runtime->dma_addr,
149
substream->runtime->dma_bytes);
150
if (ret) {
151
dev_err(afe->dev, "%s(), error, id %d, set addr, ret %d\n",
152
__func__, id, ret);
153
return ret;
154
}
155
156
/* set channel */
157
ret = mtk_memif_set_channel(afe, id, channels);
158
if (ret) {
159
dev_err(afe->dev, "%s(), error, id %d, set channel %d, ret %d\n",
160
__func__, id, channels, ret);
161
return ret;
162
}
163
164
/* set rate */
165
ret = mtk_memif_set_rate_substream(substream, id, rate);
166
if (ret) {
167
dev_err(afe->dev, "%s(), error, id %d, set rate %d, ret %d\n",
168
__func__, id, rate, ret);
169
return ret;
170
}
171
172
/* set format */
173
ret = mtk_memif_set_format(afe, id, format);
174
if (ret) {
175
dev_err(afe->dev, "%s(), error, id %d, set format %d, ret %d\n",
176
__func__, id, format, ret);
177
return ret;
178
}
179
180
return 0;
181
}
182
EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_params);
183
184
int mtk_afe_fe_hw_free(struct snd_pcm_substream *substream,
185
struct snd_soc_dai *dai)
186
{
187
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
188
189
if (afe->release_dram_resource)
190
afe->release_dram_resource(afe->dev);
191
192
return 0;
193
}
194
EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_free);
195
196
int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
197
struct snd_soc_dai *dai)
198
{
199
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
200
struct snd_pcm_runtime * const runtime = substream->runtime;
201
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
202
int id = snd_soc_rtd_to_cpu(rtd, 0)->id;
203
struct mtk_base_afe_memif *memif = &afe->memif[id];
204
struct mtk_base_afe_irq *irqs = &afe->irqs[memif->irq_usage];
205
const struct mtk_base_irq_data *irq_data = irqs->irq_data;
206
unsigned int counter = runtime->period_size;
207
int fs;
208
int ret;
209
210
dev_dbg(afe->dev, "%s %s cmd=%d\n", __func__, memif->data->name, cmd);
211
212
switch (cmd) {
213
case SNDRV_PCM_TRIGGER_START:
214
case SNDRV_PCM_TRIGGER_RESUME:
215
ret = mtk_memif_set_enable(afe, id);
216
if (ret) {
217
dev_err(afe->dev, "%s(), error, id %d, memif enable, ret %d\n",
218
__func__, id, ret);
219
return ret;
220
}
221
222
/* set irq counter */
223
mtk_regmap_update_bits(afe->regmap, irq_data->irq_cnt_reg,
224
irq_data->irq_cnt_maskbit, counter,
225
irq_data->irq_cnt_shift);
226
227
/* set irq fs */
228
fs = afe->irq_fs(substream, runtime->rate);
229
230
if (fs < 0)
231
return -EINVAL;
232
233
mtk_regmap_update_bits(afe->regmap, irq_data->irq_fs_reg,
234
irq_data->irq_fs_maskbit, fs,
235
irq_data->irq_fs_shift);
236
237
/* enable interrupt */
238
mtk_regmap_update_bits(afe->regmap, irq_data->irq_en_reg,
239
1, 1, irq_data->irq_en_shift);
240
241
return 0;
242
case SNDRV_PCM_TRIGGER_STOP:
243
case SNDRV_PCM_TRIGGER_SUSPEND:
244
ret = mtk_memif_set_disable(afe, id);
245
if (ret) {
246
dev_err(afe->dev, "%s(), error, id %d, memif enable, ret %d\n",
247
__func__, id, ret);
248
}
249
250
/* disable interrupt */
251
mtk_regmap_update_bits(afe->regmap, irq_data->irq_en_reg,
252
1, 0, irq_data->irq_en_shift);
253
/* and clear pending IRQ */
254
mtk_regmap_write(afe->regmap, irq_data->irq_clr_reg,
255
1 << irq_data->irq_clr_shift);
256
return ret;
257
default:
258
return -EINVAL;
259
}
260
}
261
EXPORT_SYMBOL_GPL(mtk_afe_fe_trigger);
262
263
int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
264
struct snd_soc_dai *dai)
265
{
266
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
267
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
268
int id = snd_soc_rtd_to_cpu(rtd, 0)->id;
269
int pbuf_size;
270
271
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
272
if (afe->get_memif_pbuf_size) {
273
pbuf_size = afe->get_memif_pbuf_size(substream);
274
mtk_memif_set_pbuf_size(afe, id, pbuf_size);
275
}
276
}
277
return 0;
278
}
279
EXPORT_SYMBOL_GPL(mtk_afe_fe_prepare);
280
281
const struct snd_soc_dai_ops mtk_afe_fe_ops = {
282
.startup = mtk_afe_fe_startup,
283
.shutdown = mtk_afe_fe_shutdown,
284
.hw_params = mtk_afe_fe_hw_params,
285
.hw_free = mtk_afe_fe_hw_free,
286
.prepare = mtk_afe_fe_prepare,
287
.trigger = mtk_afe_fe_trigger,
288
};
289
EXPORT_SYMBOL_GPL(mtk_afe_fe_ops);
290
291
int mtk_dynamic_irq_acquire(struct mtk_base_afe *afe)
292
{
293
int i;
294
295
mutex_lock(&afe->irq_alloc_lock);
296
for (i = 0; i < afe->irqs_size; ++i) {
297
if (afe->irqs[i].irq_occupyed == 0) {
298
afe->irqs[i].irq_occupyed = 1;
299
mutex_unlock(&afe->irq_alloc_lock);
300
return i;
301
}
302
}
303
mutex_unlock(&afe->irq_alloc_lock);
304
return afe->irqs_size;
305
}
306
EXPORT_SYMBOL_GPL(mtk_dynamic_irq_acquire);
307
308
int mtk_dynamic_irq_release(struct mtk_base_afe *afe, int irq_id)
309
{
310
mutex_lock(&afe->irq_alloc_lock);
311
if (irq_id >= 0 && irq_id < afe->irqs_size) {
312
afe->irqs[irq_id].irq_occupyed = 0;
313
mutex_unlock(&afe->irq_alloc_lock);
314
return 0;
315
}
316
mutex_unlock(&afe->irq_alloc_lock);
317
return -EINVAL;
318
}
319
EXPORT_SYMBOL_GPL(mtk_dynamic_irq_release);
320
321
int mtk_afe_suspend(struct snd_soc_component *component)
322
{
323
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
324
struct device *dev = afe->dev;
325
struct regmap *regmap = afe->regmap;
326
int i;
327
328
if (pm_runtime_status_suspended(dev) || afe->suspended)
329
return 0;
330
331
if (!afe->reg_back_up)
332
afe->reg_back_up =
333
devm_kcalloc(dev, afe->reg_back_up_list_num,
334
sizeof(unsigned int), GFP_KERNEL);
335
336
if (afe->reg_back_up) {
337
for (i = 0; i < afe->reg_back_up_list_num; i++)
338
regmap_read(regmap, afe->reg_back_up_list[i],
339
&afe->reg_back_up[i]);
340
}
341
342
afe->suspended = true;
343
afe->runtime_suspend(dev);
344
return 0;
345
}
346
EXPORT_SYMBOL_GPL(mtk_afe_suspend);
347
348
int mtk_afe_resume(struct snd_soc_component *component)
349
{
350
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
351
struct device *dev = afe->dev;
352
struct regmap *regmap = afe->regmap;
353
int i;
354
355
if (pm_runtime_status_suspended(dev) || !afe->suspended)
356
return 0;
357
358
afe->runtime_resume(dev);
359
360
if (!afe->reg_back_up) {
361
dev_dbg(dev, "%s no reg_backup\n", __func__);
362
} else {
363
for (i = 0; i < afe->reg_back_up_list_num; i++)
364
mtk_regmap_write(regmap, afe->reg_back_up_list[i],
365
afe->reg_back_up[i]);
366
}
367
368
afe->suspended = false;
369
return 0;
370
}
371
EXPORT_SYMBOL_GPL(mtk_afe_resume);
372
373
int mtk_memif_set_enable(struct mtk_base_afe *afe, int id)
374
{
375
struct mtk_base_afe_memif *memif = &afe->memif[id];
376
377
if (memif->data->enable_shift < 0) {
378
dev_warn(afe->dev, "%s(), error, id %d, enable_shift < 0\n",
379
__func__, id);
380
return 0;
381
}
382
return mtk_regmap_update_bits(afe->regmap, memif->data->enable_reg,
383
1, 1, memif->data->enable_shift);
384
}
385
EXPORT_SYMBOL_GPL(mtk_memif_set_enable);
386
387
int mtk_memif_set_disable(struct mtk_base_afe *afe, int id)
388
{
389
struct mtk_base_afe_memif *memif = &afe->memif[id];
390
391
if (memif->data->enable_shift < 0) {
392
dev_warn(afe->dev, "%s(), error, id %d, enable_shift < 0\n",
393
__func__, id);
394
return 0;
395
}
396
return mtk_regmap_update_bits(afe->regmap, memif->data->enable_reg,
397
1, 0, memif->data->enable_shift);
398
}
399
EXPORT_SYMBOL_GPL(mtk_memif_set_disable);
400
401
int mtk_memif_set_addr(struct mtk_base_afe *afe, int id,
402
unsigned char *dma_area,
403
dma_addr_t dma_addr,
404
size_t dma_bytes)
405
{
406
struct mtk_base_afe_memif *memif = &afe->memif[id];
407
int msb_at_bit33 = upper_32_bits(dma_addr) ? 1 : 0;
408
unsigned int phys_buf_addr = lower_32_bits(dma_addr);
409
unsigned int phys_buf_addr_upper_32 = upper_32_bits(dma_addr);
410
411
memif->dma_area = dma_area;
412
memif->dma_addr = dma_addr;
413
memif->dma_bytes = dma_bytes;
414
415
/* start */
416
mtk_regmap_write(afe->regmap, memif->data->reg_ofs_base,
417
phys_buf_addr);
418
/* end */
419
if (memif->data->reg_ofs_end)
420
mtk_regmap_write(afe->regmap,
421
memif->data->reg_ofs_end,
422
phys_buf_addr + dma_bytes - 1);
423
else
424
mtk_regmap_write(afe->regmap,
425
memif->data->reg_ofs_base +
426
AFE_BASE_END_OFFSET,
427
phys_buf_addr + dma_bytes - 1);
428
429
/* set start, end, upper 32 bits */
430
if (memif->data->reg_ofs_base_msb) {
431
mtk_regmap_write(afe->regmap, memif->data->reg_ofs_base_msb,
432
phys_buf_addr_upper_32);
433
mtk_regmap_write(afe->regmap,
434
memif->data->reg_ofs_end_msb,
435
phys_buf_addr_upper_32);
436
}
437
438
/*
439
* set MSB to 33-bit, for memif address
440
* only for memif base address, if msb_end_reg exists
441
*/
442
if (memif->data->msb_reg)
443
mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg,
444
1, msb_at_bit33, memif->data->msb_shift);
445
446
/* set MSB to 33-bit, for memif end address */
447
if (memif->data->msb_end_reg)
448
mtk_regmap_update_bits(afe->regmap, memif->data->msb_end_reg,
449
1, msb_at_bit33,
450
memif->data->msb_end_shift);
451
452
return 0;
453
}
454
EXPORT_SYMBOL_GPL(mtk_memif_set_addr);
455
456
int mtk_memif_set_channel(struct mtk_base_afe *afe,
457
int id, unsigned int channel)
458
{
459
struct mtk_base_afe_memif *memif = &afe->memif[id];
460
unsigned int mono;
461
462
if (memif->data->mono_shift < 0)
463
return 0;
464
465
if (memif->data->quad_ch_mask) {
466
unsigned int quad_ch = (channel == 4) ? 1 : 0;
467
468
mtk_regmap_update_bits(afe->regmap, memif->data->quad_ch_reg,
469
memif->data->quad_ch_mask,
470
quad_ch, memif->data->quad_ch_shift);
471
}
472
473
if (memif->data->mono_invert)
474
mono = (channel == 1) ? 0 : 1;
475
else
476
mono = (channel == 1) ? 1 : 0;
477
478
/* for specific configuration of memif mono mode */
479
if (memif->data->int_odd_flag_reg)
480
mtk_regmap_update_bits(afe->regmap,
481
memif->data->int_odd_flag_reg,
482
1, mono,
483
memif->data->int_odd_flag_shift);
484
485
return mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
486
1, mono, memif->data->mono_shift);
487
}
488
EXPORT_SYMBOL_GPL(mtk_memif_set_channel);
489
490
static int mtk_memif_set_rate_fs(struct mtk_base_afe *afe,
491
int id, int fs)
492
{
493
struct mtk_base_afe_memif *memif = &afe->memif[id];
494
495
if (memif->data->fs_shift >= 0)
496
mtk_regmap_update_bits(afe->regmap, memif->data->fs_reg,
497
memif->data->fs_maskbit,
498
fs, memif->data->fs_shift);
499
500
return 0;
501
}
502
503
int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream,
504
int id, unsigned int rate)
505
{
506
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
507
struct snd_soc_component *component =
508
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
509
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
510
511
int fs = 0;
512
513
if (!afe->memif_fs) {
514
dev_err(afe->dev, "%s(), error, afe->memif_fs == NULL\n",
515
__func__);
516
return -EINVAL;
517
}
518
519
fs = afe->memif_fs(substream, rate);
520
521
if (fs < 0)
522
return -EINVAL;
523
524
return mtk_memif_set_rate_fs(afe, id, fs);
525
}
526
EXPORT_SYMBOL_GPL(mtk_memif_set_rate_substream);
527
528
int mtk_memif_set_format(struct mtk_base_afe *afe,
529
int id, snd_pcm_format_t format)
530
{
531
struct mtk_base_afe_memif *memif = &afe->memif[id];
532
int hd_audio = 0;
533
int hd_align = 0;
534
535
/* set hd mode */
536
switch (format) {
537
case SNDRV_PCM_FORMAT_S16_LE:
538
case SNDRV_PCM_FORMAT_U16_LE:
539
hd_audio = 0;
540
break;
541
case SNDRV_PCM_FORMAT_S32_LE:
542
case SNDRV_PCM_FORMAT_U32_LE:
543
if (afe->memif_32bit_supported) {
544
hd_audio = 2;
545
hd_align = 0;
546
} else {
547
hd_audio = 1;
548
hd_align = 1;
549
}
550
break;
551
case SNDRV_PCM_FORMAT_S24_LE:
552
case SNDRV_PCM_FORMAT_U24_LE:
553
hd_audio = 1;
554
break;
555
default:
556
dev_err(afe->dev, "%s() error: unsupported format %d\n",
557
__func__, format);
558
break;
559
}
560
561
mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg,
562
0x3, hd_audio, memif->data->hd_shift);
563
564
mtk_regmap_update_bits(afe->regmap, memif->data->hd_align_reg,
565
0x1, hd_align, memif->data->hd_align_mshift);
566
567
return 0;
568
}
569
EXPORT_SYMBOL_GPL(mtk_memif_set_format);
570
571
int mtk_memif_set_pbuf_size(struct mtk_base_afe *afe,
572
int id, int pbuf_size)
573
{
574
const struct mtk_base_memif_data *memif_data = afe->memif[id].data;
575
576
if (memif_data->pbuf_mask == 0 || memif_data->minlen_mask == 0)
577
return 0;
578
579
mtk_regmap_update_bits(afe->regmap, memif_data->pbuf_reg,
580
memif_data->pbuf_mask,
581
pbuf_size, memif_data->pbuf_shift);
582
583
mtk_regmap_update_bits(afe->regmap, memif_data->minlen_reg,
584
memif_data->minlen_mask,
585
pbuf_size, memif_data->minlen_shift);
586
return 0;
587
}
588
EXPORT_SYMBOL_GPL(mtk_memif_set_pbuf_size);
589
590
MODULE_DESCRIPTION("Mediatek simple fe dai operator");
591
MODULE_AUTHOR("Garlic Tseng <[email protected]>");
592
MODULE_LICENSE("GPL v2");
593
594