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/mutex.h> 6 #include <linux/wait.h> 7 #include <linux/module.h> 8 #include <linux/soc/qcom/apr.h> 9 #include <linux/device.h> 10 #include <linux/of_platform.h> 11 #include <linux/spinlock.h> 12 #include <linux/kref.h> 13 #include <linux/of.h> 14 #include <uapi/sound/asound.h> 15 #include <uapi/sound/compress_params.h> 16 #include <linux/delay.h> 17 #include <linux/slab.h> 18 #include <linux/mm.h> 19 #include "q6asm.h" 20 #include "q6core.h" 21 #include "q6dsp-errno.h" 22 #include "q6dsp-common.h" 23 24 #define ASM_STREAM_CMD_CLOSE 0x00010BCD 25 #define ASM_STREAM_CMD_FLUSH 0x00010BCE 26 #define ASM_SESSION_CMD_PAUSE 0x00010BD3 27 #define ASM_DATA_CMD_EOS 0x00010BDB 28 #define ASM_NULL_POPP_TOPOLOGY 0x00010C68 29 #define ASM_STREAM_CMD_FLUSH_READBUFS 0x00010C09 30 #define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10 31 #define ASM_STREAM_POSTPROC_TOPO_ID_NONE 0x00010C68 32 #define ASM_CMD_SHARED_MEM_MAP_REGIONS 0x00010D92 33 #define ASM_CMDRSP_SHARED_MEM_MAP_REGIONS 0x00010D93 34 #define ASM_CMD_SHARED_MEM_UNMAP_REGIONS 0x00010D94 35 #define ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2 0x00010D98 36 #define ASM_DATA_EVENT_WRITE_DONE_V2 0x00010D99 37 #define ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2 0x00010DA3 38 #define ASM_SESSION_CMD_RUN_V2 0x00010DAA 39 #define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2 0x00010DA5 40 #define ASM_MEDIA_FMT_MP3 0x00010BE9 41 #define ASM_MEDIA_FMT_FLAC 0x00010C16 42 #define ASM_MEDIA_FMT_WMA_V9 0x00010DA8 43 #define ASM_MEDIA_FMT_WMA_V10 0x00010DA7 44 #define ASM_DATA_CMD_WRITE_V2 0x00010DAB 45 #define ASM_DATA_CMD_READ_V2 0x00010DAC 46 #define ASM_SESSION_CMD_SUSPEND 0x00010DEC 47 #define ASM_STREAM_CMD_OPEN_WRITE_V3 0x00010DB3 48 #define ASM_STREAM_CMD_OPEN_READ_V3 0x00010DB4 49 #define ASM_DATA_EVENT_READ_DONE_V2 0x00010D9A 50 #define ASM_STREAM_CMD_OPEN_READWRITE_V2 0x00010D8D 51 #define ASM_MEDIA_FMT_ALAC 0x00012f31 52 #define ASM_MEDIA_FMT_APE 0x00012f32 53 54 55 #define ASM_LEGACY_STREAM_SESSION 0 56 /* Bit shift for the stream_perf_mode subfield. */ 57 #define ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ 29 58 #define ASM_END_POINT_DEVICE_MATRIX 0 59 #define ASM_DEFAULT_APP_TYPE 0 60 #define ASM_SYNC_IO_MODE 0x0001 61 #define ASM_ASYNC_IO_MODE 0x0002 62 #define ASM_TUN_READ_IO_MODE 0x0004 /* tunnel read write mode */ 63 #define ASM_TUN_WRITE_IO_MODE 0x0008 /* tunnel read write mode */ 64 #define ASM_SHIFT_GAPLESS_MODE_FLAG 31 65 #define ADSP_MEMORY_MAP_SHMEM8_4K_POOL 3 66 67 struct avs_cmd_shared_mem_map_regions { 68 u16 mem_pool_id; 69 u16 num_regions; 70 u32 property_flag; 71 } __packed; 72 73 struct avs_shared_map_region_payload { 74 u32 shm_addr_lsw; 75 u32 shm_addr_msw; 76 u32 mem_size_bytes; 77 } __packed; 78 79 struct avs_cmd_shared_mem_unmap_regions { 80 u32 mem_map_handle; 81 } __packed; 82 83 struct asm_data_cmd_media_fmt_update_v2 { 84 u32 fmt_blk_size; 85 } __packed; 86 87 struct asm_multi_channel_pcm_fmt_blk_v2 { 88 struct asm_data_cmd_media_fmt_update_v2 fmt_blk; 89 u16 num_channels; 90 u16 bits_per_sample; 91 u32 sample_rate; 92 u16 is_signed; 93 u16 reserved; 94 u8 channel_mapping[PCM_MAX_NUM_CHANNEL]; 95 } __packed; 96 97 struct asm_flac_fmt_blk_v2 { 98 struct asm_data_cmd_media_fmt_update_v2 fmt_blk; 99 u16 is_stream_info_present; 100 u16 num_channels; 101 u16 min_blk_size; 102 u16 max_blk_size; 103 u16 md5_sum[8]; 104 u32 sample_rate; 105 u32 min_frame_size; 106 u32 max_frame_size; 107 u16 sample_size; 108 u16 reserved; 109 } __packed; 110 111 struct asm_wmastdv9_fmt_blk_v2 { 112 struct asm_data_cmd_media_fmt_update_v2 fmt_blk; 113 u16 fmtag; 114 u16 num_channels; 115 u32 sample_rate; 116 u32 bytes_per_sec; 117 u16 blk_align; 118 u16 bits_per_sample; 119 u32 channel_mask; 120 u16 enc_options; 121 u16 reserved; 122 } __packed; 123 124 struct asm_wmaprov10_fmt_blk_v2 { 125 struct asm_data_cmd_media_fmt_update_v2 fmt_blk; 126 u16 fmtag; 127 u16 num_channels; 128 u32 sample_rate; 129 u32 bytes_per_sec; 130 u16 blk_align; 131 u16 bits_per_sample; 132 u32 channel_mask; 133 u16 enc_options; 134 u16 advanced_enc_options1; 135 u32 advanced_enc_options2; 136 } __packed; 137 138 struct asm_alac_fmt_blk_v2 { 139 struct asm_data_cmd_media_fmt_update_v2 fmt_blk; 140 u32 frame_length; 141 u8 compatible_version; 142 u8 bit_depth; 143 u8 pb; 144 u8 mb; 145 u8 kb; 146 u8 num_channels; 147 u16 max_run; 148 u32 max_frame_bytes; 149 u32 avg_bit_rate; 150 u32 sample_rate; 151 u32 channel_layout_tag; 152 } __packed; 153 154 struct asm_ape_fmt_blk_v2 { 155 struct asm_data_cmd_media_fmt_update_v2 fmt_blk; 156 u16 compatible_version; 157 u16 compression_level; 158 u32 format_flags; 159 u32 blocks_per_frame; 160 u32 final_frame_blocks; 161 u32 total_frames; 162 u16 bits_per_sample; 163 u16 num_channels; 164 u32 sample_rate; 165 u32 seek_table_present; 166 } __packed; 167 168 struct asm_stream_cmd_set_encdec_param { 169 u32 param_id; 170 u32 param_size; 171 } __packed; 172 173 struct asm_enc_cfg_blk_param_v2 { 174 u32 frames_per_buf; 175 u32 enc_cfg_blk_size; 176 } __packed; 177 178 struct asm_multi_channel_pcm_enc_cfg_v2 { 179 struct asm_stream_cmd_set_encdec_param encdec; 180 struct asm_enc_cfg_blk_param_v2 encblk; 181 uint16_t num_channels; 182 uint16_t bits_per_sample; 183 uint32_t sample_rate; 184 uint16_t is_signed; 185 uint16_t reserved; 186 uint8_t channel_mapping[8]; 187 } __packed; 188 189 struct asm_data_cmd_read_v2 { 190 u32 buf_addr_lsw; 191 u32 buf_addr_msw; 192 u32 mem_map_handle; 193 u32 buf_size; 194 u32 seq_id; 195 } __packed; 196 197 struct asm_data_cmd_read_v2_done { 198 u32 status; 199 u32 buf_addr_lsw; 200 u32 buf_addr_msw; 201 }; 202 203 struct asm_stream_cmd_open_read_v3 { 204 u32 mode_flags; 205 u32 src_endpointype; 206 u32 preprocopo_id; 207 u32 enc_cfg_id; 208 u16 bits_per_sample; 209 u16 reserved; 210 } __packed; 211 212 struct asm_data_cmd_write_v2 { 213 u32 buf_addr_lsw; 214 u32 buf_addr_msw; 215 u32 mem_map_handle; 216 u32 buf_size; 217 u32 seq_id; 218 u32 timestamp_lsw; 219 u32 timestamp_msw; 220 u32 flags; 221 } __packed; 222 223 struct asm_stream_cmd_open_write_v3 { 224 uint32_t mode_flags; 225 uint16_t sink_endpointype; 226 uint16_t bits_per_sample; 227 uint32_t postprocopo_id; 228 uint32_t dec_fmt_id; 229 } __packed; 230 231 struct asm_session_cmd_run_v2 { 232 u32 flags; 233 u32 time_lsw; 234 u32 time_msw; 235 } __packed; 236 237 struct audio_buffer { 238 phys_addr_t phys; 239 uint32_t size; /* size of buffer */ 240 }; 241 242 struct audio_port_data { 243 struct audio_buffer *buf; 244 uint32_t num_periods; 245 uint32_t dsp_buf; 246 uint32_t mem_map_handle; 247 }; 248 249 struct q6asm { 250 struct apr_device *adev; 251 struct device *dev; 252 struct q6core_svc_api_info ainfo; 253 wait_queue_head_t mem_wait; 254 spinlock_t slock; 255 struct audio_client *session[MAX_SESSIONS + 1]; 256 }; 257 258 struct audio_client { 259 int session; 260 q6asm_cb cb; 261 void *priv; 262 uint32_t io_mode; 263 struct apr_device *adev; 264 struct mutex cmd_lock; 265 spinlock_t lock; 266 struct kref refcount; 267 /* idx:1 out port, 0: in port */ 268 struct audio_port_data port[2]; 269 wait_queue_head_t cmd_wait; 270 struct aprv2_ibasic_rsp_result_t result; 271 int perf_mode; 272 int stream_id; 273 struct q6asm *q6asm; 274 struct device *dev; 275 }; 276 277 static inline void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, 278 uint32_t pkt_size, bool cmd_flg, 279 uint32_t stream_id) 280 { 281 hdr->hdr_field = APR_SEQ_CMD_HDR_FIELD; 282 hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id); 283 hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id); 284 hdr->pkt_size = pkt_size; 285 if (cmd_flg) 286 hdr->token = ac->session; 287 } 288 289 static int q6asm_apr_send_session_pkt(struct q6asm *a, struct audio_client *ac, 290 struct apr_pkt *pkt, uint32_t rsp_opcode) 291 { 292 struct apr_hdr *hdr = &pkt->hdr; 293 int rc; 294 295 mutex_lock(&ac->cmd_lock); 296 ac->result.opcode = 0; 297 ac->result.status = 0; 298 rc = apr_send_pkt(a->adev, pkt); 299 if (rc < 0) 300 goto err; 301 302 if (rsp_opcode) 303 rc = wait_event_timeout(a->mem_wait, 304 (ac->result.opcode == hdr->opcode) || 305 (ac->result.opcode == rsp_opcode), 306 5 * HZ); 307 else 308 rc = wait_event_timeout(a->mem_wait, 309 (ac->result.opcode == hdr->opcode), 310 5 * HZ); 311 312 if (!rc) { 313 dev_err(a->dev, "CMD timeout\n"); 314 rc = -ETIMEDOUT; 315 } else if (ac->result.status > 0) { 316 dev_err(a->dev, "DSP returned error[%x]\n", 317 ac->result.status); 318 rc = -EINVAL; 319 } 320 321 err: 322 mutex_unlock(&ac->cmd_lock); 323 return rc; 324 } 325 326 static int __q6asm_memory_unmap(struct audio_client *ac, 327 phys_addr_t buf_add, int dir) 328 { 329 struct avs_cmd_shared_mem_unmap_regions *mem_unmap; 330 struct q6asm *a = dev_get_drvdata(ac->dev->parent); 331 struct apr_pkt *pkt; 332 int rc, pkt_size; 333 void *p; 334 335 if (ac->port[dir].mem_map_handle == 0) { 336 dev_err(ac->dev, "invalid mem handle\n"); 337 return -EINVAL; 338 } 339 340 pkt_size = APR_HDR_SIZE + sizeof(*mem_unmap); 341 p = kzalloc(pkt_size, GFP_KERNEL); 342 if (!p) 343 return -ENOMEM; 344 345 pkt = p; 346 mem_unmap = p + APR_HDR_SIZE; 347 348 pkt->hdr.hdr_field = APR_SEQ_CMD_HDR_FIELD; 349 pkt->hdr.src_port = 0; 350 pkt->hdr.dest_port = 0; 351 pkt->hdr.pkt_size = pkt_size; 352 pkt->hdr.token = ((ac->session << 8) | dir); 353 354 pkt->hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS; 355 mem_unmap->mem_map_handle = ac->port[dir].mem_map_handle; 356 357 rc = q6asm_apr_send_session_pkt(a, ac, pkt, 0); 358 if (rc < 0) { 359 kfree(pkt); 360 return rc; 361 } 362 363 ac->port[dir].mem_map_handle = 0; 364 365 kfree(pkt); 366 return 0; 367 } 368 369 370 static void q6asm_audio_client_free_buf(struct audio_client *ac, 371 struct audio_port_data *port) 372 { 373 unsigned long flags; 374 375 spin_lock_irqsave(&ac->lock, flags); 376 port->num_periods = 0; 377 kfree(port->buf); 378 port->buf = NULL; 379 spin_unlock_irqrestore(&ac->lock, flags); 380 } 381 382 /** 383 * q6asm_unmap_memory_regions() - unmap memory regions in the dsp. 384 * 385 * @dir: direction of audio stream 386 * @ac: audio client instanace 387 * 388 * Return: Will be an negative value on failure or zero on success 389 */ 390 int q6asm_unmap_memory_regions(unsigned int dir, struct audio_client *ac) 391 { 392 struct audio_port_data *port; 393 int cnt = 0; 394 int rc = 0; 395 396 port = &ac->port[dir]; 397 if (!port->buf) { 398 rc = -EINVAL; 399 goto err; 400 } 401 402 cnt = port->num_periods - 1; 403 if (cnt >= 0) { 404 rc = __q6asm_memory_unmap(ac, port->buf[dir].phys, dir); 405 if (rc < 0) { 406 dev_err(ac->dev, "%s: Memory_unmap_regions failed %d\n", 407 __func__, rc); 408 goto err; 409 } 410 } 411 412 q6asm_audio_client_free_buf(ac, port); 413 414 err: 415 return rc; 416 } 417 EXPORT_SYMBOL_GPL(q6asm_unmap_memory_regions); 418 419 static int __q6asm_memory_map_regions(struct audio_client *ac, int dir, 420 size_t period_sz, unsigned int periods, 421 bool is_contiguous) 422 { 423 struct avs_cmd_shared_mem_map_regions *cmd = NULL; 424 struct avs_shared_map_region_payload *mregions = NULL; 425 struct q6asm *a = dev_get_drvdata(ac->dev->parent); 426 struct audio_port_data *port = NULL; 427 struct audio_buffer *ab = NULL; 428 struct apr_pkt *pkt; 429 void *p; 430 unsigned long flags; 431 uint32_t num_regions, buf_sz; 432 int rc, i, pkt_size; 433 434 if (is_contiguous) { 435 num_regions = 1; 436 buf_sz = period_sz * periods; 437 } else { 438 buf_sz = period_sz; 439 num_regions = periods; 440 } 441 442 /* DSP expects size should be aligned to 4K */ 443 buf_sz = ALIGN(buf_sz, 4096); 444 445 pkt_size = APR_HDR_SIZE + sizeof(*cmd) + 446 (sizeof(*mregions) * num_regions); 447 448 p = kzalloc(pkt_size, GFP_KERNEL); 449 if (!p) 450 return -ENOMEM; 451 452 pkt = p; 453 cmd = p + APR_HDR_SIZE; 454 mregions = p + APR_HDR_SIZE + sizeof(*cmd); 455 456 pkt->hdr.hdr_field = APR_SEQ_CMD_HDR_FIELD; 457 pkt->hdr.src_port = 0; 458 pkt->hdr.dest_port = 0; 459 pkt->hdr.pkt_size = pkt_size; 460 pkt->hdr.token = ((ac->session << 8) | dir); 461 pkt->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS; 462 463 cmd->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL; 464 cmd->num_regions = num_regions; 465 cmd->property_flag = 0x00; 466 467 spin_lock_irqsave(&ac->lock, flags); 468 port = &ac->port[dir]; 469 470 for (i = 0; i < num_regions; i++) { 471 ab = &port->buf[i]; 472 mregions->shm_addr_lsw = lower_32_bits(ab->phys); 473 mregions->shm_addr_msw = upper_32_bits(ab->phys); 474 mregions->mem_size_bytes = buf_sz; 475 ++mregions; 476 } 477 spin_unlock_irqrestore(&ac->lock, flags); 478 479 rc = q6asm_apr_send_session_pkt(a, ac, pkt, 480 ASM_CMDRSP_SHARED_MEM_MAP_REGIONS); 481 482 kfree(pkt); 483 484 return rc; 485 } 486 487 /** 488 * q6asm_map_memory_regions() - map memory regions in the dsp. 489 * 490 * @dir: direction of audio stream 491 * @ac: audio client instanace 492 * @phys: physcial address that needs mapping. 493 * @period_sz: audio period size 494 * @periods: number of periods 495 * 496 * Return: Will be an negative value on failure or zero on success 497 */ 498 int q6asm_map_memory_regions(unsigned int dir, struct audio_client *ac, 499 phys_addr_t phys, 500 size_t period_sz, unsigned int periods) 501 { 502 struct audio_buffer *buf; 503 unsigned long flags; 504 int cnt; 505 int rc; 506 507 spin_lock_irqsave(&ac->lock, flags); 508 if (ac->port[dir].buf) { 509 dev_err(ac->dev, "Buffer already allocated\n"); 510 spin_unlock_irqrestore(&ac->lock, flags); 511 return 0; 512 } 513 514 buf = kzalloc(((sizeof(struct audio_buffer)) * periods), GFP_ATOMIC); 515 if (!buf) { 516 spin_unlock_irqrestore(&ac->lock, flags); 517 return -ENOMEM; 518 } 519 520 521 ac->port[dir].buf = buf; 522 523 buf[0].phys = phys; 524 buf[0].size = period_sz; 525 526 for (cnt = 1; cnt < periods; cnt++) { 527 if (period_sz > 0) { 528 buf[cnt].phys = buf[0].phys + (cnt * period_sz); 529 buf[cnt].size = period_sz; 530 } 531 } 532 ac->port[dir].num_periods = periods; 533 534 spin_unlock_irqrestore(&ac->lock, flags); 535 536 rc = __q6asm_memory_map_regions(ac, dir, period_sz, periods, 1); 537 if (rc < 0) { 538 dev_err(ac->dev, "Memory_map_regions failed\n"); 539 q6asm_audio_client_free_buf(ac, &ac->port[dir]); 540 } 541 542 return rc; 543 } 544 EXPORT_SYMBOL_GPL(q6asm_map_memory_regions); 545 546 static void q6asm_audio_client_release(struct kref *ref) 547 { 548 struct audio_client *ac; 549 struct q6asm *a; 550 unsigned long flags; 551 552 ac = container_of(ref, struct audio_client, refcount); 553 a = ac->q6asm; 554 555 spin_lock_irqsave(&a->slock, flags); 556 a->session[ac->session] = NULL; 557 spin_unlock_irqrestore(&a->slock, flags); 558 559 kfree(ac); 560 } 561 562 /** 563 * q6asm_audio_client_free() - Freee allocated audio client 564 * 565 * @ac: audio client to free 566 */ 567 void q6asm_audio_client_free(struct audio_client *ac) 568 { 569 kref_put(&ac->refcount, q6asm_audio_client_release); 570 } 571 EXPORT_SYMBOL_GPL(q6asm_audio_client_free); 572 573 static struct audio_client *q6asm_get_audio_client(struct q6asm *a, 574 int session_id) 575 { 576 struct audio_client *ac = NULL; 577 unsigned long flags; 578 579 spin_lock_irqsave(&a->slock, flags); 580 if ((session_id <= 0) || (session_id > MAX_SESSIONS)) { 581 dev_err(a->dev, "invalid session: %d\n", session_id); 582 goto err; 583 } 584 585 /* check for valid session */ 586 if (!a->session[session_id]) 587 goto err; 588 else if (a->session[session_id]->session != session_id) 589 goto err; 590 591 ac = a->session[session_id]; 592 kref_get(&ac->refcount); 593 err: 594 spin_unlock_irqrestore(&a->slock, flags); 595 return ac; 596 } 597 598 static int32_t q6asm_stream_callback(struct apr_device *adev, 599 struct apr_resp_pkt *data, 600 int session_id) 601 { 602 struct q6asm *q6asm = dev_get_drvdata(&adev->dev); 603 struct aprv2_ibasic_rsp_result_t *result; 604 struct apr_hdr *hdr = &data->hdr; 605 struct audio_port_data *port; 606 struct audio_client *ac; 607 uint32_t client_event = 0; 608 int ret = 0; 609 610 ac = q6asm_get_audio_client(q6asm, session_id); 611 if (!ac)/* Audio client might already be freed by now */ 612 return 0; 613 614 result = data->payload; 615 616 switch (hdr->opcode) { 617 case APR_BASIC_RSP_RESULT: 618 switch (result->opcode) { 619 case ASM_SESSION_CMD_PAUSE: 620 client_event = ASM_CLIENT_EVENT_CMD_PAUSE_DONE; 621 break; 622 case ASM_SESSION_CMD_SUSPEND: 623 client_event = ASM_CLIENT_EVENT_CMD_SUSPEND_DONE; 624 break; 625 case ASM_DATA_CMD_EOS: 626 client_event = ASM_CLIENT_EVENT_CMD_EOS_DONE; 627 break; 628 case ASM_STREAM_CMD_FLUSH: 629 client_event = ASM_CLIENT_EVENT_CMD_FLUSH_DONE; 630 break; 631 case ASM_SESSION_CMD_RUN_V2: 632 client_event = ASM_CLIENT_EVENT_CMD_RUN_DONE; 633 break; 634 case ASM_STREAM_CMD_CLOSE: 635 client_event = ASM_CLIENT_EVENT_CMD_CLOSE_DONE; 636 break; 637 case ASM_STREAM_CMD_FLUSH_READBUFS: 638 client_event = ASM_CLIENT_EVENT_CMD_OUT_FLUSH_DONE; 639 break; 640 case ASM_STREAM_CMD_OPEN_WRITE_V3: 641 case ASM_STREAM_CMD_OPEN_READ_V3: 642 case ASM_STREAM_CMD_OPEN_READWRITE_V2: 643 case ASM_STREAM_CMD_SET_ENCDEC_PARAM: 644 case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2: 645 if (result->status != 0) { 646 dev_err(ac->dev, 647 "cmd = 0x%x returned error = 0x%x\n", 648 result->opcode, result->status); 649 ac->result = *result; 650 wake_up(&ac->cmd_wait); 651 ret = 0; 652 goto done; 653 } 654 break; 655 default: 656 dev_err(ac->dev, "command[0x%x] not expecting rsp\n", 657 result->opcode); 658 break; 659 } 660 661 ac->result = *result; 662 wake_up(&ac->cmd_wait); 663 664 if (ac->cb) 665 ac->cb(client_event, hdr->token, 666 data->payload, ac->priv); 667 668 ret = 0; 669 goto done; 670 671 case ASM_DATA_EVENT_WRITE_DONE_V2: 672 client_event = ASM_CLIENT_EVENT_DATA_WRITE_DONE; 673 if (ac->io_mode & ASM_SYNC_IO_MODE) { 674 phys_addr_t phys; 675 unsigned long flags; 676 677 spin_lock_irqsave(&ac->lock, flags); 678 679 port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK]; 680 681 if (!port->buf) { 682 spin_unlock_irqrestore(&ac->lock, flags); 683 ret = 0; 684 goto done; 685 } 686 687 phys = port->buf[hdr->token].phys; 688 689 if (lower_32_bits(phys) != result->opcode || 690 upper_32_bits(phys) != result->status) { 691 dev_err(ac->dev, "Expected addr %pa\n", 692 &port->buf[hdr->token].phys); 693 spin_unlock_irqrestore(&ac->lock, flags); 694 ret = -EINVAL; 695 goto done; 696 } 697 spin_unlock_irqrestore(&ac->lock, flags); 698 } 699 break; 700 case ASM_DATA_EVENT_READ_DONE_V2: 701 client_event = ASM_CLIENT_EVENT_DATA_READ_DONE; 702 if (ac->io_mode & ASM_SYNC_IO_MODE) { 703 struct asm_data_cmd_read_v2_done *done = data->payload; 704 unsigned long flags; 705 phys_addr_t phys; 706 707 spin_lock_irqsave(&ac->lock, flags); 708 port = &ac->port[SNDRV_PCM_STREAM_CAPTURE]; 709 if (!port->buf) { 710 spin_unlock_irqrestore(&ac->lock, flags); 711 ret = 0; 712 goto done; 713 } 714 715 phys = port->buf[hdr->token].phys; 716 717 if (upper_32_bits(phys) != done->buf_addr_msw || 718 lower_32_bits(phys) != done->buf_addr_lsw) { 719 dev_err(ac->dev, "Expected addr %pa %08x-%08x\n", 720 &port->buf[hdr->token].phys, 721 done->buf_addr_lsw, 722 done->buf_addr_msw); 723 spin_unlock_irqrestore(&ac->lock, flags); 724 ret = -EINVAL; 725 goto done; 726 } 727 spin_unlock_irqrestore(&ac->lock, flags); 728 } 729 730 break; 731 } 732 733 if (ac->cb) 734 ac->cb(client_event, hdr->token, data->payload, ac->priv); 735 736 done: 737 kref_put(&ac->refcount, q6asm_audio_client_release); 738 return ret; 739 } 740 741 static int q6asm_srvc_callback(struct apr_device *adev, 742 struct apr_resp_pkt *data) 743 { 744 struct q6asm *q6asm = dev_get_drvdata(&adev->dev); 745 struct aprv2_ibasic_rsp_result_t *result; 746 struct audio_port_data *port; 747 struct audio_client *ac = NULL; 748 struct apr_hdr *hdr = &data->hdr; 749 struct q6asm *a; 750 uint32_t sid = 0; 751 uint32_t dir = 0; 752 int session_id; 753 754 session_id = (hdr->dest_port >> 8) & 0xFF; 755 if (session_id) 756 return q6asm_stream_callback(adev, data, session_id); 757 758 sid = (hdr->token >> 8) & 0x0F; 759 ac = q6asm_get_audio_client(q6asm, sid); 760 if (!ac) { 761 dev_err(&adev->dev, "Audio Client not active\n"); 762 return 0; 763 } 764 765 a = dev_get_drvdata(ac->dev->parent); 766 dir = (hdr->token & 0x0F); 767 port = &ac->port[dir]; 768 result = data->payload; 769 770 switch (hdr->opcode) { 771 case APR_BASIC_RSP_RESULT: 772 switch (result->opcode) { 773 case ASM_CMD_SHARED_MEM_MAP_REGIONS: 774 case ASM_CMD_SHARED_MEM_UNMAP_REGIONS: 775 ac->result = *result; 776 wake_up(&a->mem_wait); 777 break; 778 default: 779 dev_err(&adev->dev, "command[0x%x] not expecting rsp\n", 780 result->opcode); 781 break; 782 } 783 goto done; 784 case ASM_CMDRSP_SHARED_MEM_MAP_REGIONS: 785 ac->result.status = 0; 786 ac->result.opcode = hdr->opcode; 787 port->mem_map_handle = result->opcode; 788 wake_up(&a->mem_wait); 789 break; 790 case ASM_CMD_SHARED_MEM_UNMAP_REGIONS: 791 ac->result.opcode = hdr->opcode; 792 ac->result.status = 0; 793 port->mem_map_handle = 0; 794 wake_up(&a->mem_wait); 795 break; 796 default: 797 dev_dbg(&adev->dev, "command[0x%x]success [0x%x]\n", 798 result->opcode, result->status); 799 break; 800 } 801 802 if (ac->cb) 803 ac->cb(hdr->opcode, hdr->token, data->payload, ac->priv); 804 805 done: 806 kref_put(&ac->refcount, q6asm_audio_client_release); 807 808 return 0; 809 } 810 811 /** 812 * q6asm_get_session_id() - get session id for audio client 813 * 814 * @c: audio client pointer 815 * 816 * Return: Will be an session id of the audio client. 817 */ 818 int q6asm_get_session_id(struct audio_client *c) 819 { 820 return c->session; 821 } 822 EXPORT_SYMBOL_GPL(q6asm_get_session_id); 823 824 /** 825 * q6asm_audio_client_alloc() - Allocate a new audio client 826 * 827 * @dev: Pointer to asm child device. 828 * @cb: event callback. 829 * @priv: private data associated with this client. 830 * @stream_id: stream id 831 * @perf_mode: performace mode for this client 832 * 833 * Return: Will be an error pointer on error or a valid audio client 834 * on success. 835 */ 836 struct audio_client *q6asm_audio_client_alloc(struct device *dev, q6asm_cb cb, 837 void *priv, int stream_id, 838 int perf_mode) 839 { 840 struct q6asm *a = dev_get_drvdata(dev->parent); 841 struct audio_client *ac; 842 unsigned long flags; 843 844 ac = q6asm_get_audio_client(a, stream_id + 1); 845 if (ac) { 846 dev_err(dev, "Audio Client already active\n"); 847 return ac; 848 } 849 850 ac = kzalloc(sizeof(*ac), GFP_KERNEL); 851 if (!ac) 852 return ERR_PTR(-ENOMEM); 853 854 spin_lock_irqsave(&a->slock, flags); 855 a->session[stream_id + 1] = ac; 856 spin_unlock_irqrestore(&a->slock, flags); 857 ac->session = stream_id + 1; 858 ac->cb = cb; 859 ac->dev = dev; 860 ac->q6asm = a; 861 ac->priv = priv; 862 ac->io_mode = ASM_SYNC_IO_MODE; 863 ac->perf_mode = perf_mode; 864 /* DSP expects stream id from 1 */ 865 ac->stream_id = 1; 866 ac->adev = a->adev; 867 kref_init(&ac->refcount); 868 869 init_waitqueue_head(&ac->cmd_wait); 870 mutex_init(&ac->cmd_lock); 871 spin_lock_init(&ac->lock); 872 873 return ac; 874 } 875 EXPORT_SYMBOL_GPL(q6asm_audio_client_alloc); 876 877 static int q6asm_ac_send_cmd_sync(struct audio_client *ac, struct apr_pkt *pkt) 878 { 879 struct apr_hdr *hdr = &pkt->hdr; 880 int rc; 881 882 mutex_lock(&ac->cmd_lock); 883 ac->result.opcode = 0; 884 ac->result.status = 0; 885 886 rc = apr_send_pkt(ac->adev, pkt); 887 if (rc < 0) 888 goto err; 889 890 rc = wait_event_timeout(ac->cmd_wait, 891 (ac->result.opcode == hdr->opcode), 5 * HZ); 892 if (!rc) { 893 dev_err(ac->dev, "CMD timeout\n"); 894 rc = -ETIMEDOUT; 895 goto err; 896 } 897 898 if (ac->result.status > 0) { 899 dev_err(ac->dev, "DSP returned error[%x]\n", 900 ac->result.status); 901 rc = -EINVAL; 902 } else { 903 rc = 0; 904 } 905 906 907 err: 908 mutex_unlock(&ac->cmd_lock); 909 return rc; 910 } 911 912 /** 913 * q6asm_open_write() - Open audio client for writing 914 * 915 * @ac: audio client pointer 916 * @format: audio sample format 917 * @bits_per_sample: bits per sample 918 * 919 * Return: Will be an negative value on error or zero on success 920 */ 921 int q6asm_open_write(struct audio_client *ac, uint32_t format, 922 u32 codec_profile, uint16_t bits_per_sample) 923 { 924 struct asm_stream_cmd_open_write_v3 *open; 925 struct apr_pkt *pkt; 926 void *p; 927 int rc, pkt_size; 928 929 pkt_size = APR_HDR_SIZE + sizeof(*open); 930 931 p = kzalloc(pkt_size, GFP_KERNEL); 932 if (!p) 933 return -ENOMEM; 934 935 pkt = p; 936 open = p + APR_HDR_SIZE; 937 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); 938 939 pkt->hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3; 940 open->mode_flags = 0x00; 941 open->mode_flags |= ASM_LEGACY_STREAM_SESSION; 942 943 /* source endpoint : matrix */ 944 open->sink_endpointype = ASM_END_POINT_DEVICE_MATRIX; 945 open->bits_per_sample = bits_per_sample; 946 open->postprocopo_id = ASM_NULL_POPP_TOPOLOGY; 947 948 switch (format) { 949 case SND_AUDIOCODEC_MP3: 950 open->dec_fmt_id = ASM_MEDIA_FMT_MP3; 951 break; 952 case FORMAT_LINEAR_PCM: 953 open->dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; 954 break; 955 case SND_AUDIOCODEC_FLAC: 956 open->dec_fmt_id = ASM_MEDIA_FMT_FLAC; 957 break; 958 case SND_AUDIOCODEC_WMA: 959 switch (codec_profile) { 960 case SND_AUDIOPROFILE_WMA9: 961 open->dec_fmt_id = ASM_MEDIA_FMT_WMA_V9; 962 break; 963 case SND_AUDIOPROFILE_WMA10: 964 case SND_AUDIOPROFILE_WMA9_PRO: 965 case SND_AUDIOPROFILE_WMA9_LOSSLESS: 966 case SND_AUDIOPROFILE_WMA10_LOSSLESS: 967 open->dec_fmt_id = ASM_MEDIA_FMT_WMA_V10; 968 break; 969 default: 970 dev_err(ac->dev, "Invalid codec profile 0x%x\n", 971 codec_profile); 972 rc = -EINVAL; 973 goto err; 974 } 975 break; 976 case SND_AUDIOCODEC_ALAC: 977 open->dec_fmt_id = ASM_MEDIA_FMT_ALAC; 978 break; 979 case SND_AUDIOCODEC_APE: 980 open->dec_fmt_id = ASM_MEDIA_FMT_APE; 981 break; 982 default: 983 dev_err(ac->dev, "Invalid format 0x%x\n", format); 984 rc = -EINVAL; 985 goto err; 986 } 987 988 rc = q6asm_ac_send_cmd_sync(ac, pkt); 989 if (rc < 0) 990 goto err; 991 992 ac->io_mode |= ASM_TUN_WRITE_IO_MODE; 993 994 err: 995 kfree(pkt); 996 return rc; 997 } 998 EXPORT_SYMBOL_GPL(q6asm_open_write); 999 1000 static int __q6asm_run(struct audio_client *ac, uint32_t flags, 1001 uint32_t msw_ts, uint32_t lsw_ts, bool wait) 1002 { 1003 struct asm_session_cmd_run_v2 *run; 1004 struct apr_pkt *pkt; 1005 int pkt_size, rc; 1006 void *p; 1007 1008 pkt_size = APR_HDR_SIZE + sizeof(*run); 1009 p = kzalloc(pkt_size, GFP_ATOMIC); 1010 if (!p) 1011 return -ENOMEM; 1012 1013 pkt = p; 1014 run = p + APR_HDR_SIZE; 1015 1016 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); 1017 1018 pkt->hdr.opcode = ASM_SESSION_CMD_RUN_V2; 1019 run->flags = flags; 1020 run->time_lsw = lsw_ts; 1021 run->time_msw = msw_ts; 1022 if (wait) { 1023 rc = q6asm_ac_send_cmd_sync(ac, pkt); 1024 } else { 1025 rc = apr_send_pkt(ac->adev, pkt); 1026 if (rc == pkt_size) 1027 rc = 0; 1028 } 1029 1030 kfree(pkt); 1031 return rc; 1032 } 1033 1034 /** 1035 * q6asm_run() - start the audio client 1036 * 1037 * @ac: audio client pointer 1038 * @flags: flags associated with write 1039 * @msw_ts: timestamp msw 1040 * @lsw_ts: timestamp lsw 1041 * 1042 * Return: Will be an negative value on error or zero on success 1043 */ 1044 int q6asm_run(struct audio_client *ac, uint32_t flags, 1045 uint32_t msw_ts, uint32_t lsw_ts) 1046 { 1047 return __q6asm_run(ac, flags, msw_ts, lsw_ts, true); 1048 } 1049 EXPORT_SYMBOL_GPL(q6asm_run); 1050 1051 /** 1052 * q6asm_run_nowait() - start the audio client withou blocking 1053 * 1054 * @ac: audio client pointer 1055 * @flags: flags associated with write 1056 * @msw_ts: timestamp msw 1057 * @lsw_ts: timestamp lsw 1058 * 1059 * Return: Will be an negative value on error or zero on success 1060 */ 1061 int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, 1062 uint32_t msw_ts, uint32_t lsw_ts) 1063 { 1064 return __q6asm_run(ac, flags, msw_ts, lsw_ts, false); 1065 } 1066 EXPORT_SYMBOL_GPL(q6asm_run_nowait); 1067 1068 /** 1069 * q6asm_media_format_block_multi_ch_pcm() - setup pcm configuration 1070 * 1071 * @ac: audio client pointer 1072 * @rate: audio sample rate 1073 * @channels: number of audio channels. 1074 * @channel_map: channel map pointer 1075 * @bits_per_sample: bits per sample 1076 * 1077 * Return: Will be an negative value on error or zero on success 1078 */ 1079 int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, 1080 uint32_t rate, uint32_t channels, 1081 u8 channel_map[PCM_MAX_NUM_CHANNEL], 1082 uint16_t bits_per_sample) 1083 { 1084 struct asm_multi_channel_pcm_fmt_blk_v2 *fmt; 1085 struct apr_pkt *pkt; 1086 u8 *channel_mapping; 1087 void *p; 1088 int rc, pkt_size; 1089 1090 pkt_size = APR_HDR_SIZE + sizeof(*fmt); 1091 p = kzalloc(pkt_size, GFP_KERNEL); 1092 if (!p) 1093 return -ENOMEM; 1094 1095 pkt = p; 1096 fmt = p + APR_HDR_SIZE; 1097 1098 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); 1099 1100 pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; 1101 fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); 1102 fmt->num_channels = channels; 1103 fmt->bits_per_sample = bits_per_sample; 1104 fmt->sample_rate = rate; 1105 fmt->is_signed = 1; 1106 1107 channel_mapping = fmt->channel_mapping; 1108 1109 if (channel_map) { 1110 memcpy(channel_mapping, channel_map, PCM_MAX_NUM_CHANNEL); 1111 } else { 1112 if (q6dsp_map_channels(channel_mapping, channels)) { 1113 dev_err(ac->dev, " map channels failed %d\n", channels); 1114 rc = -EINVAL; 1115 goto err; 1116 } 1117 } 1118 1119 rc = q6asm_ac_send_cmd_sync(ac, pkt); 1120 1121 err: 1122 kfree(pkt); 1123 return rc; 1124 } 1125 EXPORT_SYMBOL_GPL(q6asm_media_format_block_multi_ch_pcm); 1126 1127 1128 int q6asm_stream_media_format_block_flac(struct audio_client *ac, 1129 struct q6asm_flac_cfg *cfg) 1130 { 1131 struct asm_flac_fmt_blk_v2 *fmt; 1132 struct apr_pkt *pkt; 1133 void *p; 1134 int rc, pkt_size; 1135 1136 pkt_size = APR_HDR_SIZE + sizeof(*fmt); 1137 p = kzalloc(pkt_size, GFP_KERNEL); 1138 if (!p) 1139 return -ENOMEM; 1140 1141 pkt = p; 1142 fmt = p + APR_HDR_SIZE; 1143 1144 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); 1145 1146 pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; 1147 fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); 1148 fmt->is_stream_info_present = cfg->stream_info_present; 1149 fmt->num_channels = cfg->ch_cfg; 1150 fmt->min_blk_size = cfg->min_blk_size; 1151 fmt->max_blk_size = cfg->max_blk_size; 1152 fmt->sample_rate = cfg->sample_rate; 1153 fmt->min_frame_size = cfg->min_frame_size; 1154 fmt->max_frame_size = cfg->max_frame_size; 1155 fmt->sample_size = cfg->sample_size; 1156 1157 rc = q6asm_ac_send_cmd_sync(ac, pkt); 1158 kfree(pkt); 1159 1160 return rc; 1161 } 1162 EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_flac); 1163 1164 int q6asm_stream_media_format_block_wma_v9(struct audio_client *ac, 1165 struct q6asm_wma_cfg *cfg) 1166 { 1167 struct asm_wmastdv9_fmt_blk_v2 *fmt; 1168 struct apr_pkt *pkt; 1169 void *p; 1170 int rc, pkt_size; 1171 1172 pkt_size = APR_HDR_SIZE + sizeof(*fmt); 1173 p = kzalloc(pkt_size, GFP_KERNEL); 1174 if (!p) 1175 return -ENOMEM; 1176 1177 pkt = p; 1178 fmt = p + APR_HDR_SIZE; 1179 1180 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); 1181 1182 pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; 1183 fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); 1184 fmt->fmtag = cfg->fmtag; 1185 fmt->num_channels = cfg->num_channels; 1186 fmt->sample_rate = cfg->sample_rate; 1187 fmt->bytes_per_sec = cfg->bytes_per_sec; 1188 fmt->blk_align = cfg->block_align; 1189 fmt->bits_per_sample = cfg->bits_per_sample; 1190 fmt->channel_mask = cfg->channel_mask; 1191 fmt->enc_options = cfg->enc_options; 1192 fmt->reserved = 0; 1193 1194 rc = q6asm_ac_send_cmd_sync(ac, pkt); 1195 kfree(pkt); 1196 1197 return rc; 1198 } 1199 EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_wma_v9); 1200 1201 int q6asm_stream_media_format_block_wma_v10(struct audio_client *ac, 1202 struct q6asm_wma_cfg *cfg) 1203 { 1204 struct asm_wmaprov10_fmt_blk_v2 *fmt; 1205 struct apr_pkt *pkt; 1206 void *p; 1207 int rc, pkt_size; 1208 1209 pkt_size = APR_HDR_SIZE + sizeof(*fmt); 1210 p = kzalloc(pkt_size, GFP_KERNEL); 1211 if (!p) 1212 return -ENOMEM; 1213 1214 pkt = p; 1215 fmt = p + APR_HDR_SIZE; 1216 1217 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); 1218 1219 pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; 1220 fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); 1221 fmt->fmtag = cfg->fmtag; 1222 fmt->num_channels = cfg->num_channels; 1223 fmt->sample_rate = cfg->sample_rate; 1224 fmt->bytes_per_sec = cfg->bytes_per_sec; 1225 fmt->blk_align = cfg->block_align; 1226 fmt->bits_per_sample = cfg->bits_per_sample; 1227 fmt->channel_mask = cfg->channel_mask; 1228 fmt->enc_options = cfg->enc_options; 1229 fmt->advanced_enc_options1 = cfg->adv_enc_options; 1230 fmt->advanced_enc_options2 = cfg->adv_enc_options2; 1231 1232 rc = q6asm_ac_send_cmd_sync(ac, pkt); 1233 kfree(pkt); 1234 1235 return rc; 1236 } 1237 EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_wma_v10); 1238 1239 int q6asm_stream_media_format_block_alac(struct audio_client *ac, 1240 struct q6asm_alac_cfg *cfg) 1241 { 1242 struct asm_alac_fmt_blk_v2 *fmt; 1243 struct apr_pkt *pkt; 1244 void *p; 1245 int rc, pkt_size; 1246 1247 pkt_size = APR_HDR_SIZE + sizeof(*fmt); 1248 p = kzalloc(pkt_size, GFP_KERNEL); 1249 if (!p) 1250 return -ENOMEM; 1251 1252 pkt = p; 1253 fmt = p + APR_HDR_SIZE; 1254 1255 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); 1256 1257 pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; 1258 fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); 1259 1260 fmt->frame_length = cfg->frame_length; 1261 fmt->compatible_version = cfg->compatible_version; 1262 fmt->bit_depth = cfg->bit_depth; 1263 fmt->num_channels = cfg->num_channels; 1264 fmt->max_run = cfg->max_run; 1265 fmt->max_frame_bytes = cfg->max_frame_bytes; 1266 fmt->avg_bit_rate = cfg->avg_bit_rate; 1267 fmt->sample_rate = cfg->sample_rate; 1268 fmt->channel_layout_tag = cfg->channel_layout_tag; 1269 fmt->pb = cfg->pb; 1270 fmt->mb = cfg->mb; 1271 fmt->kb = cfg->kb; 1272 1273 rc = q6asm_ac_send_cmd_sync(ac, pkt); 1274 kfree(pkt); 1275 1276 return rc; 1277 } 1278 EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_alac); 1279 1280 int q6asm_stream_media_format_block_ape(struct audio_client *ac, 1281 struct q6asm_ape_cfg *cfg) 1282 { 1283 struct asm_ape_fmt_blk_v2 *fmt; 1284 struct apr_pkt *pkt; 1285 void *p; 1286 int rc, pkt_size; 1287 1288 pkt_size = APR_HDR_SIZE + sizeof(*fmt); 1289 p = kzalloc(pkt_size, GFP_KERNEL); 1290 if (!p) 1291 return -ENOMEM; 1292 1293 pkt = p; 1294 fmt = p + APR_HDR_SIZE; 1295 1296 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); 1297 1298 pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; 1299 fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); 1300 1301 fmt->compatible_version = cfg->compatible_version; 1302 fmt->compression_level = cfg->compression_level; 1303 fmt->format_flags = cfg->format_flags; 1304 fmt->blocks_per_frame = cfg->blocks_per_frame; 1305 fmt->final_frame_blocks = cfg->final_frame_blocks; 1306 fmt->total_frames = cfg->total_frames; 1307 fmt->bits_per_sample = cfg->bits_per_sample; 1308 fmt->num_channels = cfg->num_channels; 1309 fmt->sample_rate = cfg->sample_rate; 1310 fmt->seek_table_present = cfg->seek_table_present; 1311 1312 rc = q6asm_ac_send_cmd_sync(ac, pkt); 1313 kfree(pkt); 1314 1315 return rc; 1316 } 1317 EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_ape); 1318 1319 /** 1320 * q6asm_enc_cfg_blk_pcm_format_support() - setup pcm configuration for capture 1321 * 1322 * @ac: audio client pointer 1323 * @rate: audio sample rate 1324 * @channels: number of audio channels. 1325 * @bits_per_sample: bits per sample 1326 * 1327 * Return: Will be an negative value on error or zero on success 1328 */ 1329 int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac, 1330 uint32_t rate, uint32_t channels, uint16_t bits_per_sample) 1331 { 1332 struct asm_multi_channel_pcm_enc_cfg_v2 *enc_cfg; 1333 struct apr_pkt *pkt; 1334 u8 *channel_mapping; 1335 u32 frames_per_buf = 0; 1336 int pkt_size, rc; 1337 void *p; 1338 1339 pkt_size = APR_HDR_SIZE + sizeof(*enc_cfg); 1340 p = kzalloc(pkt_size, GFP_KERNEL); 1341 if (!p) 1342 return -ENOMEM; 1343 1344 pkt = p; 1345 enc_cfg = p + APR_HDR_SIZE; 1346 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); 1347 1348 pkt->hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM; 1349 enc_cfg->encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2; 1350 enc_cfg->encdec.param_size = sizeof(*enc_cfg) - sizeof(enc_cfg->encdec); 1351 enc_cfg->encblk.frames_per_buf = frames_per_buf; 1352 enc_cfg->encblk.enc_cfg_blk_size = enc_cfg->encdec.param_size - 1353 sizeof(struct asm_enc_cfg_blk_param_v2); 1354 1355 enc_cfg->num_channels = channels; 1356 enc_cfg->bits_per_sample = bits_per_sample; 1357 enc_cfg->sample_rate = rate; 1358 enc_cfg->is_signed = 1; 1359 channel_mapping = enc_cfg->channel_mapping; 1360 1361 if (q6dsp_map_channels(channel_mapping, channels)) { 1362 rc = -EINVAL; 1363 goto err; 1364 } 1365 1366 rc = q6asm_ac_send_cmd_sync(ac, pkt); 1367 err: 1368 kfree(pkt); 1369 return rc; 1370 } 1371 EXPORT_SYMBOL_GPL(q6asm_enc_cfg_blk_pcm_format_support); 1372 1373 1374 /** 1375 * q6asm_read() - read data of period size from audio client 1376 * 1377 * @ac: audio client pointer 1378 * 1379 * Return: Will be an negative value on error or zero on success 1380 */ 1381 int q6asm_read(struct audio_client *ac) 1382 { 1383 struct asm_data_cmd_read_v2 *read; 1384 struct audio_port_data *port; 1385 struct audio_buffer *ab; 1386 struct apr_pkt *pkt; 1387 unsigned long flags; 1388 int pkt_size; 1389 int rc = 0; 1390 void *p; 1391 1392 pkt_size = APR_HDR_SIZE + sizeof(*read); 1393 p = kzalloc(pkt_size, GFP_ATOMIC); 1394 if (!p) 1395 return -ENOMEM; 1396 1397 pkt = p; 1398 read = p + APR_HDR_SIZE; 1399 1400 spin_lock_irqsave(&ac->lock, flags); 1401 port = &ac->port[SNDRV_PCM_STREAM_CAPTURE]; 1402 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, ac->stream_id); 1403 ab = &port->buf[port->dsp_buf]; 1404 pkt->hdr.opcode = ASM_DATA_CMD_READ_V2; 1405 read->buf_addr_lsw = lower_32_bits(ab->phys); 1406 read->buf_addr_msw = upper_32_bits(ab->phys); 1407 read->mem_map_handle = port->mem_map_handle; 1408 1409 read->buf_size = ab->size; 1410 read->seq_id = port->dsp_buf; 1411 pkt->hdr.token = port->dsp_buf; 1412 1413 port->dsp_buf++; 1414 1415 if (port->dsp_buf >= port->num_periods) 1416 port->dsp_buf = 0; 1417 1418 spin_unlock_irqrestore(&ac->lock, flags); 1419 rc = apr_send_pkt(ac->adev, pkt); 1420 if (rc == pkt_size) 1421 rc = 0; 1422 else 1423 pr_err("read op[0x%x]rc[%d]\n", pkt->hdr.opcode, rc); 1424 1425 kfree(pkt); 1426 return rc; 1427 } 1428 EXPORT_SYMBOL_GPL(q6asm_read); 1429 1430 static int __q6asm_open_read(struct audio_client *ac, 1431 uint32_t format, uint16_t bits_per_sample) 1432 { 1433 struct asm_stream_cmd_open_read_v3 *open; 1434 struct apr_pkt *pkt; 1435 int pkt_size, rc; 1436 void *p; 1437 1438 pkt_size = APR_HDR_SIZE + sizeof(*open); 1439 p = kzalloc(pkt_size, GFP_KERNEL); 1440 if (!p) 1441 return -ENOMEM; 1442 1443 pkt = p; 1444 open = p + APR_HDR_SIZE; 1445 1446 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); 1447 pkt->hdr.opcode = ASM_STREAM_CMD_OPEN_READ_V3; 1448 /* Stream prio : High, provide meta info with encoded frames */ 1449 open->src_endpointype = ASM_END_POINT_DEVICE_MATRIX; 1450 1451 open->preprocopo_id = ASM_STREAM_POSTPROC_TOPO_ID_NONE; 1452 open->bits_per_sample = bits_per_sample; 1453 open->mode_flags = 0x0; 1454 1455 open->mode_flags |= ASM_LEGACY_STREAM_SESSION << 1456 ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ; 1457 1458 switch (format) { 1459 case FORMAT_LINEAR_PCM: 1460 open->mode_flags |= 0x00; 1461 open->enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; 1462 break; 1463 default: 1464 pr_err("Invalid format[%d]\n", format); 1465 } 1466 1467 rc = q6asm_ac_send_cmd_sync(ac, pkt); 1468 1469 kfree(pkt); 1470 return rc; 1471 } 1472 1473 /** 1474 * q6asm_open_read() - Open audio client for reading 1475 * 1476 * @ac: audio client pointer 1477 * @format: audio sample format 1478 * @bits_per_sample: bits per sample 1479 * 1480 * Return: Will be an negative value on error or zero on success 1481 */ 1482 int q6asm_open_read(struct audio_client *ac, uint32_t format, 1483 uint16_t bits_per_sample) 1484 { 1485 return __q6asm_open_read(ac, format, bits_per_sample); 1486 } 1487 EXPORT_SYMBOL_GPL(q6asm_open_read); 1488 1489 /** 1490 * q6asm_write_async() - non blocking write 1491 * 1492 * @ac: audio client pointer 1493 * @len: length in bytes 1494 * @msw_ts: timestamp msw 1495 * @lsw_ts: timestamp lsw 1496 * @wflags: flags associated with write 1497 * 1498 * Return: Will be an negative value on error or zero on success 1499 */ 1500 int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts, 1501 uint32_t lsw_ts, uint32_t wflags) 1502 { 1503 struct asm_data_cmd_write_v2 *write; 1504 struct audio_port_data *port; 1505 struct audio_buffer *ab; 1506 unsigned long flags; 1507 struct apr_pkt *pkt; 1508 int pkt_size; 1509 int rc = 0; 1510 void *p; 1511 1512 pkt_size = APR_HDR_SIZE + sizeof(*write); 1513 p = kzalloc(pkt_size, GFP_ATOMIC); 1514 if (!p) 1515 return -ENOMEM; 1516 1517 pkt = p; 1518 write = p + APR_HDR_SIZE; 1519 1520 spin_lock_irqsave(&ac->lock, flags); 1521 port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK]; 1522 q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, ac->stream_id); 1523 1524 ab = &port->buf[port->dsp_buf]; 1525 pkt->hdr.token = port->dsp_buf; 1526 pkt->hdr.opcode = ASM_DATA_CMD_WRITE_V2; 1527 write->buf_addr_lsw = lower_32_bits(ab->phys); 1528 write->buf_addr_msw = upper_32_bits(ab->phys); 1529 write->buf_size = len; 1530 write->seq_id = port->dsp_buf; 1531 write->timestamp_lsw = lsw_ts; 1532 write->timestamp_msw = msw_ts; 1533 write->mem_map_handle = 1534 ac->port[SNDRV_PCM_STREAM_PLAYBACK].mem_map_handle; 1535 1536 if (wflags == NO_TIMESTAMP) 1537 write->flags = (wflags & 0x800000FF); 1538 else 1539 write->flags = (0x80000000 | wflags); 1540 1541 port->dsp_buf++; 1542 1543 if (port->dsp_buf >= port->num_periods) 1544 port->dsp_buf = 0; 1545 1546 spin_unlock_irqrestore(&ac->lock, flags); 1547 rc = apr_send_pkt(ac->adev, pkt); 1548 if (rc == pkt_size) 1549 rc = 0; 1550 1551 kfree(pkt); 1552 return rc; 1553 } 1554 EXPORT_SYMBOL_GPL(q6asm_write_async); 1555 1556 static void q6asm_reset_buf_state(struct audio_client *ac) 1557 { 1558 struct audio_port_data *port = NULL; 1559 unsigned long flags; 1560 1561 spin_lock_irqsave(&ac->lock, flags); 1562 port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK]; 1563 port->dsp_buf = 0; 1564 port = &ac->port[SNDRV_PCM_STREAM_CAPTURE]; 1565 port->dsp_buf = 0; 1566 spin_unlock_irqrestore(&ac->lock, flags); 1567 } 1568 1569 static int __q6asm_cmd(struct audio_client *ac, int cmd, bool wait) 1570 { 1571 int stream_id = ac->stream_id; 1572 struct apr_pkt pkt; 1573 int rc; 1574 1575 q6asm_add_hdr(ac, &pkt.hdr, APR_HDR_SIZE, true, stream_id); 1576 1577 switch (cmd) { 1578 case CMD_PAUSE: 1579 pkt.hdr.opcode = ASM_SESSION_CMD_PAUSE; 1580 break; 1581 case CMD_SUSPEND: 1582 pkt.hdr.opcode = ASM_SESSION_CMD_SUSPEND; 1583 break; 1584 case CMD_FLUSH: 1585 pkt.hdr.opcode = ASM_STREAM_CMD_FLUSH; 1586 break; 1587 case CMD_OUT_FLUSH: 1588 pkt.hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS; 1589 break; 1590 case CMD_EOS: 1591 pkt.hdr.opcode = ASM_DATA_CMD_EOS; 1592 break; 1593 case CMD_CLOSE: 1594 pkt.hdr.opcode = ASM_STREAM_CMD_CLOSE; 1595 break; 1596 default: 1597 return -EINVAL; 1598 } 1599 1600 if (wait) 1601 rc = q6asm_ac_send_cmd_sync(ac, &pkt); 1602 else 1603 return apr_send_pkt(ac->adev, &pkt); 1604 1605 if (rc < 0) 1606 return rc; 1607 1608 if (cmd == CMD_FLUSH) 1609 q6asm_reset_buf_state(ac); 1610 1611 return 0; 1612 } 1613 1614 /** 1615 * q6asm_cmd() - run cmd on audio client 1616 * 1617 * @ac: audio client pointer 1618 * @cmd: command to run on audio client. 1619 * 1620 * Return: Will be an negative value on error or zero on success 1621 */ 1622 int q6asm_cmd(struct audio_client *ac, int cmd) 1623 { 1624 return __q6asm_cmd(ac, cmd, true); 1625 } 1626 EXPORT_SYMBOL_GPL(q6asm_cmd); 1627 1628 /** 1629 * q6asm_cmd_nowait() - non blocking, run cmd on audio client 1630 * 1631 * @ac: audio client pointer 1632 * @cmd: command to run on audio client. 1633 * 1634 * Return: Will be an negative value on error or zero on success 1635 */ 1636 int q6asm_cmd_nowait(struct audio_client *ac, int cmd) 1637 { 1638 return __q6asm_cmd(ac, cmd, false); 1639 } 1640 EXPORT_SYMBOL_GPL(q6asm_cmd_nowait); 1641 1642 static int q6asm_probe(struct apr_device *adev) 1643 { 1644 struct device *dev = &adev->dev; 1645 struct q6asm *q6asm; 1646 1647 q6asm = devm_kzalloc(dev, sizeof(*q6asm), GFP_KERNEL); 1648 if (!q6asm) 1649 return -ENOMEM; 1650 1651 q6core_get_svc_api_info(adev->svc_id, &q6asm->ainfo); 1652 1653 q6asm->dev = dev; 1654 q6asm->adev = adev; 1655 init_waitqueue_head(&q6asm->mem_wait); 1656 spin_lock_init(&q6asm->slock); 1657 dev_set_drvdata(dev, q6asm); 1658 1659 return of_platform_populate(dev->of_node, NULL, NULL, dev); 1660 } 1661 1662 static int q6asm_remove(struct apr_device *adev) 1663 { 1664 of_platform_depopulate(&adev->dev); 1665 1666 return 0; 1667 } 1668 static const struct of_device_id q6asm_device_id[] = { 1669 { .compatible = "qcom,q6asm" }, 1670 {}, 1671 }; 1672 MODULE_DEVICE_TABLE(of, q6asm_device_id); 1673 1674 static struct apr_driver qcom_q6asm_driver = { 1675 .probe = q6asm_probe, 1676 .remove = q6asm_remove, 1677 .callback = q6asm_srvc_callback, 1678 .driver = { 1679 .name = "qcom-q6asm", 1680 .of_match_table = of_match_ptr(q6asm_device_id), 1681 }, 1682 }; 1683 1684 module_apr_driver(qcom_q6asm_driver); 1685 MODULE_DESCRIPTION("Q6 Audio Stream Manager driver"); 1686 MODULE_LICENSE("GPL v2"); 1687