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