blob: 1651c14c87ba95aab70b6a9b4da61abc207c9027 [file] [log] [blame]
Vaibhav Agarwal6339d232016-01-13 14:07:51 -07001/*
2 * Greybus audio driver
3 * Copyright 2015-2016 Google Inc.
4 * Copyright 2015-2016 Linaro Ltd.
5 *
6 * Released under the GPLv2 only.
7 */
8
9#include "audio_codec.h"
10#include "greybus_protocols.h"
11
12#define GBAUDIO_INVALID_ID 0xFF
13
14/* mixer control */
15struct gb_mixer_control {
16 int min, max;
17 unsigned int reg, rreg, shift, rshift, invert;
18};
19
20struct gbaudio_ctl_pvt {
21 unsigned int ctl_id;
22 unsigned int data_cport;
23 unsigned int access;
24 unsigned int vcount;
25 struct gb_audio_ctl_elem_info *info;
26};
27
28static const char *gbaudio_map_controlid(struct gbaudio_codec_info *gbcodec,
29 __u8 control_id, __u8 index)
30{
31 struct gbaudio_control *control;
32
33 if (control_id == GBAUDIO_INVALID_ID)
34 return NULL;
35
36 list_for_each_entry(control, &gbcodec->codec_ctl_list, list) {
37 if (control->id == control_id) {
38 if (index == GBAUDIO_INVALID_ID)
39 return control->name;
40 return control->texts[index];
41 }
42 }
43 list_for_each_entry(control, &gbcodec->widget_ctl_list, list) {
44 if (control->id == control_id) {
45 if (index == GBAUDIO_INVALID_ID)
46 return control->name;
47 return control->texts[index];
48 }
49 }
50 return NULL;
51}
52
53static int gbaudio_map_widgetname(struct gbaudio_codec_info *gbcodec,
54 const char *name)
55{
56 struct gbaudio_widget *widget;
57 char widget_name[NAME_SIZE];
58 char prefix_name[NAME_SIZE];
59
60 snprintf(prefix_name, NAME_SIZE, "GB %d ", gbcodec->dev_id);
61 if (strncmp(name, prefix_name, strlen(prefix_name)))
62 return -EINVAL;
63
64 strlcpy(widget_name, name+strlen(prefix_name), NAME_SIZE);
65 dev_dbg(gbcodec->dev, "widget_name:%s, truncated widget_name:%s\n",
66 name, widget_name);
67
68 list_for_each_entry(widget, &gbcodec->widget_list, list) {
69 if (!strncmp(widget->name, widget_name, NAME_SIZE))
70 return widget->id;
71 }
72 return -EINVAL;
73}
74
75static const char *gbaudio_map_widgetid(struct gbaudio_codec_info *gbcodec,
76 __u8 widget_id)
77{
78 struct gbaudio_widget *widget;
79
80 list_for_each_entry(widget, &gbcodec->widget_list, list) {
81 if (widget->id == widget_id)
82 return widget->name;
83 }
84 return NULL;
85}
86
87static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol,
88 struct snd_ctl_elem_info *uinfo)
89{
90 unsigned int max;
91 const char *name;
92 struct gbaudio_ctl_pvt *data;
93 struct gb_audio_ctl_elem_info *info;
94 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Vaibhav Agarwal796fad42016-01-28 21:15:39 +053095 struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec);
Vaibhav Agarwal6339d232016-01-13 14:07:51 -070096
97 data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
98 info = (struct gb_audio_ctl_elem_info *)data->info;
99
100 if (!info) {
101 dev_err(gbcodec->dev, "NULL info for %s\n", uinfo->id.name);
102 return -EINVAL;
103 }
104
105 /* update uinfo */
106 uinfo->access = data->access;
107 uinfo->count = data->vcount;
108 uinfo->type = (snd_ctl_elem_type_t)info->type;
109
110 switch (info->type) {
111 case GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN:
112 case GB_AUDIO_CTL_ELEM_TYPE_INTEGER:
113 uinfo->value.integer.min = info->value.integer.min;
114 uinfo->value.integer.max = info->value.integer.max;
115 break;
116 case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED:
117 max = info->value.enumerated.items;
118 uinfo->value.enumerated.items = max;
119 if (uinfo->value.enumerated.item > max - 1)
120 uinfo->value.enumerated.item = max - 1;
121 name = gbaudio_map_controlid(gbcodec, data->ctl_id,
122 uinfo->value.enumerated.item);
123 strlcpy(uinfo->value.enumerated.name, name, NAME_SIZE);
124 break;
125 default:
126 dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n",
127 info->type, kcontrol->id.name);
128 break;
129 }
130 return 0;
131}
132
133static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol,
134 struct snd_ctl_elem_value *ucontrol)
135{
136 int ret;
137 struct gb_audio_ctl_elem_info *info;
138 struct gbaudio_ctl_pvt *data;
139 struct gb_audio_ctl_elem_value gbvalue;
140 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Vaibhav Agarwal796fad42016-01-28 21:15:39 +0530141 struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec);
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700142
Vaibhav Agarwal3994e0b2016-01-28 21:15:40 +0530143 if (!atomic_read(&gb->is_connected))
144 return -ENODEV;
145
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700146 data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
147 info = (struct gb_audio_ctl_elem_info *)data->info;
148
149 ret = gb_audio_gb_get_control(gb->mgmt_connection, data->ctl_id,
150 GB_AUDIO_INVALID_INDEX, &gbvalue);
151 if (ret) {
152 dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__,
153 kcontrol->id.name);
154 return ret;
155 }
156
157 /* update ucontrol */
158 switch (info->type) {
159 case GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN:
160 case GB_AUDIO_CTL_ELEM_TYPE_INTEGER:
161 ucontrol->value.integer.value[0] =
162 gbvalue.value.integer_value[0];
163 if (data->vcount == 2)
164 ucontrol->value.integer.value[1] =
165 gbvalue.value.integer_value[1];
166 break;
167 case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED:
168 ucontrol->value.enumerated.item[0] =
169 gbvalue.value.enumerated_item[0];
170 if (data->vcount == 2)
171 ucontrol->value.enumerated.item[1] =
172 gbvalue.value.enumerated_item[1];
173 break;
174 default:
175 dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n",
176 info->type, kcontrol->id.name);
177 ret = -EINVAL;
178 break;
179 }
180 return ret;
181}
182
183static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol,
184 struct snd_ctl_elem_value *ucontrol)
185{
186 int ret = 0;
187 struct gb_audio_ctl_elem_info *info;
188 struct gbaudio_ctl_pvt *data;
189 struct gb_audio_ctl_elem_value gbvalue;
190 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Vaibhav Agarwal796fad42016-01-28 21:15:39 +0530191 struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec);
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700192
Vaibhav Agarwal3994e0b2016-01-28 21:15:40 +0530193 if (!atomic_read(&gb->is_connected))
194 return -ENODEV;
195
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700196 data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
197 info = (struct gb_audio_ctl_elem_info *)data->info;
198
199 /* update ucontrol */
200 switch (info->type) {
201 case GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN:
202 case GB_AUDIO_CTL_ELEM_TYPE_INTEGER:
203 gbvalue.value.integer_value[0] =
204 ucontrol->value.integer.value[0];
205 if (data->vcount == 2)
206 gbvalue.value.integer_value[1] =
207 ucontrol->value.integer.value[1];
208 break;
209 case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED:
210 gbvalue.value.enumerated_item[0] =
211 ucontrol->value.enumerated.item[0];
212 if (data->vcount == 2)
213 gbvalue.value.enumerated_item[1] =
214 ucontrol->value.enumerated.item[1];
215 break;
216 default:
217 dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n",
218 info->type, kcontrol->id.name);
219 ret = -EINVAL;
220 break;
221 }
222
223 if (ret)
224 return ret;
225
226 ret = gb_audio_gb_set_control(gb->mgmt_connection, data->ctl_id,
227 GB_AUDIO_INVALID_INDEX, &gbvalue);
228 if (ret) {
229 dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__,
230 kcontrol->id.name);
231 }
232
233 return ret;
234}
235
236#define SOC_MIXER_GB(xname, kcount, data) \
237{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
238 .count = kcount, .info = gbcodec_mixer_ctl_info, \
239 .get = gbcodec_mixer_ctl_get, .put = gbcodec_mixer_ctl_put, \
240 .private_value = (unsigned long)data }
241
242/*
243 * although below callback functions seems redundant to above functions.
244 * same are kept to allow provision for different handling in case
245 * of DAPM related sequencing, etc.
246 */
247static int gbcodec_mixer_dapm_ctl_info(struct snd_kcontrol *kcontrol,
248 struct snd_ctl_elem_info *uinfo)
249{
250 int platform_max, platform_min;
251 struct gbaudio_ctl_pvt *data;
252 struct gb_audio_ctl_elem_info *info;
253
254 data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
255 info = (struct gb_audio_ctl_elem_info *)data->info;
256
257 /* update uinfo */
258 platform_max = info->value.integer.max;
259 platform_min = info->value.integer.min;
260
261 if (platform_max == 1 &&
262 !strnstr(kcontrol->id.name, " Volume", NAME_SIZE))
263 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
264 else
265 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
266
267 uinfo->count = data->vcount;
268 uinfo->value.integer.min = 0;
269 if (info->value.integer.min < 0 &&
270 (uinfo->type == SNDRV_CTL_ELEM_TYPE_INTEGER))
271 uinfo->value.integer.max = platform_max - platform_min;
272 else
273 uinfo->value.integer.max = platform_max;
274
275 return 0;
276}
277
278static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol,
279 struct snd_ctl_elem_value *ucontrol)
280{
281 int ret;
282 struct gb_audio_ctl_elem_info *info;
283 struct gbaudio_ctl_pvt *data;
284 struct gb_audio_ctl_elem_value gbvalue;
285 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
286 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
287 struct snd_soc_codec *codec = widget->codec;
Vaibhav Agarwal796fad42016-01-28 21:15:39 +0530288 struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec);
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700289
Vaibhav Agarwal3994e0b2016-01-28 21:15:40 +0530290 if (!atomic_read(&gb->is_connected))
291 return -ENODEV;
292
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700293 data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
294 info = (struct gb_audio_ctl_elem_info *)data->info;
295
296 if (data->vcount == 2)
297 dev_warn(widget->dapm->dev,
298 "GB: Control '%s' is stereo, which is not supported\n",
299 kcontrol->id.name);
300
301 ret = gb_audio_gb_get_control(gb->mgmt_connection, data->ctl_id,
302 GB_AUDIO_INVALID_INDEX, &gbvalue);
303 if (ret) {
304 dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__,
305 kcontrol->id.name);
306 return ret;
307 }
308 /* update ucontrol */
309 ucontrol->value.integer.value[0] = gbvalue.value.integer_value[0];
310
311 return ret;
312}
313
314static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol,
315 struct snd_ctl_elem_value *ucontrol)
316{
317 int ret, wi, max, connect;
318 unsigned int mask, val;
319 struct gb_audio_ctl_elem_info *info;
320 struct gbaudio_ctl_pvt *data;
321 struct gb_audio_ctl_elem_value gbvalue;
322 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
323 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
324 struct snd_soc_codec *codec = widget->codec;
Vaibhav Agarwal796fad42016-01-28 21:15:39 +0530325 struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec);
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700326
Vaibhav Agarwal3994e0b2016-01-28 21:15:40 +0530327 if (!atomic_read(&gb->is_connected))
328 return -ENODEV;
329
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700330 data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
331 info = (struct gb_audio_ctl_elem_info *)data->info;
332
333 if (data->vcount == 2)
334 dev_warn(widget->dapm->dev,
335 "GB: Control '%s' is stereo, which is not supported\n",
336 kcontrol->id.name);
337
338 max = info->value.integer.max;
339 mask = (1 << fls(max)) - 1;
340 val = (ucontrol->value.integer.value[0] & mask);
341 connect = !!val;
342
343 /* update ucontrol */
344 if (gbvalue.value.integer_value[0] != val) {
345 for (wi = 0; wi < wlist->num_widgets; wi++) {
346 widget = wlist->widgets[wi];
347
348 widget->value = val;
349 widget->dapm->update = NULL;
350 snd_soc_dapm_mixer_update_power(widget, kcontrol,
351 connect);
352 }
353 gbvalue.value.integer_value[0] =
354 ucontrol->value.integer.value[0];
355 ret = gb_audio_gb_set_control(gb->mgmt_connection,
356 data->ctl_id,
357 GB_AUDIO_INVALID_INDEX, &gbvalue);
358 if (ret) {
359 dev_err(codec->dev,
360 "%d:Error in %s for %s\n", ret, __func__,
361 kcontrol->id.name);
362 }
363 }
364
365 return ret;
366}
367
368#define SOC_DAPM_MIXER_GB(xname, kcount, data) \
369{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
370 .count = kcount, .info = gbcodec_mixer_dapm_ctl_info, \
371 .get = gbcodec_mixer_dapm_ctl_get, .put = gbcodec_mixer_dapm_ctl_put, \
372 .private_value = (unsigned long)data}
373
374static int gbcodec_event_spk(struct snd_soc_dapm_widget *w,
375 struct snd_kcontrol *k, int event)
376{
377 /* Ensure GB speaker is connected */
378
379 return 0;
380}
381
382static int gbcodec_event_hp(struct snd_soc_dapm_widget *w,
383 struct snd_kcontrol *k, int event)
384{
385 /* Ensure GB module supports jack slot */
386
387 return 0;
388}
389
390static int gbcodec_event_int_mic(struct snd_soc_dapm_widget *w,
391 struct snd_kcontrol *k, int event)
392{
393 /* Ensure GB module supports jack slot */
394
395 return 0;
396}
397
398static int gbaudio_validate_kcontrol_count(struct gb_audio_widget *w)
399{
400 int ret = 0;
401
402 switch (w->type) {
403 case snd_soc_dapm_spk:
404 case snd_soc_dapm_hp:
405 case snd_soc_dapm_mic:
406 case snd_soc_dapm_output:
407 case snd_soc_dapm_input:
408 if (w->ncontrols)
409 ret = -EINVAL;
410 break;
411 case snd_soc_dapm_switch:
412 case snd_soc_dapm_mux:
413 if (w->ncontrols != 1)
414 ret = -EINVAL;
415 break;
416 default:
417 break;
418 }
419
420 return ret;
421}
422
423static int gbaudio_tplg_create_kcontrol(struct gbaudio_codec_info *gb,
424 struct snd_kcontrol_new *kctl,
425 struct gb_audio_control *ctl)
426{
427 struct gbaudio_ctl_pvt *ctldata;
428
429 switch (ctl->iface) {
430 case SNDRV_CTL_ELEM_IFACE_MIXER:
431 ctldata = devm_kzalloc(gb->dev, sizeof(struct gbaudio_ctl_pvt),
432 GFP_KERNEL);
433 if (!ctldata)
434 return -ENOMEM;
435 ctldata->ctl_id = ctl->id;
436 ctldata->data_cport = ctl->data_cport;
437 ctldata->access = ctl->access;
438 ctldata->vcount = ctl->count_values;
439 ctldata->info = &ctl->info;
440 *kctl = (struct snd_kcontrol_new)
441 SOC_MIXER_GB(ctl->name, ctl->count, ctldata);
442 ctldata = NULL;
443 break;
444 default:
445 return -EINVAL;
446 }
447
448 dev_dbg(gb->dev, "%s:%d control created\n", ctl->name, ctl->id);
449 return 0;
450}
451
452static const char * const gbtexts[] = {"Stereo", "Left", "Right"};
453
454static const SOC_ENUM_SINGLE_DECL(
455 gbcodec_apb1_rx_enum, GBCODEC_APB1_MUX_REG, 0, gbtexts);
456
457static const SOC_ENUM_SINGLE_DECL(
458 gbcodec_mic_enum, GBCODEC_APB1_MUX_REG, 4, gbtexts);
459
460static int gbaudio_tplg_create_enum_ctl(struct gbaudio_codec_info *gb,
461 struct snd_kcontrol_new *kctl,
462 struct gb_audio_control *ctl)
463{
464 switch (ctl->id) {
465 case 8:
466 *kctl = (struct snd_kcontrol_new)
467 SOC_DAPM_ENUM(ctl->name, gbcodec_apb1_rx_enum);
468 break;
469 case 9:
470 *kctl = (struct snd_kcontrol_new)
471 SOC_DAPM_ENUM(ctl->name, gbcodec_mic_enum);
472 break;
473 default:
474 return -EINVAL;
475 }
476
477 return 0;
478}
479
480static int gbaudio_tplg_create_mixer_ctl(struct gbaudio_codec_info *gb,
481 struct snd_kcontrol_new *kctl,
482 struct gb_audio_control *ctl)
483{
484 struct gbaudio_ctl_pvt *ctldata;
485
486 ctldata = devm_kzalloc(gb->dev, sizeof(struct gbaudio_ctl_pvt),
487 GFP_KERNEL);
488 if (!ctldata)
489 return -ENOMEM;
490 ctldata->ctl_id = ctl->id;
491 ctldata->data_cport = ctl->data_cport;
492 ctldata->access = ctl->access;
493 ctldata->vcount = ctl->count_values;
494 ctldata->info = &ctl->info;
495 *kctl = (struct snd_kcontrol_new)
496 SOC_DAPM_MIXER_GB(ctl->name, ctl->count, ctldata);
497
498 return 0;
499}
500
501static int gbaudio_tplg_create_wcontrol(struct gbaudio_codec_info *gb,
502 struct snd_kcontrol_new *kctl,
503 struct gb_audio_control *ctl)
504{
505 int ret;
506
507 switch (ctl->iface) {
508 case SNDRV_CTL_ELEM_IFACE_MIXER:
509 switch (ctl->info.type) {
510 case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED:
511 ret = gbaudio_tplg_create_enum_ctl(gb, kctl, ctl);
512 break;
513 default:
514 ret = gbaudio_tplg_create_mixer_ctl(gb, kctl, ctl);
515 break;
516 }
517 break;
518 default:
519 return -EINVAL;
520
521 }
522
523 dev_dbg(gb->dev, "%s:%d DAPM control created, ret:%d\n", ctl->name,
524 ctl->id, ret);
525 return ret;
526}
527
528static int gbaudio_widget_event(struct snd_soc_dapm_widget *w,
529 struct snd_kcontrol *kcontrol, int event)
530{
531 int wid;
532 int ret;
533 struct snd_soc_codec *codec = w->codec;
Vaibhav Agarwal796fad42016-01-28 21:15:39 +0530534 struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec);
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700535
536 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
537
538 /* map name to widget id */
539 wid = gbaudio_map_widgetname(gbcodec, w->name);
540 if (wid < 0) {
541 dev_err(codec->dev, "Invalid widget name:%s\n", w->name);
542 return -EINVAL;
543 }
544
545 switch (event) {
546 case SND_SOC_DAPM_PRE_PMU:
547 ret = gb_audio_gb_enable_widget(gbcodec->mgmt_connection, wid);
548 break;
549 case SND_SOC_DAPM_POST_PMD:
550 ret = gb_audio_gb_disable_widget(gbcodec->mgmt_connection, wid);
551 break;
552 }
553 if (ret)
554 dev_err(codec->dev, "%d: widget, event:%d failed:%d\n", wid,
555 event, ret);
556 return ret;
557}
558
559static int gbaudio_tplg_create_widget(struct gbaudio_codec_info *gbcodec,
560 struct snd_soc_dapm_widget *dw,
561 struct gb_audio_widget *w)
562{
563 int i, ret;
564 struct snd_kcontrol_new *widget_kctls;
565 struct gb_audio_control *curr;
566 struct gbaudio_control *control, *_control;
567 size_t size;
568
569 ret = gbaudio_validate_kcontrol_count(w);
570 if (ret) {
571 dev_err(gbcodec->dev, "Inavlid kcontrol count=%d for %s\n",
572 w->ncontrols, w->name);
573 return ret;
574 }
575
576 /* allocate memory for kcontrol */
577 if (w->ncontrols) {
578 size = sizeof(struct snd_kcontrol_new) * w->ncontrols;
579 widget_kctls = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL);
580 if (!widget_kctls)
581 return -ENOMEM;
582 }
583
584 /* create relevant kcontrols */
585 for (i = 0; i < w->ncontrols; i++) {
586 curr = &w->ctl[i];
587 ret = gbaudio_tplg_create_wcontrol(gbcodec, &widget_kctls[i],
588 curr);
589 if (ret) {
590 dev_err(gbcodec->dev,
591 "%s:%d type widget_ctl not supported\n",
592 curr->name, curr->iface);
593 goto error;
594 }
595 control = devm_kzalloc(gbcodec->dev,
596 sizeof(struct gbaudio_control),
597 GFP_KERNEL);
598 if (!control) {
599 ret = -ENOMEM;
600 goto error;
601 }
602 control->id = curr->id;
603 control->name = curr->name;
604 if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED)
605 control->texts = (const char * const *)
606 curr->info.value.enumerated.names;
607 list_add(&control->list, &gbcodec->widget_ctl_list);
608 dev_dbg(gbcodec->dev, "%s: control of type %d created\n",
609 widget_kctls[i].name, widget_kctls[i].iface);
610 }
611
612 switch (w->type) {
613 case snd_soc_dapm_spk:
614 *dw = (struct snd_soc_dapm_widget)
615 SND_SOC_DAPM_SPK(w->name, gbcodec_event_spk);
616 break;
617 case snd_soc_dapm_hp:
618 *dw = (struct snd_soc_dapm_widget)
619 SND_SOC_DAPM_HP(w->name, gbcodec_event_hp);
620 break;
621 case snd_soc_dapm_mic:
622 *dw = (struct snd_soc_dapm_widget)
623 SND_SOC_DAPM_MIC(w->name, gbcodec_event_int_mic);
624 break;
625 case snd_soc_dapm_output:
626 *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_OUTPUT(w->name);
627 break;
628 case snd_soc_dapm_input:
629 *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_INPUT(w->name);
630 break;
631 case snd_soc_dapm_switch:
632 *dw = (struct snd_soc_dapm_widget)
633 SND_SOC_DAPM_SWITCH_E(w->name, SND_SOC_NOPM, 0, 0,
634 widget_kctls, gbaudio_widget_event,
635 SND_SOC_DAPM_PRE_PMU |
636 SND_SOC_DAPM_POST_PMD);
637 break;
638 case snd_soc_dapm_pga:
639 *dw = (struct snd_soc_dapm_widget)
640 SND_SOC_DAPM_PGA_E(w->name, SND_SOC_NOPM, 0, 0, NULL, 0,
641 gbaudio_widget_event,
642 SND_SOC_DAPM_PRE_PMU |
643 SND_SOC_DAPM_POST_PMD);
644 break;
645 case snd_soc_dapm_mixer:
646 *dw = (struct snd_soc_dapm_widget)
647 SND_SOC_DAPM_MIXER_E(w->name, SND_SOC_NOPM, 0, 0, NULL,
648 0, gbaudio_widget_event,
649 SND_SOC_DAPM_PRE_PMU |
650 SND_SOC_DAPM_POST_PMD);
651 break;
652 case snd_soc_dapm_mux:
653 *dw = (struct snd_soc_dapm_widget)
654 SND_SOC_DAPM_MUX_E(w->name, SND_SOC_NOPM, 0, 0,
655 widget_kctls, gbaudio_widget_event,
656 SND_SOC_DAPM_PRE_PMU |
657 SND_SOC_DAPM_POST_PMD);
658 break;
659 case snd_soc_dapm_aif_in:
660 *dw = (struct snd_soc_dapm_widget)
661 SND_SOC_DAPM_AIF_IN_E(w->name, w->sname, 0,
662 SND_SOC_NOPM,
663 0, 0, gbaudio_widget_event,
664 SND_SOC_DAPM_PRE_PMU |
665 SND_SOC_DAPM_POST_PMD);
666 break;
667 case snd_soc_dapm_aif_out:
668 *dw = (struct snd_soc_dapm_widget)
669 SND_SOC_DAPM_AIF_OUT_E(w->name, w->sname, 0,
670 SND_SOC_NOPM,
671 0, 0, gbaudio_widget_event,
672 SND_SOC_DAPM_PRE_PMU |
673 SND_SOC_DAPM_POST_PMD);
674 break;
675 default:
676 ret = -EINVAL;
677 goto error;
678 }
679
680 dev_dbg(gbcodec->dev, "%s: widget of type %d created\n", dw->name,
681 dw->id);
682 return 0;
683error:
684 list_for_each_entry_safe(control, _control, &gbcodec->widget_ctl_list,
685 list) {
686 list_del(&control->list);
687 devm_kfree(gbcodec->dev, control);
688 }
689 return ret;
690}
691
692static int gbaudio_tplg_create_dai(struct gbaudio_codec_info *gbcodec,
693 struct snd_soc_dai_driver *gb_dai,
694 struct gb_audio_dai *dai)
695{
696 /*
697 * do not update name here,
698 * append dev_id before assigning it here
699 */
700
701 gb_dai->playback.stream_name = dai->playback.stream_name;
702 gb_dai->playback.channels_min = dai->playback.chan_min;
703 gb_dai->playback.channels_max = dai->playback.chan_max;
704 gb_dai->playback.formats = dai->playback.formats;
705 gb_dai->playback.rates = dai->playback.rates;
706 gb_dai->playback.sig_bits = dai->playback.sig_bits;
707
708 gb_dai->capture.stream_name = dai->capture.stream_name;
709 gb_dai->capture.channels_min = dai->capture.chan_min;
710 gb_dai->capture.channels_max = dai->capture.chan_max;
711 gb_dai->capture.formats = dai->capture.formats;
712 gb_dai->capture.rates = dai->capture.rates;
713 gb_dai->capture.sig_bits = dai->capture.sig_bits;
714
715 return 0;
716}
717
718static int gbaudio_tplg_process_kcontrols(struct gbaudio_codec_info *gbcodec,
719 struct gb_audio_control *controls)
720{
721 int i, ret;
722 struct snd_kcontrol_new *dapm_kctls;
723 struct gb_audio_control *curr;
724 struct gbaudio_control *control, *_control;
725 size_t size;
726
727 size = sizeof(struct snd_kcontrol_new) * gbcodec->num_kcontrols;
728 dapm_kctls = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL);
729 if (!dapm_kctls)
730 return -ENOMEM;
731
732 curr = controls;
733 for (i = 0; i < gbcodec->num_kcontrols; i++) {
734 ret = gbaudio_tplg_create_kcontrol(gbcodec, &dapm_kctls[i],
735 curr);
736 if (ret) {
737 dev_err(gbcodec->dev, "%s:%d type not supported\n",
738 curr->name, curr->iface);
739 goto error;
740 }
741 control = devm_kzalloc(gbcodec->dev, sizeof(struct
742 gbaudio_control),
743 GFP_KERNEL);
744 if (!control) {
745 ret = -ENOMEM;
746 goto error;
747 }
748 control->id = curr->id;
749 control->name = curr->name;
750 if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED)
751 control->texts = (const char * const *)
752 curr->info.value.enumerated.names;
753 list_add(&control->list, &gbcodec->codec_ctl_list);
754 dev_dbg(gbcodec->dev, "%d:%s created of type %d\n", curr->id,
755 curr->name, curr->info.type);
756 curr++;
757 }
758 gbcodec->kctls = dapm_kctls;
759
760 return 0;
761error:
762 list_for_each_entry_safe(control, _control, &gbcodec->codec_ctl_list,
763 list) {
764 list_del(&control->list);
765 devm_kfree(gbcodec->dev, control);
766 }
767 devm_kfree(gbcodec->dev, dapm_kctls);
768 return ret;
769}
770
771static int gbaudio_tplg_process_widgets(struct gbaudio_codec_info *gbcodec,
772 struct gb_audio_widget *widgets)
773{
774 int i, ret, ncontrols;
775 struct snd_soc_dapm_widget *dapm_widgets;
776 struct gb_audio_widget *curr;
777 struct gbaudio_widget *widget, *_widget;
778 size_t size;
779
780 size = sizeof(struct snd_soc_dapm_widget) * gbcodec->num_dapm_widgets;
781 dapm_widgets = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL);
782 if (!dapm_widgets)
783 return -ENOMEM;
784
785 curr = widgets;
786 for (i = 0; i < gbcodec->num_dapm_widgets; i++) {
787 ret = gbaudio_tplg_create_widget(gbcodec, &dapm_widgets[i],
788 curr);
789 if (ret) {
790 dev_err(gbcodec->dev, "%s:%d type not supported\n",
791 curr->name, curr->type);
792 goto error;
793 }
794 widget = devm_kzalloc(gbcodec->dev, sizeof(struct
795 gbaudio_widget),
796 GFP_KERNEL);
797 if (!widget) {
798 ret = -ENOMEM;
799 goto error;
800 }
801 widget->id = curr->id;
802 widget->name = curr->name;
803 list_add(&widget->list, &gbcodec->widget_list);
804 ncontrols = curr->ncontrols;
805 curr++;
806 curr += ncontrols * sizeof(struct gb_audio_control);
807 }
808 gbcodec->widgets = dapm_widgets;
809
810 return 0;
811
812error:
813 list_for_each_entry_safe(widget, _widget, &gbcodec->widget_list,
814 list) {
815 list_del(&widget->list);
816 devm_kfree(gbcodec->dev, widget);
817 }
818 devm_kfree(gbcodec->dev, dapm_widgets);
819 return ret;
820}
821
822static int gbaudio_tplg_process_dais(struct gbaudio_codec_info *gbcodec,
823 struct gb_audio_dai *dais)
824{
825 int i, ret;
826 struct snd_soc_dai_driver *gb_dais;
827 struct gb_audio_dai *curr;
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700828 size_t size;
829 char dai_name[NAME_SIZE];
Vaibhav Agarwal796fad42016-01-28 21:15:39 +0530830 struct gbaudio_dai *dai;
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700831
832 size = sizeof(struct snd_soc_dai_driver) * gbcodec->num_dais;
833 gb_dais = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL);
834 if (!gb_dais)
835 return -ENOMEM;
836
837 curr = dais;
838 for (i = 0; i < gbcodec->num_dais; i++) {
839 ret = gbaudio_tplg_create_dai(gbcodec, &gb_dais[i], curr);
840 if (ret) {
841 dev_err(gbcodec->dev, "%s failed to create\n",
842 curr->name);
843 goto error;
844 }
845 /* append dev_id to dai_name */
846 snprintf(dai_name, NAME_SIZE, "%s.%d", curr->name,
847 gbcodec->dev_id);
Vaibhav Agarwal796fad42016-01-28 21:15:39 +0530848 dai = gbaudio_find_dai(gbcodec, curr->data_cport, NULL);
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700849 if (!dai)
850 goto error;
Vaibhav Agarwal796fad42016-01-28 21:15:39 +0530851 strlcpy(dai->name, dai_name, NAME_SIZE);
Vaibhav Agarwal538ecb52016-01-13 14:07:54 -0700852 dev_dbg(gbcodec->dev, "%s:DAI added\n", dai->name);
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700853 gb_dais[i].name = dai->name;
854 curr++;
855 }
856 gbcodec->dais = gb_dais;
857
858 return 0;
859
860error:
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700861 devm_kfree(gbcodec->dev, gb_dais);
862 return ret;
863}
864
865static int gbaudio_tplg_process_routes(struct gbaudio_codec_info *gbcodec,
866 struct gb_audio_route *routes)
867{
868 int i, ret;
869 struct snd_soc_dapm_route *dapm_routes;
870 struct gb_audio_route *curr;
871 size_t size;
872
873 size = sizeof(struct snd_soc_dapm_route) * gbcodec->num_dapm_routes;
874 dapm_routes = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL);
875 if (!dapm_routes)
876 return -ENOMEM;
877
878
879 gbcodec->routes = dapm_routes;
880 curr = routes;
881
882 for (i = 0; i < gbcodec->num_dapm_routes; i++) {
883 dapm_routes->sink =
884 gbaudio_map_widgetid(gbcodec, curr->destination_id);
885 if (!dapm_routes->sink) {
886 dev_err(gbcodec->dev, "%d:%d:%d:%d - Invalid sink\n",
887 curr->source_id, curr->destination_id,
888 curr->control_id, curr->index);
889 ret = -EINVAL;
890 goto error;
891 }
892 dapm_routes->source =
893 gbaudio_map_widgetid(gbcodec, curr->source_id);
894 if (!dapm_routes->source) {
895 dev_err(gbcodec->dev, "%d:%d:%d:%d - Invalid source\n",
896 curr->source_id, curr->destination_id,
897 curr->control_id, curr->index);
898 ret = -EINVAL;
899 goto error;
900 }
901 dapm_routes->control =
902 gbaudio_map_controlid(gbcodec,
903 curr->control_id,
904 curr->index);
905 if ((curr->control_id != GBAUDIO_INVALID_ID) &&
906 !dapm_routes->control) {
907 dev_err(gbcodec->dev, "%d:%d:%d:%d - Invalid control\n",
908 curr->source_id, curr->destination_id,
909 curr->control_id, curr->index);
910 ret = -EINVAL;
911 goto error;
912 }
913 dev_dbg(gbcodec->dev, "Route {%s, %s, %s}\n", dapm_routes->sink,
914 (dapm_routes->control) ? dapm_routes->control:"NULL",
915 dapm_routes->source);
916 dapm_routes++;
917 curr++;
918 }
919
920 return 0;
921
922error:
923 devm_kfree(gbcodec->dev, dapm_routes);
924 return ret;
925}
926
927static int gbaudio_tplg_process_header(struct gbaudio_codec_info *gbcodec,
928 struct gb_audio_topology *tplg_data)
929{
930 /* fetch no. of kcontrols, widgets & routes */
931 gbcodec->num_dais = tplg_data->num_dais;
932 gbcodec->num_kcontrols = tplg_data->num_controls;
933 gbcodec->num_dapm_widgets = tplg_data->num_widgets;
934 gbcodec->num_dapm_routes = tplg_data->num_routes;
935
936 /* update block offset */
937 gbcodec->dai_offset = (unsigned long)&tplg_data->data;
938 gbcodec->control_offset = gbcodec->dai_offset + tplg_data->size_dais;
939 gbcodec->widget_offset = gbcodec->control_offset +
940 tplg_data->size_controls;
941 gbcodec->route_offset = gbcodec->widget_offset +
942 tplg_data->size_widgets;
943
944 dev_dbg(gbcodec->dev, "DAI offset is 0x%lx\n", gbcodec->dai_offset);
945 dev_dbg(gbcodec->dev, "control offset is %lx\n",
946 gbcodec->control_offset);
947 dev_dbg(gbcodec->dev, "widget offset is %lx\n", gbcodec->widget_offset);
948 dev_dbg(gbcodec->dev, "route offset is %lx\n", gbcodec->route_offset);
949
950 return 0;
951}
952
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700953int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec,
954 struct gb_audio_topology *tplg_data)
955{
956 int ret;
957 struct gb_audio_dai *dais;
958 struct gb_audio_control *controls;
959 struct gb_audio_widget *widgets;
960 struct gb_audio_route *routes;
961
962 if (!tplg_data)
963 return -EINVAL;
964
965 ret = gbaudio_tplg_process_header(gbcodec, tplg_data);
966 if (ret) {
967 dev_err(gbcodec->dev, "%d: Error in parsing topology header\n",
968 ret);
969 return ret;
970 }
971
972 /* process control */
973 controls = (struct gb_audio_control *)gbcodec->control_offset;
974 ret = gbaudio_tplg_process_kcontrols(gbcodec, controls);
975 if (ret) {
976 dev_err(gbcodec->dev,
977 "%d: Error in parsing controls data\n", ret);
978 return ret;
979 }
Vaibhav Agarwal538ecb52016-01-13 14:07:54 -0700980 dev_dbg(gbcodec->dev, "Control parsing finished\n");
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700981
982 /* process DAI */
983 dais = (struct gb_audio_dai *)gbcodec->dai_offset;
984 ret = gbaudio_tplg_process_dais(gbcodec, dais);
985 if (ret) {
986 dev_err(gbcodec->dev,
987 "%d: Error in parsing DAIs data\n", ret);
988 return ret;
989 }
Vaibhav Agarwal538ecb52016-01-13 14:07:54 -0700990 dev_dbg(gbcodec->dev, "DAI parsing finished\n");
Vaibhav Agarwal6339d232016-01-13 14:07:51 -0700991
992 /* process widgets */
993 widgets = (struct gb_audio_widget *)gbcodec->widget_offset;
994 ret = gbaudio_tplg_process_widgets(gbcodec, widgets);
995 if (ret) {
996 dev_err(gbcodec->dev,
997 "%d: Error in parsing widgets data\n", ret);
998 return ret;
999 }
Vaibhav Agarwal538ecb52016-01-13 14:07:54 -07001000 dev_dbg(gbcodec->dev, "Widget parsing finished\n");
Vaibhav Agarwal6339d232016-01-13 14:07:51 -07001001
1002 /* process route */
1003 routes = (struct gb_audio_route *)gbcodec->route_offset;
1004 ret = gbaudio_tplg_process_routes(gbcodec, routes);
1005 if (ret) {
1006 dev_err(gbcodec->dev,
1007 "%d: Error in parsing routes data\n", ret);
1008 return ret;
1009 }
Vaibhav Agarwal538ecb52016-01-13 14:07:54 -07001010 dev_dbg(gbcodec->dev, "Route parsing finished\n");
Vaibhav Agarwal6339d232016-01-13 14:07:51 -07001011
1012 return ret;
1013}
1014
1015void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec)
1016{
Vaibhav Agarwal6339d232016-01-13 14:07:51 -07001017 struct gbaudio_control *control, *_control;
1018 struct gbaudio_widget *widget, *_widget;
1019
1020 if (!gbcodec->topology)
1021 return;
1022
1023 /* release kcontrols */
1024 list_for_each_entry_safe(control, _control, &gbcodec->codec_ctl_list,
1025 list) {
1026 list_del(&control->list);
1027 devm_kfree(gbcodec->dev, control);
1028 }
1029 if (gbcodec->kctls)
1030 devm_kfree(gbcodec->dev, gbcodec->kctls);
1031
1032 /* release widget controls */
1033 list_for_each_entry_safe(control, _control, &gbcodec->widget_ctl_list,
1034 list) {
1035 list_del(&control->list);
1036 devm_kfree(gbcodec->dev, control);
1037 }
1038
1039 /* release widgets */
1040 list_for_each_entry_safe(widget, _widget, &gbcodec->widget_list,
1041 list) {
1042 list_del(&widget->list);
1043 devm_kfree(gbcodec->dev, widget);
1044 }
1045 if (gbcodec->widgets)
1046 devm_kfree(gbcodec->dev, gbcodec->widgets);
1047
1048 /* release routes */
1049 if (gbcodec->routes)
1050 devm_kfree(gbcodec->dev, gbcodec->routes);
Vaibhav Agarwal6339d232016-01-13 14:07:51 -07001051}