1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2026 BayLibre, SAS.
// Author: Valerio Setti <vsetti@baylibre.com>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#include "aiu.h"
#include "gx-formatter.h"
#define AIU_I2S_SOURCE_DESC_MODE_8CH BIT(0)
#define AIU_I2S_SOURCE_DESC_MODE_24BIT BIT(5)
#define AIU_I2S_SOURCE_DESC_MODE_32BIT BIT(9)
#define AIU_I2S_DAC_CFG_MSB_FIRST BIT(2)
static struct snd_soc_dai *
aiu_formatter_i2s_get_be(struct snd_soc_dapm_widget *w)
{
struct snd_soc_dapm_path *p;
struct snd_soc_dai *be;
snd_soc_dapm_widget_for_each_sink_path(w, p) {
if (!p->connect)
continue;
if (p->sink->id == snd_soc_dapm_dai_in)
return (struct snd_soc_dai *)p->sink->priv;
be = aiu_formatter_i2s_get_be(p->sink);
if (be)
return be;
}
return NULL;
}
static struct gx_stream *
aiu_formatter_i2s_get_stream(struct snd_soc_dapm_widget *w)
{
struct snd_soc_dai *be = aiu_formatter_i2s_get_be(w);
if (!be)
return NULL;
return snd_soc_dai_dma_data_get_playback(be);
}
static int aiu_formatter_i2s_prepare(struct regmap *map,
const struct gx_formatter_hw *quirks,
struct gx_stream *ts)
{
/* Always operate in split (classic interleaved) mode */
unsigned int desc = 0;
/*
* Pipeline reset is already implemented in aiu_fifo_i2s_trigger() at
* trigger time.
*/
switch (ts->physical_width) {
case 16: /* Nothing to do */
break;
case 32:
desc |= (AIU_I2S_SOURCE_DESC_MODE_24BIT |
AIU_I2S_SOURCE_DESC_MODE_32BIT);
break;
default:
return -EINVAL;
}
switch (ts->channels) {
case 2: /* Nothing to do */
break;
case 8:
desc |= AIU_I2S_SOURCE_DESC_MODE_8CH;
break;
default:
return -EINVAL;
}
regmap_update_bits(map, AIU_I2S_SOURCE_DESC,
AIU_I2S_SOURCE_DESC_MODE_8CH |
AIU_I2S_SOURCE_DESC_MODE_24BIT |
AIU_I2S_SOURCE_DESC_MODE_32BIT,
desc);
/* Send data MSB first */
regmap_update_bits(map, AIU_I2S_DAC_CFG,
AIU_I2S_DAC_CFG_MSB_FIRST,
AIU_I2S_DAC_CFG_MSB_FIRST);
return 0;
}
const struct gx_formatter_ops aiu_formatter_i2s_ops = {
.get_stream = aiu_formatter_i2s_get_stream,
.prepare = aiu_formatter_i2s_prepare,
};
|