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 20 static 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 69 static 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 132 static 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 141 static 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 177 static 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 201 static 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 = 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 233 static 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 gbmodule->dev = dev; 262 snprintf(gbmodule->name, NAME_SIZE, "%s.%s", dev->driver->name, 263 dev_name(dev)); 264 greybus_set_drvdata(bundle, gbmodule); 265 266 /* Create all connections */ 267 for (i = 0; i < bundle->num_cports; i++) { 268 cport_desc = &bundle->cport_desc[i]; 269 270 switch (cport_desc->protocol_id) { 271 case GREYBUS_PROTOCOL_AUDIO_MGMT: 272 ret = gb_audio_add_mgmt_connection(gbmodule, cport_desc, 273 bundle); 274 if (ret) 275 goto destroy_connections; 276 break; 277 case GREYBUS_PROTOCOL_AUDIO_DATA: 278 ret = gb_audio_add_data_connection(gbmodule, cport_desc, 279 bundle); 280 if (ret) 281 goto destroy_connections; 282 break; 283 default: 284 dev_err(dev, "Unsupported protocol: 0x%02x\n", 285 cport_desc->protocol_id); 286 ret = -ENODEV; 287 goto destroy_connections; 288 } 289 } 290 291 /* There must be a management cport */ 292 if (!gbmodule->mgmt_connection) { 293 ret = -EINVAL; 294 dev_err(dev, "Missing management connection\n"); 295 goto destroy_connections; 296 } 297 298 /* Initialize management connection */ 299 ret = gb_connection_enable(gbmodule->mgmt_connection); 300 if (ret) { 301 dev_err(dev, "%d: Error while enabling mgmt connection\n", ret); 302 goto destroy_connections; 303 } 304 gbmodule->dev_id = gbmodule->mgmt_connection->intf->interface_id; 305 306 /* 307 * FIXME: malloc for topology happens via audio_gb driver 308 * should be done within codec driver itself 309 */ 310 ret = gb_audio_gb_get_topology(gbmodule->mgmt_connection, &topology); 311 if (ret) { 312 dev_err(dev, "%d:Error while fetching topology\n", ret); 313 goto disable_connection; 314 } 315 316 /* process topology data */ 317 ret = gbaudio_tplg_parse_data(gbmodule, topology); 318 if (ret) { 319 dev_err(dev, "%d:Error while parsing topology data\n", 320 ret); 321 goto free_topology; 322 } 323 gbmodule->topology = topology; 324 325 /* Initialize data connections */ 326 list_for_each_entry(dai, &gbmodule->data_list, list) { 327 ret = gb_connection_enable(dai->connection); 328 if (ret) { 329 dev_err(dev, 330 "%d:Error while enabling %d:data connection\n", 331 ret, dai->data_cport); 332 goto disable_data_connection; 333 } 334 } 335 336 /* register module with gbcodec */ 337 ret = gbaudio_register_module(gbmodule); 338 if (ret) 339 goto disable_data_connection; 340 341 /* inform above layer for uevent */ 342 dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); 343 /* prepare for the audio manager */ 344 strlcpy(desc.name, gbmodule->name, GB_AUDIO_MANAGER_MODULE_NAME_LEN); 345 desc.vid = 2; /* todo */ 346 desc.pid = 3; /* todo */ 347 desc.intf_id = gbmodule->dev_id; 348 desc.op_devices = gbmodule->op_devices; 349 desc.ip_devices = gbmodule->ip_devices; 350 gbmodule->manager_id = gb_audio_manager_add(&desc); 351 352 dev_dbg(dev, "Add GB Audio device:%s\n", gbmodule->name); 353 354 gb_pm_runtime_put_autosuspend(bundle); 355 356 return 0; 357 358 disable_data_connection: 359 list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) 360 gb_connection_disable(dai->connection); 361 gbaudio_tplg_release(gbmodule); 362 gbmodule->topology = NULL; 363 364 free_topology: 365 kfree(topology); 366 367 disable_connection: 368 gb_connection_disable(gbmodule->mgmt_connection); 369 370 destroy_connections: 371 list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) { 372 gb_connection_destroy(dai->connection); 373 list_del(&dai->list); 374 devm_kfree(dev, dai); 375 } 376 377 if (gbmodule->mgmt_connection) 378 gb_connection_destroy(gbmodule->mgmt_connection); 379 380 devm_kfree(dev, gbmodule); 381 382 return ret; 383 } 384 385 static void gb_audio_disconnect(struct gb_bundle *bundle) 386 { 387 struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); 388 struct gbaudio_data_connection *dai, *_dai; 389 390 gb_pm_runtime_get_sync(bundle); 391 392 /* cleanup module related resources first */ 393 gbaudio_unregister_module(gbmodule); 394 395 /* inform uevent to above layers */ 396 gb_audio_manager_remove(gbmodule->manager_id); 397 398 gbaudio_tplg_release(gbmodule); 399 kfree(gbmodule->topology); 400 gbmodule->topology = NULL; 401 gb_connection_disable(gbmodule->mgmt_connection); 402 list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) { 403 gb_connection_disable(dai->connection); 404 gb_connection_destroy(dai->connection); 405 list_del(&dai->list); 406 devm_kfree(gbmodule->dev, dai); 407 } 408 gb_connection_destroy(gbmodule->mgmt_connection); 409 gbmodule->mgmt_connection = NULL; 410 411 devm_kfree(&bundle->dev, gbmodule); 412 } 413 414 static const struct greybus_bundle_id gb_audio_id_table[] = { 415 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO) }, 416 { } 417 }; 418 MODULE_DEVICE_TABLE(greybus, gb_audio_id_table); 419 420 #ifdef CONFIG_PM 421 static int gb_audio_suspend(struct device *dev) 422 { 423 struct gb_bundle *bundle = to_gb_bundle(dev); 424 struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); 425 struct gbaudio_data_connection *dai; 426 427 list_for_each_entry(dai, &gbmodule->data_list, list) 428 gb_connection_disable(dai->connection); 429 430 gb_connection_disable(gbmodule->mgmt_connection); 431 432 return 0; 433 } 434 435 static int gb_audio_resume(struct device *dev) 436 { 437 struct gb_bundle *bundle = to_gb_bundle(dev); 438 struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); 439 struct gbaudio_data_connection *dai; 440 int ret; 441 442 ret = gb_connection_enable(gbmodule->mgmt_connection); 443 if (ret) { 444 dev_err(dev, "%d:Error while enabling mgmt connection\n", ret); 445 return ret; 446 } 447 448 list_for_each_entry(dai, &gbmodule->data_list, list) { 449 ret = gb_connection_enable(dai->connection); 450 if (ret) { 451 dev_err(dev, 452 "%d:Error while enabling %d:data connection\n", 453 ret, dai->data_cport); 454 return ret; 455 } 456 } 457 458 return 0; 459 } 460 #endif 461 462 static const struct dev_pm_ops gb_audio_pm_ops = { 463 SET_RUNTIME_PM_OPS(gb_audio_suspend, gb_audio_resume, NULL) 464 }; 465 466 static struct greybus_driver gb_audio_driver = { 467 .name = "gb-audio", 468 .probe = gb_audio_probe, 469 .disconnect = gb_audio_disconnect, 470 .id_table = gb_audio_id_table, 471 .driver.pm = &gb_audio_pm_ops, 472 }; 473 module_greybus_driver(gb_audio_driver); 474 475 MODULE_DESCRIPTION("Greybus Audio module driver"); 476 MODULE_AUTHOR("Vaibhav Agarwal <vaibhav.agarwal@linaro.org>"); 477 MODULE_LICENSE("GPL v2"); 478 MODULE_ALIAS("platform:gbaudio-module"); 479