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