1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. 3 // Copyright (c) 2018, Linaro Limited 4 5 #include <linux/slab.h> 6 #include <linux/wait.h> 7 #include <linux/kernel.h> 8 #include <linux/device.h> 9 #include <linux/module.h> 10 #include <linux/sched.h> 11 #include <linux/jiffies.h> 12 #include <linux/of.h> 13 #include <linux/of_platform.h> 14 #include <linux/kref.h> 15 #include <linux/wait.h> 16 #include <linux/soc/qcom/apr.h> 17 #include <linux/platform_device.h> 18 #include <sound/asound.h> 19 #include "q6adm.h" 20 #include "q6afe.h" 21 #include "q6core.h" 22 #include "q6dsp-errno.h" 23 #include "q6dsp-common.h" 24 25 #define ADM_CMD_DEVICE_OPEN_V5 0x00010326 26 #define ADM_CMDRSP_DEVICE_OPEN_V5 0x00010329 27 #define ADM_CMD_DEVICE_CLOSE_V5 0x00010327 28 #define ADM_CMD_MATRIX_MAP_ROUTINGS_V5 0x00010325 29 30 #define TIMEOUT_MS 1000 31 #define RESET_COPP_ID 99 32 #define INVALID_COPP_ID 0xFF 33 /* Definition for a legacy device session. */ 34 #define ADM_LEGACY_DEVICE_SESSION 0 35 #define ADM_MATRIX_ID_AUDIO_RX 0 36 #define ADM_MATRIX_ID_AUDIO_TX 1 37 38 struct q6copp { 39 int afe_port; 40 int copp_idx; 41 int id; 42 int topology; 43 int mode; 44 int rate; 45 int bit_width; 46 int channels; 47 int app_type; 48 int acdb_id; 49 50 struct aprv2_ibasic_rsp_result_t result; 51 struct kref refcount; 52 wait_queue_head_t wait; 53 struct list_head node; 54 struct q6adm *adm; 55 }; 56 57 struct q6adm { 58 struct apr_device *apr; 59 struct device *dev; 60 struct q6core_svc_api_info ainfo; 61 unsigned long copp_bitmap[AFE_MAX_PORTS]; 62 struct list_head copps_list; 63 spinlock_t copps_list_lock; 64 struct aprv2_ibasic_rsp_result_t result; 65 struct mutex lock; 66 wait_queue_head_t matrix_map_wait; 67 struct platform_device *pdev_routing; 68 }; 69 70 struct q6adm_cmd_device_open_v5 { 71 u16 flags; 72 u16 mode_of_operation; 73 u16 endpoint_id_1; 74 u16 endpoint_id_2; 75 u32 topology_id; 76 u16 dev_num_channel; 77 u16 bit_width; 78 u32 sample_rate; 79 u8 dev_channel_mapping[8]; 80 } __packed; 81 82 struct q6adm_cmd_matrix_map_routings_v5 { 83 u32 matrix_id; 84 u32 num_sessions; 85 } __packed; 86 87 struct q6adm_session_map_node_v5 { 88 u16 session_id; 89 u16 num_copps; 90 } __packed; 91 92 static struct q6copp *q6adm_find_copp(struct q6adm *adm, int port_idx, 93 int copp_idx) 94 { 95 struct q6copp *c = NULL; 96 struct q6copp *ret = NULL; 97 unsigned long flags; 98 99 spin_lock_irqsave(&adm->copps_list_lock, flags); 100 list_for_each_entry(c, &adm->copps_list, node) { 101 if ((port_idx == c->afe_port) && (copp_idx == c->copp_idx)) { 102 ret = c; 103 kref_get(&c->refcount); 104 break; 105 } 106 } 107 108 spin_unlock_irqrestore(&adm->copps_list_lock, flags); 109 110 return ret; 111 112 } 113 114 static void q6adm_free_copp(struct kref *ref) 115 { 116 struct q6copp *c = container_of(ref, struct q6copp, refcount); 117 struct q6adm *adm = c->adm; 118 unsigned long flags; 119 120 spin_lock_irqsave(&adm->copps_list_lock, flags); 121 clear_bit(c->copp_idx, &adm->copp_bitmap[c->afe_port]); 122 list_del(&c->node); 123 spin_unlock_irqrestore(&adm->copps_list_lock, flags); 124 kfree(c); 125 } 126 127 static int q6adm_callback(struct apr_device *adev, struct apr_resp_pkt *data) 128 { 129 struct aprv2_ibasic_rsp_result_t *result = data->payload; 130 int port_idx, copp_idx; 131 struct apr_hdr *hdr = &data->hdr; 132 struct q6copp *copp; 133 struct q6adm *adm = dev_get_drvdata(&adev->dev); 134 135 if (!data->payload_size) 136 return 0; 137 138 copp_idx = (hdr->token) & 0XFF; 139 port_idx = ((hdr->token) >> 16) & 0xFF; 140 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) { 141 dev_err(&adev->dev, "Invalid port idx %d token %d\n", 142 port_idx, hdr->token); 143 return 0; 144 } 145 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) { 146 dev_err(&adev->dev, "Invalid copp idx %d token %d\n", 147 copp_idx, hdr->token); 148 return 0; 149 } 150 151 switch (hdr->opcode) { 152 case APR_BASIC_RSP_RESULT: { 153 if (result->status != 0) { 154 dev_err(&adev->dev, "cmd = 0x%x return error = 0x%x\n", 155 result->opcode, result->status); 156 } 157 switch (result->opcode) { 158 case ADM_CMD_DEVICE_OPEN_V5: 159 case ADM_CMD_DEVICE_CLOSE_V5: 160 copp = q6adm_find_copp(adm, port_idx, copp_idx); 161 if (!copp) 162 return 0; 163 164 copp->result = *result; 165 wake_up(&copp->wait); 166 kref_put(&copp->refcount, q6adm_free_copp); 167 break; 168 case ADM_CMD_MATRIX_MAP_ROUTINGS_V5: 169 adm->result = *result; 170 wake_up(&adm->matrix_map_wait); 171 break; 172 173 default: 174 dev_err(&adev->dev, "Unknown Cmd: 0x%x\n", 175 result->opcode); 176 break; 177 } 178 return 0; 179 } 180 case ADM_CMDRSP_DEVICE_OPEN_V5: { 181 struct adm_cmd_rsp_device_open_v5 { 182 u32 status; 183 u16 copp_id; 184 u16 reserved; 185 } __packed * open = data->payload; 186 187 copp = q6adm_find_copp(adm, port_idx, copp_idx); 188 if (!copp) 189 return 0; 190 191 if (open->copp_id == INVALID_COPP_ID) { 192 dev_err(&adev->dev, "Invalid coppid rxed %d\n", 193 open->copp_id); 194 copp->result.status = ADSP_EBADPARAM; 195 wake_up(&copp->wait); 196 kref_put(&copp->refcount, q6adm_free_copp); 197 break; 198 } 199 copp->result.opcode = hdr->opcode; 200 copp->id = open->copp_id; 201 wake_up(&copp->wait); 202 kref_put(&copp->refcount, q6adm_free_copp); 203 } 204 break; 205 default: 206 dev_err(&adev->dev, "Unknown cmd:0x%x\n", 207 hdr->opcode); 208 break; 209 } 210 211 return 0; 212 } 213 214 static struct q6copp *q6adm_alloc_copp(struct q6adm *adm, int port_idx) 215 { 216 struct q6copp *c; 217 int idx; 218 219 idx = find_first_zero_bit(&adm->copp_bitmap[port_idx], 220 MAX_COPPS_PER_PORT); 221 222 if (idx > MAX_COPPS_PER_PORT) 223 return ERR_PTR(-EBUSY); 224 225 c = kzalloc(sizeof(*c), GFP_ATOMIC); 226 if (!c) 227 return ERR_PTR(-ENOMEM); 228 229 set_bit(idx, &adm->copp_bitmap[port_idx]); 230 c->copp_idx = idx; 231 c->afe_port = port_idx; 232 c->adm = adm; 233 234 init_waitqueue_head(&c->wait); 235 236 return c; 237 } 238 239 static int q6adm_apr_send_copp_pkt(struct q6adm *adm, struct q6copp *copp, 240 struct apr_pkt *pkt, uint32_t rsp_opcode) 241 { 242 struct device *dev = adm->dev; 243 uint32_t opcode = pkt->hdr.opcode; 244 int ret; 245 246 mutex_lock(&adm->lock); 247 copp->result.opcode = 0; 248 copp->result.status = 0; 249 ret = apr_send_pkt(adm->apr, pkt); 250 if (ret < 0) { 251 dev_err(dev, "Failed to send APR packet\n"); 252 ret = -EINVAL; 253 goto err; 254 } 255 256 /* Wait for the callback with copp id */ 257 if (rsp_opcode) 258 ret = wait_event_timeout(copp->wait, 259 (copp->result.opcode == opcode) || 260 (copp->result.opcode == rsp_opcode), 261 msecs_to_jiffies(TIMEOUT_MS)); 262 else 263 ret = wait_event_timeout(copp->wait, 264 (copp->result.opcode == opcode), 265 msecs_to_jiffies(TIMEOUT_MS)); 266 267 if (!ret) { 268 dev_err(dev, "ADM copp cmd timedout\n"); 269 ret = -ETIMEDOUT; 270 } else if (copp->result.status > 0) { 271 dev_err(dev, "DSP returned error[%d]\n", 272 copp->result.status); 273 ret = -EINVAL; 274 } 275 276 err: 277 mutex_unlock(&adm->lock); 278 return ret; 279 } 280 281 static int q6adm_device_close(struct q6adm *adm, struct q6copp *copp, 282 int port_id, int copp_idx) 283 { 284 struct apr_pkt close; 285 286 close.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, 287 APR_HDR_LEN(APR_HDR_SIZE), 288 APR_PKT_VER); 289 close.hdr.pkt_size = sizeof(close); 290 close.hdr.src_port = port_id; 291 close.hdr.dest_port = copp->id; 292 close.hdr.token = port_id << 16 | copp_idx; 293 close.hdr.opcode = ADM_CMD_DEVICE_CLOSE_V5; 294 295 return q6adm_apr_send_copp_pkt(adm, copp, &close, 0); 296 } 297 298 static struct q6copp *q6adm_find_matching_copp(struct q6adm *adm, 299 int port_id, int topology, 300 int mode, int rate, 301 int channel_mode, int bit_width, 302 int app_type) 303 { 304 struct q6copp *c = NULL; 305 struct q6copp *ret = NULL; 306 unsigned long flags; 307 308 spin_lock_irqsave(&adm->copps_list_lock, flags); 309 310 list_for_each_entry(c, &adm->copps_list, node) { 311 if ((port_id == c->afe_port) && (topology == c->topology) && 312 (mode == c->mode) && (rate == c->rate) && 313 (bit_width == c->bit_width) && (app_type == c->app_type)) { 314 ret = c; 315 kref_get(&c->refcount); 316 } 317 } 318 spin_unlock_irqrestore(&adm->copps_list_lock, flags); 319 320 return ret; 321 } 322 323 static int q6adm_device_open(struct q6adm *adm, struct q6copp *copp, 324 int port_id, int path, int topology, 325 int channel_mode, int bit_width, int rate) 326 { 327 struct q6adm_cmd_device_open_v5 *open; 328 int afe_port = q6afe_get_port_id(port_id); 329 struct apr_pkt *pkt; 330 void *p; 331 int ret, pkt_size; 332 333 pkt_size = APR_HDR_SIZE + sizeof(*open); 334 p = kzalloc(pkt_size, GFP_KERNEL); 335 if (!p) 336 return -ENOMEM; 337 338 pkt = p; 339 open = p + APR_HDR_SIZE; 340 pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, 341 APR_HDR_LEN(APR_HDR_SIZE), 342 APR_PKT_VER); 343 pkt->hdr.pkt_size = pkt_size; 344 pkt->hdr.src_port = afe_port; 345 pkt->hdr.dest_port = afe_port; 346 pkt->hdr.token = port_id << 16 | copp->copp_idx; 347 pkt->hdr.opcode = ADM_CMD_DEVICE_OPEN_V5; 348 open->flags = ADM_LEGACY_DEVICE_SESSION; 349 open->mode_of_operation = path; 350 open->endpoint_id_1 = afe_port; 351 open->topology_id = topology; 352 open->dev_num_channel = channel_mode & 0x00FF; 353 open->bit_width = bit_width; 354 open->sample_rate = rate; 355 356 ret = q6dsp_map_channels(&open->dev_channel_mapping[0], 357 channel_mode); 358 if (ret) 359 goto err; 360 361 ret = q6adm_apr_send_copp_pkt(adm, copp, pkt, 362 ADM_CMDRSP_DEVICE_OPEN_V5); 363 364 err: 365 kfree(pkt); 366 return ret; 367 } 368 369 /** 370 * q6adm_open() - open adm and grab a free copp 371 * 372 * @dev: Pointer to adm child device. 373 * @port_id: port id 374 * @path: playback or capture path. 375 * @rate: rate at which copp is required. 376 * @channel_mode: channel mode 377 * @topology: adm topology id 378 * @perf_mode: performace mode. 379 * @bit_width: audio sample bit width 380 * @app_type: Application type. 381 * @acdb_id: ACDB id 382 * 383 * Return: Will be an negative on error or a valid copp pointer on success. 384 */ 385 struct q6copp *q6adm_open(struct device *dev, int port_id, int path, int rate, 386 int channel_mode, int topology, int perf_mode, 387 uint16_t bit_width, int app_type, int acdb_id) 388 { 389 struct q6adm *adm = dev_get_drvdata(dev->parent); 390 struct q6copp *copp; 391 unsigned long flags; 392 int ret = 0; 393 394 if (port_id < 0) { 395 dev_err(dev, "Invalid port_id 0x%x\n", port_id); 396 return ERR_PTR(-EINVAL); 397 } 398 399 copp = q6adm_find_matching_copp(adm, port_id, topology, perf_mode, 400 rate, channel_mode, bit_width, app_type); 401 if (copp) { 402 dev_err(dev, "Found Matching Copp 0x%x\n", copp->copp_idx); 403 return copp; 404 } 405 406 spin_lock_irqsave(&adm->copps_list_lock, flags); 407 copp = q6adm_alloc_copp(adm, port_id); 408 if (IS_ERR_OR_NULL(copp)) { 409 spin_unlock_irqrestore(&adm->copps_list_lock, flags); 410 return ERR_CAST(copp); 411 } 412 413 list_add_tail(&copp->node, &adm->copps_list); 414 spin_unlock_irqrestore(&adm->copps_list_lock, flags); 415 416 kref_init(&copp->refcount); 417 copp->topology = topology; 418 copp->mode = perf_mode; 419 copp->rate = rate; 420 copp->channels = channel_mode; 421 copp->bit_width = bit_width; 422 copp->app_type = app_type; 423 424 425 ret = q6adm_device_open(adm, copp, port_id, path, topology, 426 channel_mode, bit_width, rate); 427 if (ret < 0) { 428 kref_put(&copp->refcount, q6adm_free_copp); 429 return ERR_PTR(ret); 430 } 431 432 return copp; 433 } 434 EXPORT_SYMBOL_GPL(q6adm_open); 435 436 /** 437 * q6adm_get_copp_id() - get copp index 438 * 439 * @copp: Pointer to valid copp 440 * 441 * Return: Will be an negative on error or a valid copp index on success. 442 **/ 443 int q6adm_get_copp_id(struct q6copp *copp) 444 { 445 if (!copp) 446 return -EINVAL; 447 448 return copp->copp_idx; 449 } 450 EXPORT_SYMBOL_GPL(q6adm_get_copp_id); 451 452 /** 453 * q6adm_matrix_map() - Map asm streams and afe ports using payload 454 * 455 * @dev: Pointer to adm child device. 456 * @path: playback or capture path. 457 * @payload_map: map between session id and afe ports. 458 * @perf_mode: Performace mode. 459 * 460 * Return: Will be an negative on error or a zero on success. 461 */ 462 int q6adm_matrix_map(struct device *dev, int path, 463 struct route_payload payload_map, int perf_mode) 464 { 465 struct q6adm *adm = dev_get_drvdata(dev->parent); 466 struct q6adm_cmd_matrix_map_routings_v5 *route; 467 struct q6adm_session_map_node_v5 *node; 468 struct apr_pkt *pkt; 469 uint16_t *copps_list; 470 int pkt_size, ret, i, copp_idx; 471 void *matrix_map = NULL; 472 struct q6copp *copp; 473 474 /* Assumes port_ids have already been validated during adm_open */ 475 pkt_size = (APR_HDR_SIZE + sizeof(*route) + sizeof(*node) + 476 (sizeof(uint32_t) * payload_map.num_copps)); 477 478 matrix_map = kzalloc(pkt_size, GFP_KERNEL); 479 if (!matrix_map) 480 return -ENOMEM; 481 482 pkt = matrix_map; 483 route = matrix_map + APR_HDR_SIZE; 484 node = matrix_map + APR_HDR_SIZE + sizeof(*route); 485 copps_list = matrix_map + APR_HDR_SIZE + sizeof(*route) + sizeof(*node); 486 487 pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, 488 APR_HDR_LEN(APR_HDR_SIZE), 489 APR_PKT_VER); 490 pkt->hdr.pkt_size = pkt_size; 491 pkt->hdr.token = 0; 492 pkt->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5; 493 route->num_sessions = 1; 494 495 switch (path) { 496 case ADM_PATH_PLAYBACK: 497 route->matrix_id = ADM_MATRIX_ID_AUDIO_RX; 498 break; 499 case ADM_PATH_LIVE_REC: 500 route->matrix_id = ADM_MATRIX_ID_AUDIO_TX; 501 break; 502 default: 503 dev_err(dev, "Wrong path set[%d]\n", path); 504 break; 505 } 506 507 node->session_id = payload_map.session_id; 508 node->num_copps = payload_map.num_copps; 509 510 for (i = 0; i < payload_map.num_copps; i++) { 511 int port_idx = payload_map.port_id[i]; 512 513 if (port_idx < 0) { 514 dev_err(dev, "Invalid port_id 0x%x\n", 515 payload_map.port_id[i]); 516 kfree(pkt); 517 return -EINVAL; 518 } 519 copp_idx = payload_map.copp_idx[i]; 520 521 copp = q6adm_find_copp(adm, port_idx, copp_idx); 522 if (!copp) { 523 kfree(pkt); 524 return -EINVAL; 525 } 526 527 copps_list[i] = copp->id; 528 kref_put(&copp->refcount, q6adm_free_copp); 529 } 530 531 mutex_lock(&adm->lock); 532 adm->result.status = 0; 533 adm->result.opcode = 0; 534 535 ret = apr_send_pkt(adm->apr, pkt); 536 if (ret < 0) { 537 dev_err(dev, "routing for stream %d failed ret %d\n", 538 payload_map.session_id, ret); 539 goto fail_cmd; 540 } 541 ret = wait_event_timeout(adm->matrix_map_wait, 542 adm->result.opcode == pkt->hdr.opcode, 543 msecs_to_jiffies(TIMEOUT_MS)); 544 if (!ret) { 545 dev_err(dev, "routing for stream %d failed\n", 546 payload_map.session_id); 547 ret = -ETIMEDOUT; 548 goto fail_cmd; 549 } else if (adm->result.status > 0) { 550 dev_err(dev, "DSP returned error[%d]\n", 551 adm->result.status); 552 ret = -EINVAL; 553 goto fail_cmd; 554 } 555 556 fail_cmd: 557 mutex_unlock(&adm->lock); 558 kfree(pkt); 559 return ret; 560 } 561 EXPORT_SYMBOL_GPL(q6adm_matrix_map); 562 563 /** 564 * q6adm_close() - Close adm copp 565 * 566 * @dev: Pointer to adm child device. 567 * @copp: pointer to previously opened copp 568 * 569 * Return: Will be an negative on error or a zero on success. 570 */ 571 int q6adm_close(struct device *dev, struct q6copp *copp) 572 { 573 struct q6adm *adm = dev_get_drvdata(dev->parent); 574 int ret = 0; 575 576 ret = q6adm_device_close(adm, copp, copp->afe_port, copp->copp_idx); 577 if (ret < 0) { 578 dev_err(adm->dev, "Failed to close copp %d\n", ret); 579 return ret; 580 } 581 582 kref_put(&copp->refcount, q6adm_free_copp); 583 584 return 0; 585 } 586 EXPORT_SYMBOL_GPL(q6adm_close); 587 588 static int q6adm_probe(struct apr_device *adev) 589 { 590 struct device *dev = &adev->dev; 591 struct device_node *dais_np; 592 struct q6adm *adm; 593 594 adm = devm_kzalloc(&adev->dev, sizeof(*adm), GFP_KERNEL); 595 if (!adm) 596 return -ENOMEM; 597 598 adm->apr = adev; 599 dev_set_drvdata(&adev->dev, adm); 600 adm->dev = dev; 601 q6core_get_svc_api_info(adev->svc_id, &adm->ainfo); 602 mutex_init(&adm->lock); 603 init_waitqueue_head(&adm->matrix_map_wait); 604 605 INIT_LIST_HEAD(&adm->copps_list); 606 spin_lock_init(&adm->copps_list_lock); 607 608 dais_np = of_get_child_by_name(dev->of_node, "routing"); 609 if (dais_np) { 610 adm->pdev_routing = of_platform_device_create(dais_np, 611 "q6routing", dev); 612 of_node_put(dais_np); 613 } 614 615 return 0; 616 } 617 618 static int q6adm_remove(struct apr_device *adev) 619 { 620 struct q6adm *adm = dev_get_drvdata(&adev->dev); 621 622 if (adm->pdev_routing) 623 of_platform_device_destroy(&adm->pdev_routing->dev, NULL); 624 625 return 0; 626 } 627 628 static const struct of_device_id q6adm_device_id[] = { 629 { .compatible = "qcom,q6adm" }, 630 {}, 631 }; 632 MODULE_DEVICE_TABLE(of, q6adm_device_id); 633 634 static struct apr_driver qcom_q6adm_driver = { 635 .probe = q6adm_probe, 636 .remove = q6adm_remove, 637 .callback = q6adm_callback, 638 .driver = { 639 .name = "qcom-q6adm", 640 .of_match_table = of_match_ptr(q6adm_device_id), 641 }, 642 }; 643 644 module_apr_driver(qcom_q6adm_driver); 645 MODULE_DESCRIPTION("Q6 Audio Device Manager"); 646 MODULE_LICENSE("GPL v2"); 647