1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Greybus audio driver
4 * Copyright 2015 Google Inc.
5 * Copyright 2015 Linaro Ltd.
6 */
7#include <linux/kernel.h>
8#include <linux/module.h>
9#include <sound/soc.h>
10#include <sound/pcm_params.h>
11
12#include "audio_codec.h"
13#include "audio_apbridgea.h"
14#include "audio_manager.h"
15
16/*
17 * gb_snd management functions
18 */
19
20static int gbaudio_request_jack(struct gbaudio_module_info *module,
21				struct gb_audio_jack_event_request *req)
22{
23	int report;
24	struct snd_jack *jack = module->headset.jack.jack;
25	struct snd_jack *btn_jack = module->button.jack.jack;
26
27	if (!jack) {
28		dev_err_ratelimited(module->dev,
29				    "Invalid jack event received:type: %u, event: %u\n",
30				    req->jack_attribute, req->event);
31		return -EINVAL;
32	}
33
34	dev_warn_ratelimited(module->dev,
35			     "Jack Event received: type: %u, event: %u\n",
36			     req->jack_attribute, req->event);
37
38	if (req->event == GB_AUDIO_JACK_EVENT_REMOVAL) {
39		module->jack_type = 0;
40		if (btn_jack && module->button_status) {
41			snd_soc_jack_report(&module->button.jack, 0,
42					    module->button_mask);
43			module->button_status = 0;
44		}
45		snd_soc_jack_report(&module->headset.jack, 0,
46				    module->jack_mask);
47		return 0;
48	}
49
50	report = req->jack_attribute & module->jack_mask;
51	if (!report) {
52		dev_err_ratelimited(module->dev,
53				    "Invalid jack event received:type: %u, event: %u\n",
54				    req->jack_attribute, req->event);
55		return -EINVAL;
56	}
57
58	if (module->jack_type)
59		dev_warn_ratelimited(module->dev,
60				     "Modifying jack from %d to %d\n",
61				     module->jack_type, report);
62
63	module->jack_type = report;
64	snd_soc_jack_report(&module->headset.jack, report, module->jack_mask);
65
66	return 0;
67}
68
69static int gbaudio_request_button(struct gbaudio_module_info *module,
70				  struct gb_audio_button_event_request *req)
71{
72	int soc_button_id, report;
73	struct snd_jack *btn_jack = module->button.jack.jack;
74
75	if (!btn_jack) {
76		dev_err_ratelimited(module->dev,
77				    "Invalid button event received:type: %u, event: %u\n",
78				    req->button_id, req->event);
79		return -EINVAL;
80	}
81
82	dev_warn_ratelimited(module->dev,
83			     "Button Event received: id: %u, event: %u\n",
84			     req->button_id, req->event);
85
86	/* currently supports 4 buttons only */
87	if (!module->jack_type) {
88		dev_err_ratelimited(module->dev,
89				    "Jack not present. Bogus event!!\n");
90		return -EINVAL;
91	}
92
93	report = module->button_status & module->button_mask;
94	soc_button_id = 0;
95
96	switch (req->button_id) {
97	case 1:
98		soc_button_id = SND_JACK_BTN_0 & module->button_mask;
99		break;
100
101	case 2:
102		soc_button_id = SND_JACK_BTN_1 & module->button_mask;
103		break;
104
105	case 3:
106		soc_button_id = SND_JACK_BTN_2 & module->button_mask;
107		break;
108
109	case 4:
110		soc_button_id = SND_JACK_BTN_3 & module->button_mask;
111		break;
112	}
113
114	if (!soc_button_id) {
115		dev_err_ratelimited(module->dev,
116				    "Invalid button request received\n");
117		return -EINVAL;
118	}
119
120	if (req->event == GB_AUDIO_BUTTON_EVENT_PRESS)
121		report = report | soc_button_id;
122	else
123		report = report & ~soc_button_id;
124
125	module->button_status = report;
126
127	snd_soc_jack_report(&module->button.jack, report, module->button_mask);
128
129	return 0;
130}
131
132static int gbaudio_request_stream(struct gbaudio_module_info *module,
133				  struct gb_audio_streaming_event_request *req)
134{
135	dev_warn(module->dev, "Audio Event received: cport: %u, event: %u\n",
136		 le16_to_cpu(req->data_cport), req->event);
137
138	return 0;
139}
140
141static int gbaudio_codec_request_handler(struct gb_operation *op)
142{
143	struct gb_connection *connection = op->connection;
144	struct gbaudio_module_info *module =
145		greybus_get_drvdata(connection->bundle);
146	struct gb_operation_msg_hdr *header = op->request->header;
147	struct gb_audio_streaming_event_request *stream_req;
148	struct gb_audio_jack_event_request *jack_req;
149	struct gb_audio_button_event_request *button_req;
150	int ret;
151
152	switch (header->type) {
153	case GB_AUDIO_TYPE_STREAMING_EVENT:
154		stream_req = op->request->payload;
155		ret = gbaudio_request_stream(module, stream_req);
156		break;
157
158	case GB_AUDIO_TYPE_JACK_EVENT:
159		jack_req = op->request->payload;
160		ret = gbaudio_request_jack(module, jack_req);
161		break;
162
163	case GB_AUDIO_TYPE_BUTTON_EVENT:
164		button_req = op->request->payload;
165		ret = gbaudio_request_button(module, button_req);
166		break;
167
168	default:
169		dev_err_ratelimited(&connection->bundle->dev,
170				    "Invalid Audio Event received\n");
171		return -EINVAL;
172	}
173
174	return ret;
175}
176
177static int gb_audio_add_mgmt_connection(struct gbaudio_module_info *gbmodule,
178					struct greybus_descriptor_cport *cport_desc,
179					struct gb_bundle *bundle)
180{
181	struct gb_connection *connection;
182
183	/* Management Cport */
184	if (gbmodule->mgmt_connection) {
185		dev_err(&bundle->dev,
186			"Can't have multiple Management connections\n");
187		return -ENODEV;
188	}
189
190	connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
191					  gbaudio_codec_request_handler);
192	if (IS_ERR(connection))
193		return PTR_ERR(connection);
194
195	greybus_set_drvdata(bundle, gbmodule);
196	gbmodule->mgmt_connection = connection;
197
198	return 0;
199}
200
201static int gb_audio_add_data_connection(struct gbaudio_module_info *gbmodule,
202					struct greybus_descriptor_cport *cport_desc,
203					struct gb_bundle *bundle)
204{
205	struct gb_connection *connection;
206	struct gbaudio_data_connection *dai;
207
208	dai = devm_kzalloc(gbmodule->dev, sizeof(*dai), GFP_KERNEL);
209	if (!dai)
210		return -ENOMEM;
211
212	connection = gb_connection_create_offloaded(bundle,
213						    le16_to_cpu(cport_desc->id),
214						    GB_CONNECTION_FLAG_CSD);
215	if (IS_ERR(connection)) {
216		devm_kfree(gbmodule->dev, dai);
217		return PTR_ERR(connection);
218	}
219
220	greybus_set_drvdata(bundle, gbmodule);
221	dai->id = 0;
222	dai->data_cport = cpu_to_le16(connection->intf_cport_id);
223	dai->connection = connection;
224	list_add(&dai->list, &gbmodule->data_list);
225
226	return 0;
227}
228
229/*
230 * This is the basic hook get things initialized and registered w/ gb
231 */
232
233static int gb_audio_probe(struct gb_bundle *bundle,
234			  const struct greybus_bundle_id *id)
235{
236	struct device *dev = &bundle->dev;
237	struct gbaudio_module_info *gbmodule;
238	struct greybus_descriptor_cport *cport_desc;
239	struct gb_audio_manager_module_descriptor desc;
240	struct gbaudio_data_connection *dai, *_dai;
241	int ret, i;
242	struct gb_audio_topology *topology;
243
244	/* There should be at least one Management and one Data cport */
245	if (bundle->num_cports < 2)
246		return -ENODEV;
247
248	/*
249	 * There can be only one Management connection and any number of data
250	 * connections.
251	 */
252	gbmodule = devm_kzalloc(dev, sizeof(*gbmodule), GFP_KERNEL);
253	if (!gbmodule)
254		return -ENOMEM;
255
256	gbmodule->num_data_connections = bundle->num_cports - 1;
257	INIT_LIST_HEAD(&gbmodule->data_list);
258	INIT_LIST_HEAD(&gbmodule->widget_list);
259	INIT_LIST_HEAD(&gbmodule->ctl_list);
260	INIT_LIST_HEAD(&gbmodule->widget_ctl_list);
261	INIT_LIST_HEAD(&gbmodule->jack_list);
262	gbmodule->dev = dev;
263	snprintf(gbmodule->name, sizeof(gbmodule->name), "%s.%s", dev->driver->name,
264		 dev_name(dev));
265	greybus_set_drvdata(bundle, gbmodule);
266
267	/* Create all connections */
268	for (i = 0; i < bundle->num_cports; i++) {
269		cport_desc = &bundle->cport_desc[i];
270
271		switch (cport_desc->protocol_id) {
272		case GREYBUS_PROTOCOL_AUDIO_MGMT:
273			ret = gb_audio_add_mgmt_connection(gbmodule, cport_desc,
274							   bundle);
275			if (ret)
276				goto destroy_connections;
277			break;
278		case GREYBUS_PROTOCOL_AUDIO_DATA:
279			ret = gb_audio_add_data_connection(gbmodule, cport_desc,
280							   bundle);
281			if (ret)
282				goto destroy_connections;
283			break;
284		default:
285			dev_err(dev, "Unsupported protocol: 0x%02x\n",
286				cport_desc->protocol_id);
287			ret = -ENODEV;
288			goto destroy_connections;
289		}
290	}
291
292	/* There must be a management cport */
293	if (!gbmodule->mgmt_connection) {
294		ret = -EINVAL;
295		dev_err(dev, "Missing management connection\n");
296		goto destroy_connections;
297	}
298
299	/* Initialize management connection */
300	ret = gb_connection_enable(gbmodule->mgmt_connection);
301	if (ret) {
302		dev_err(dev, "%d: Error while enabling mgmt connection\n", ret);
303		goto destroy_connections;
304	}
305	gbmodule->dev_id = gbmodule->mgmt_connection->intf->interface_id;
306
307	/*
308	 * FIXME: malloc for topology happens via audio_gb driver
309	 * should be done within codec driver itself
310	 */
311	ret = gb_audio_gb_get_topology(gbmodule->mgmt_connection, &topology);
312	if (ret) {
313		dev_err(dev, "%d:Error while fetching topology\n", ret);
314		goto disable_connection;
315	}
316
317	/* process topology data */
318	ret = gbaudio_tplg_parse_data(gbmodule, topology);
319	if (ret) {
320		dev_err(dev, "%d:Error while parsing topology data\n",
321			ret);
322		goto free_topology;
323	}
324	gbmodule->topology = topology;
325
326	/* Initialize data connections */
327	list_for_each_entry(dai, &gbmodule->data_list, list) {
328		ret = gb_connection_enable(dai->connection);
329		if (ret) {
330			dev_err(dev,
331				"%d:Error while enabling %d:data connection\n",
332				ret, le16_to_cpu(dai->data_cport));
333			goto disable_data_connection;
334		}
335	}
336
337	/* register module with gbcodec */
338	ret = gbaudio_register_module(gbmodule);
339	if (ret)
340		goto disable_data_connection;
341
342	/* inform above layer for uevent */
343	dev_dbg(dev, "Inform set_event:%d to above layer\n", 1);
344	/* prepare for the audio manager */
345	strscpy(desc.name, gbmodule->name, sizeof(desc.name));
346	desc.vid = 2; /* todo */
347	desc.pid = 3; /* todo */
348	desc.intf_id = gbmodule->dev_id;
349	desc.op_devices = gbmodule->op_devices;
350	desc.ip_devices = gbmodule->ip_devices;
351	gbmodule->manager_id = gb_audio_manager_add(&desc);
352
353	dev_dbg(dev, "Add GB Audio device:%s\n", gbmodule->name);
354
355	gb_pm_runtime_put_autosuspend(bundle);
356
357	return 0;
358
359disable_data_connection:
360	list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list)
361		gb_connection_disable(dai->connection);
362	gbaudio_tplg_release(gbmodule);
363	gbmodule->topology = NULL;
364
365free_topology:
366	kfree(topology);
367
368disable_connection:
369	gb_connection_disable(gbmodule->mgmt_connection);
370
371destroy_connections:
372	list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) {
373		gb_connection_destroy(dai->connection);
374		list_del(&dai->list);
375		devm_kfree(dev, dai);
376	}
377
378	if (gbmodule->mgmt_connection)
379		gb_connection_destroy(gbmodule->mgmt_connection);
380
381	devm_kfree(dev, gbmodule);
382
383	return ret;
384}
385
386static void gb_audio_disconnect(struct gb_bundle *bundle)
387{
388	struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle);
389	struct gbaudio_data_connection *dai, *_dai;
390
391	gb_pm_runtime_get_sync(bundle);
392
393	/* cleanup module related resources first */
394	gbaudio_unregister_module(gbmodule);
395
396	/* inform uevent to above layers */
397	gb_audio_manager_remove(gbmodule->manager_id);
398
399	gbaudio_tplg_release(gbmodule);
400	kfree(gbmodule->topology);
401	gbmodule->topology = NULL;
402	gb_connection_disable(gbmodule->mgmt_connection);
403	list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) {
404		gb_connection_disable(dai->connection);
405		gb_connection_destroy(dai->connection);
406		list_del(&dai->list);
407		devm_kfree(gbmodule->dev, dai);
408	}
409	gb_connection_destroy(gbmodule->mgmt_connection);
410	gbmodule->mgmt_connection = NULL;
411
412	devm_kfree(&bundle->dev, gbmodule);
413}
414
415static const struct greybus_bundle_id gb_audio_id_table[] = {
416	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO) },
417	{ }
418};
419MODULE_DEVICE_TABLE(greybus, gb_audio_id_table);
420
421#ifdef CONFIG_PM
422static int gb_audio_suspend(struct device *dev)
423{
424	struct gb_bundle *bundle = to_gb_bundle(dev);
425	struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle);
426	struct gbaudio_data_connection *dai;
427
428	list_for_each_entry(dai, &gbmodule->data_list, list)
429		gb_connection_disable(dai->connection);
430
431	gb_connection_disable(gbmodule->mgmt_connection);
432
433	return 0;
434}
435
436static int gb_audio_resume(struct device *dev)
437{
438	struct gb_bundle *bundle = to_gb_bundle(dev);
439	struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle);
440	struct gbaudio_data_connection *dai;
441	int ret;
442
443	ret = gb_connection_enable(gbmodule->mgmt_connection);
444	if (ret) {
445		dev_err(dev, "%d:Error while enabling mgmt connection\n", ret);
446		return ret;
447	}
448
449	list_for_each_entry(dai, &gbmodule->data_list, list) {
450		ret = gb_connection_enable(dai->connection);
451		if (ret) {
452			dev_err(dev,
453				"%d:Error while enabling %d:data connection\n",
454				ret, le16_to_cpu(dai->data_cport));
455			return ret;
456		}
457	}
458
459	return 0;
460}
461#endif
462
463static const struct dev_pm_ops gb_audio_pm_ops = {
464	SET_RUNTIME_PM_OPS(gb_audio_suspend, gb_audio_resume, NULL)
465};
466
467static struct greybus_driver gb_audio_driver = {
468	.name		= "gb-audio",
469	.probe		= gb_audio_probe,
470	.disconnect	= gb_audio_disconnect,
471	.id_table	= gb_audio_id_table,
472	.driver.pm	= &gb_audio_pm_ops,
473};
474module_greybus_driver(gb_audio_driver);
475
476MODULE_DESCRIPTION("Greybus Audio module driver");
477MODULE_AUTHOR("Vaibhav Agarwal <vaibhav.agarwal@linaro.org>");
478MODULE_LICENSE("GPL v2");
479MODULE_ALIAS("platform:gbaudio-module");
480