Skip to content

Commit 6339d23

Browse files
Vaibhav Agarwalgregkh
authored andcommitted
greybus: audio: Add topology parser for GB codec
For each GB codec module inserted, DAPM widgets, kcontrols, routes and DAIs can be fetched through greybus in a binary chunk and parsed locally to create & populate DAPM graph for the specific module. It is required by each codec module to populate a minimum set of kcontrols with fixed names to support basic audio usecase. To support advanced features of codec module, the same can be polpulated with existing topology parser. However, to use them for different usecase separate mechanism (may be via MSP) is required to inform userspace about their configuration value & enable/disable sequence. ToDos: Currently, support for enumerated kcontrol/dapm control is hardcoded. Need to add complete logic within the parser. Signed-off-by: Vaibhav Agarwal <[email protected]> Signed-off-by: Mark Greer <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2a70e49 commit 6339d23

File tree

4 files changed

+1191
-210
lines changed

4 files changed

+1191
-210
lines changed

drivers/staging/greybus/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ gb-raw-y := raw.o
2929
gb-hid-y := hid.o
3030
gb-es2-y := es2.o
3131
gb-arche-y := arche-platform.o arche-apb-ctrl.o
32-
gb-audio-codec-y := audio_codec.o
32+
gb-audio-codec-y := audio_codec.o audio_topology.o
3333
gb-audio-gb-y := audio_gb.o
3434
gb-audio-apbridgea-y := audio_apbridgea.o
3535
gb-audio-manager-y += audio_manager.o

drivers/staging/greybus/audio_codec.c

Lines changed: 45 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -19,124 +19,6 @@
1919
static DEFINE_MUTEX(gb_codec_list_lock);
2020
static LIST_HEAD(gb_codec_list);
2121

22-
static int gbcodec_event_spk(struct snd_soc_dapm_widget *w,
23-
struct snd_kcontrol *k, int event)
24-
{
25-
/* Ensure GB speaker is connected */
26-
27-
return 0;
28-
}
29-
30-
static int gbcodec_event_hp(struct snd_soc_dapm_widget *w,
31-
struct snd_kcontrol *k, int event)
32-
{
33-
/* Ensure GB module supports jack slot */
34-
35-
return 0;
36-
}
37-
38-
static int gbcodec_event_int_mic(struct snd_soc_dapm_widget *w,
39-
struct snd_kcontrol *k, int event)
40-
{
41-
/* Ensure GB module supports jack slot */
42-
43-
return 0;
44-
}
45-
46-
static const struct snd_kcontrol_new gbcodec_snd_controls[] = {
47-
SOC_DOUBLE("Playback Mute", GBCODEC_MUTE_REG, 0, 1, 1, 1),
48-
SOC_DOUBLE("Capture Mute", GBCODEC_MUTE_REG, 4, 5, 1, 1),
49-
SOC_DOUBLE_R("Playback Volume", GBCODEC_PB_LVOL_REG,
50-
GBCODEC_PB_RVOL_REG, 0, 127, 0),
51-
SOC_DOUBLE_R("Capture Volume", GBCODEC_CAP_LVOL_REG,
52-
GBCODEC_CAP_RVOL_REG, 0, 127, 0),
53-
};
54-
55-
static const struct snd_kcontrol_new spk_amp_ctl =
56-
SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 0, 1, 0);
57-
58-
static const struct snd_kcontrol_new hp_amp_ctl =
59-
SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 1, 1, 0);
60-
61-
static const struct snd_kcontrol_new mic_adc_ctl =
62-
SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 4, 1, 0);
63-
64-
/* APB1-GBSPK source */
65-
static const char * const gbcodec_apb1_src[] = {"Stereo", "Left", "Right"};
66-
67-
static const SOC_ENUM_SINGLE_DECL(
68-
gbcodec_apb1_rx_enum, GBCODEC_APB1_MUX_REG, 0, gbcodec_apb1_src);
69-
70-
static const struct snd_kcontrol_new gbcodec_apb1_rx_mux =
71-
SOC_DAPM_ENUM("APB1 source", gbcodec_apb1_rx_enum);
72-
73-
static const SOC_ENUM_SINGLE_DECL(
74-
gbcodec_mic_enum, GBCODEC_APB1_MUX_REG, 4, gbcodec_apb1_src);
75-
76-
static const struct snd_kcontrol_new gbcodec_mic_mux =
77-
SOC_DAPM_ENUM("MIC source", gbcodec_mic_enum);
78-
79-
static const struct snd_soc_dapm_widget gbcodec_dapm_widgets[] = {
80-
SND_SOC_DAPM_SPK("Spk", gbcodec_event_spk),
81-
SND_SOC_DAPM_SPK("HP", gbcodec_event_hp),
82-
SND_SOC_DAPM_MIC("Int Mic", gbcodec_event_int_mic),
83-
84-
SND_SOC_DAPM_OUTPUT("SPKOUT"),
85-
SND_SOC_DAPM_OUTPUT("HPOUT"),
86-
87-
SND_SOC_DAPM_INPUT("MIC"),
88-
SND_SOC_DAPM_INPUT("HSMIC"),
89-
90-
SND_SOC_DAPM_SWITCH("SPK Amp", SND_SOC_NOPM, 0, 0, &spk_amp_ctl),
91-
SND_SOC_DAPM_SWITCH("HP Amp", SND_SOC_NOPM, 0, 0, &hp_amp_ctl),
92-
SND_SOC_DAPM_SWITCH("MIC ADC", SND_SOC_NOPM, 0, 0, &mic_adc_ctl),
93-
94-
SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
95-
SND_SOC_DAPM_PGA("HP DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
96-
97-
SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
98-
SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
99-
SND_SOC_DAPM_MIXER("APB1_TX Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
100-
101-
SND_SOC_DAPM_MUX("APB1_RX Mux", SND_SOC_NOPM, 0, 0,
102-
&gbcodec_apb1_rx_mux),
103-
SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &gbcodec_mic_mux),
104-
105-
SND_SOC_DAPM_AIF_IN("APB1RX", "APBridgeA1 Playback", 0, SND_SOC_NOPM, 0,
106-
0),
107-
SND_SOC_DAPM_AIF_OUT("APB1TX", "APBridgeA1 Capture", 0, SND_SOC_NOPM, 0,
108-
0),
109-
};
110-
111-
static const struct snd_soc_dapm_route gbcodec_dapm_routes[] = {
112-
/* Playback path */
113-
{"Spk", NULL, "SPKOUT"},
114-
{"SPKOUT", NULL, "SPK Amp"},
115-
{"SPK Amp", "Switch", "SPK DAC"},
116-
{"SPK DAC", NULL, "SPK Mixer"},
117-
118-
{"HP", NULL, "HPOUT"},
119-
{"HPOUT", NULL, "HP Amp"},
120-
{"HP Amp", "Switch", "HP DAC"},
121-
{"HP DAC", NULL, "HP Mixer"},
122-
123-
{"SPK Mixer", NULL, "APB1_RX Mux"},
124-
{"HP Mixer", NULL, "APB1_RX Mux"},
125-
126-
{"APB1_RX Mux", "Left", "APB1RX"},
127-
{"APB1_RX Mux", "Right", "APB1RX"},
128-
{"APB1_RX Mux", "Stereo", "APB1RX"},
129-
130-
/* Capture path */
131-
{"MIC", NULL, "Int Mic"},
132-
{"MIC", NULL, "MIC Mux"},
133-
{"MIC Mux", "Left", "MIC ADC"},
134-
{"MIC Mux", "Right", "MIC ADC"},
135-
{"MIC Mux", "Stereo", "MIC ADC"},
136-
{"MIC ADC", "Switch", "APB1_TX Mixer"},
137-
{"APB1_TX Mixer", NULL, "APB1TX"}
138-
};
139-
14022
static int gbcodec_startup(struct snd_pcm_substream *substream,
14123
struct snd_soc_dai *dai)
14224
{
@@ -180,24 +62,9 @@ static struct snd_soc_dai_ops gbcodec_dai_ops = {
18062
.digital_mute = gbcodec_digital_mute,
18163
};
18264

183-
static struct snd_soc_dai_driver gbcodec_dai = {
184-
.playback = {
185-
.stream_name = "APBridgeA1 Playback",
186-
.channels_min = 1,
187-
.channels_max = 2,
188-
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
189-
.formats = SNDRV_PCM_FMTBIT_S16_LE,
190-
},
191-
.capture = {
192-
.stream_name = "APBridgeA1 Capture",
193-
.channels_min = 2,
194-
.channels_max = 2,
195-
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
196-
.formats = SNDRV_PCM_FMTBIT_S16_LE,
197-
},
198-
.ops = &gbcodec_dai_ops,
199-
};
200-
65+
/*
66+
* codec driver ops
67+
*/
20168
static int gbcodec_probe(struct snd_soc_codec *codec)
20269
{
20370
/* Empty function for now */
@@ -261,13 +128,6 @@ static struct snd_soc_codec_driver soc_codec_dev_gbcodec = {
261128
.reg_word_size = 1,
262129

263130
.idle_bias_off = true,
264-
265-
.controls = gbcodec_snd_controls,
266-
.num_controls = ARRAY_SIZE(gbcodec_snd_controls),
267-
.dapm_widgets = gbcodec_dapm_widgets,
268-
.num_dapm_widgets = ARRAY_SIZE(gbcodec_dapm_widgets),
269-
.dapm_routes = gbcodec_dapm_routes,
270-
.num_dapm_routes = ARRAY_SIZE(gbcodec_dapm_routes),
271131
};
272132

273133
/*
@@ -369,6 +229,9 @@ static struct gbaudio_codec_info *gbaudio_get_codec(struct device *dev,
369229

370230
mutex_init(&gbcodec->lock);
371231
INIT_LIST_HEAD(&gbcodec->dai_list);
232+
INIT_LIST_HEAD(&gbcodec->widget_list);
233+
INIT_LIST_HEAD(&gbcodec->codec_ctl_list);
234+
INIT_LIST_HEAD(&gbcodec->widget_ctl_list);
372235
gbcodec->dev_id = dev_id;
373236
dev_set_drvdata(dev, gbcodec);
374237
gbcodec->dev = dev;
@@ -412,8 +275,9 @@ struct device_driver gb_codec_driver = {
412275

413276
static int gbaudio_codec_probe(struct gb_connection *connection)
414277
{
415-
int ret;
278+
int ret, i;
416279
struct gbaudio_codec_info *gbcodec;
280+
struct gb_audio_topology *topology;
417281
struct device *dev = &connection->bundle->dev;
418282
int dev_id = connection->bundle->id;
419283

@@ -425,8 +289,35 @@ static int gbaudio_codec_probe(struct gb_connection *connection)
425289

426290
gbcodec->mgmt_connection = connection;
427291

292+
/* fetch topology data */
293+
ret = gb_audio_gb_get_topology(connection, &topology);
294+
if (ret) {
295+
dev_err(gbcodec->dev,
296+
"%d:Error while fetching topology\n", ret);
297+
goto base_error;
298+
}
299+
300+
/* process topology data */
301+
ret = gbaudio_tplg_parse_data(gbcodec, topology);
302+
if (ret) {
303+
dev_err(dev, "%d:Error while parsing topology data\n",
304+
ret);
305+
goto topology_error;
306+
}
307+
gbcodec->topology = topology;
308+
309+
/* update codec info */
310+
soc_codec_dev_gbcodec.controls = gbcodec->kctls;
311+
soc_codec_dev_gbcodec.num_controls = gbcodec->num_kcontrols;
312+
soc_codec_dev_gbcodec.dapm_widgets = gbcodec->widgets;
313+
soc_codec_dev_gbcodec.num_dapm_widgets = gbcodec->num_dapm_widgets;
314+
soc_codec_dev_gbcodec.dapm_routes = gbcodec->routes;
315+
soc_codec_dev_gbcodec.num_dapm_routes = gbcodec->num_dapm_routes;
316+
428317
/* update DAI info */
429-
gbcodec->dais = &gbcodec_dai;
318+
for (i = 0; i < gbcodec->num_dais; i++)
319+
gbcodec->dais[i].ops = &gbcodec_dai_ops;
320+
430321
/* FIXME */
431322
dev->driver = &gb_codec_driver;
432323

@@ -435,7 +326,7 @@ static int gbaudio_codec_probe(struct gb_connection *connection)
435326
gbcodec->dais, 1);
436327
if (ret) {
437328
dev_err(dev, "%d:Failed to register codec\n", ret);
438-
goto base_error;
329+
goto parse_error;
439330
}
440331

441332
/* update DAI links in response to this codec */
@@ -455,8 +346,13 @@ static int gbaudio_codec_probe(struct gb_connection *connection)
455346

456347
codec_reg_error:
457348
snd_soc_unregister_codec(dev);
458-
base_error:
459349
dev->driver = NULL;
350+
parse_error:
351+
gbaudio_tplg_release(gbcodec);
352+
gbcodec->topology = NULL;
353+
topology_error:
354+
kfree(topology);
355+
base_error:
460356
gbcodec->mgmt_connection = NULL;
461357
return ret;
462358
}
@@ -480,6 +376,8 @@ static void gbaudio_codec_remove(struct gb_connection *connection)
480376

481377
snd_soc_unregister_codec(dev);
482378
dev->driver = NULL;
379+
gbaudio_tplg_release(gbcodec);
380+
kfree(gbcodec->topology);
483381
gbcodec->mgmt_connection = NULL;
484382
mutex_lock(&gbcodec->lock);
485383
gbcodec->codec_registered = 0;
@@ -509,68 +407,6 @@ static struct gb_protocol gb_audio_mgmt_protocol = {
509407
.request_recv = gbaudio_codec_report_event_recv,
510408
};
511409

512-
static struct gbaudio_dai *gbaudio_allocate_dai(struct gbaudio_codec_info *gb,
513-
int data_cport,
514-
struct gb_connection *connection,
515-
const char *name)
516-
{
517-
struct gbaudio_dai *dai;
518-
519-
mutex_lock(&gb->lock);
520-
dai = devm_kzalloc(gb->dev, sizeof(*dai), GFP_KERNEL);
521-
if (!dai) {
522-
dev_err(gb->dev, "%s:DAI Malloc failure\n", name);
523-
mutex_unlock(&gb->lock);
524-
return NULL;
525-
}
526-
527-
dai->data_cport = data_cport;
528-
dai->connection = connection;
529-
530-
/* update name */
531-
if (name)
532-
strlcpy(dai->name, name, NAME_SIZE);
533-
list_add(&dai->list, &gb->dai_list);
534-
dev_dbg(gb->dev, "%d:%s: DAI added\n", data_cport, dai->name);
535-
mutex_unlock(&gb->lock);
536-
537-
return dai;
538-
}
539-
540-
struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec,
541-
int data_cport,
542-
struct gb_connection *connection,
543-
const char *name)
544-
{
545-
struct gbaudio_dai *dai, *_dai;
546-
547-
/* FIXME need to take care for multiple DAIs */
548-
mutex_lock(&gbcodec->lock);
549-
if (list_empty(&gbcodec->dai_list)) {
550-
mutex_unlock(&gbcodec->lock);
551-
return gbaudio_allocate_dai(gbcodec, data_cport, connection,
552-
name);
553-
}
554-
555-
list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) {
556-
if (dai->data_cport == data_cport) {
557-
if (connection)
558-
dai->connection = connection;
559-
560-
if (name)
561-
strlcpy(dai->name, name, NAME_SIZE);
562-
dev_dbg(gbcodec->dev, "%d:%s: DAI updated\n",
563-
data_cport, dai->name);
564-
mutex_unlock(&gbcodec->lock);
565-
return dai;
566-
}
567-
}
568-
569-
dev_err(gbcodec->dev, "%s:DAI not found\n", name);
570-
mutex_unlock(&gbcodec->lock);
571-
return NULL;
572-
}
573-
574410
static int gbaudio_dai_probe(struct gb_connection *connection)
575411
{
576412
struct gbaudio_dai *dai;

drivers/staging/greybus/audio_codec.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = {
6868
GBCODEC_APB2_MUX_REG_DEFAULT,
6969
};
7070

71+
struct gbaudio_widget {
72+
__u8 id;
73+
const char *name;
74+
struct list_head list;
75+
};
76+
77+
struct gbaudio_control {
78+
__u8 id;
79+
char *name;
80+
const char * const *texts;
81+
struct list_head list;
82+
};
83+
7184
struct gbaudio_dai {
7285
__le16 data_cport;
7386
char name[NAME_SIZE];
@@ -87,6 +100,7 @@ struct gbaudio_codec_info {
87100
char vstr[NAME_SIZE];
88101
char pstr[NAME_SIZE];
89102
struct list_head list;
103+
struct gb_audio_topology *topology;
90104
char name[NAME_SIZE];
91105

92106
/* soc related data */
@@ -105,17 +119,34 @@ struct gbaudio_codec_info {
105119
int num_kcontrols;
106120
int num_dapm_widgets;
107121
int num_dapm_routes;
122+
unsigned long dai_offset;
123+
unsigned long widget_offset;
124+
unsigned long control_offset;
125+
unsigned long route_offset;
108126
struct snd_kcontrol_new *kctls;
109127
struct snd_soc_dapm_widget *widgets;
110128
struct snd_soc_dapm_route *routes;
111129
struct snd_soc_dai_driver *dais;
112130

113131
/* lists */
114132
struct list_head dai_list;
133+
struct list_head widget_list;
134+
struct list_head codec_ctl_list;
135+
struct list_head widget_ctl_list;
115136
struct mutex lock;
116137
};
117138

139+
struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec,
140+
int data_cport,
141+
struct gb_connection *connection,
142+
const char *name);
143+
int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec,
144+
struct gb_audio_topology *tplg_data);
145+
void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec);
146+
118147
/* protocol related */
148+
extern int gb_audio_gb_get_topology(struct gb_connection *connection,
149+
struct gb_audio_topology **topology);
119150
extern int gb_audio_gb_get_control(struct gb_connection *connection,
120151
uint8_t control_id, uint8_t index,
121152
struct gb_audio_ctl_elem_value *value);

0 commit comments

Comments
 (0)