1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
3 // Copyright (c) 2018, Linaro Limited
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>
14 #include <uapi/sound/asound.h>
15 #include <uapi/sound/compress_params.h>
16 #include <linux/delay.h>
17 #include <linux/slab.h>
21 #include "q6dsp-errno.h"
22 #include "q6dsp-common.h"
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 #define ASM_DATA_CMD_REMOVE_INITIAL_SILENCE 0x00010D67
55 #define ASM_DATA_CMD_REMOVE_TRAILING_SILENCE 0x00010D68
58 #define ASM_LEGACY_STREAM_SESSION 0
59 /* Bit shift for the stream_perf_mode subfield. */
60 #define ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ 29
61 #define ASM_END_POINT_DEVICE_MATRIX 0
62 #define ASM_DEFAULT_APP_TYPE 0
63 #define ASM_SYNC_IO_MODE 0x0001
64 #define ASM_ASYNC_IO_MODE 0x0002
65 #define ASM_TUN_READ_IO_MODE 0x0004 /* tunnel read write mode */
66 #define ASM_TUN_WRITE_IO_MODE 0x0008 /* tunnel read write mode */
67 #define ASM_SHIFT_GAPLESS_MODE_FLAG 31
68 #define ADSP_MEMORY_MAP_SHMEM8_4K_POOL 3
70 struct avs_cmd_shared_mem_map_regions
{
76 struct avs_shared_map_region_payload
{
82 struct avs_cmd_shared_mem_unmap_regions
{
86 struct asm_data_cmd_media_fmt_update_v2
{
90 struct asm_multi_channel_pcm_fmt_blk_v2
{
91 struct asm_data_cmd_media_fmt_update_v2 fmt_blk
;
97 u8 channel_mapping
[PCM_MAX_NUM_CHANNEL
];
100 struct asm_flac_fmt_blk_v2
{
101 struct asm_data_cmd_media_fmt_update_v2 fmt_blk
;
102 u16 is_stream_info_present
;
114 struct asm_wmastdv9_fmt_blk_v2
{
115 struct asm_data_cmd_media_fmt_update_v2 fmt_blk
;
127 struct asm_wmaprov10_fmt_blk_v2
{
128 struct asm_data_cmd_media_fmt_update_v2 fmt_blk
;
137 u16 advanced_enc_options1
;
138 u32 advanced_enc_options2
;
141 struct asm_alac_fmt_blk_v2
{
142 struct asm_data_cmd_media_fmt_update_v2 fmt_blk
;
144 u8 compatible_version
;
154 u32 channel_layout_tag
;
157 struct asm_ape_fmt_blk_v2
{
158 struct asm_data_cmd_media_fmt_update_v2 fmt_blk
;
159 u16 compatible_version
;
160 u16 compression_level
;
162 u32 blocks_per_frame
;
163 u32 final_frame_blocks
;
168 u32 seek_table_present
;
171 struct asm_stream_cmd_set_encdec_param
{
176 struct asm_enc_cfg_blk_param_v2
{
178 u32 enc_cfg_blk_size
;
181 struct asm_multi_channel_pcm_enc_cfg_v2
{
182 struct asm_stream_cmd_set_encdec_param encdec
;
183 struct asm_enc_cfg_blk_param_v2 encblk
;
184 uint16_t num_channels
;
185 uint16_t bits_per_sample
;
186 uint32_t sample_rate
;
189 uint8_t channel_mapping
[8];
192 struct asm_data_cmd_read_v2
{
200 struct asm_data_cmd_read_v2_done
{
206 struct asm_stream_cmd_open_read_v3
{
215 struct asm_data_cmd_write_v2
{
226 struct asm_stream_cmd_open_write_v3
{
228 uint16_t sink_endpointype
;
229 uint16_t bits_per_sample
;
230 uint32_t postprocopo_id
;
234 struct asm_session_cmd_run_v2
{
240 struct audio_buffer
{
242 uint32_t size
; /* size of buffer */
245 struct audio_port_data
{
246 struct audio_buffer
*buf
;
247 uint32_t num_periods
;
249 uint32_t mem_map_handle
;
253 struct apr_device
*adev
;
255 struct q6core_svc_api_info ainfo
;
256 wait_queue_head_t mem_wait
;
258 struct audio_client
*session
[MAX_SESSIONS
+ 1];
261 struct audio_client
{
266 struct apr_device
*adev
;
267 struct mutex cmd_lock
;
269 struct kref refcount
;
270 /* idx:1 out port, 0: in port */
271 struct audio_port_data port
[2];
272 wait_queue_head_t cmd_wait
;
273 struct aprv2_ibasic_rsp_result_t result
;
279 static inline void q6asm_add_hdr(struct audio_client
*ac
, struct apr_hdr
*hdr
,
280 uint32_t pkt_size
, bool cmd_flg
,
283 hdr
->hdr_field
= APR_SEQ_CMD_HDR_FIELD
;
284 hdr
->src_port
= ((ac
->session
<< 8) & 0xFF00) | (stream_id
);
285 hdr
->dest_port
= ((ac
->session
<< 8) & 0xFF00) | (stream_id
);
286 hdr
->pkt_size
= pkt_size
;
288 hdr
->token
= ac
->session
;
291 static int q6asm_apr_send_session_pkt(struct q6asm
*a
, struct audio_client
*ac
,
292 struct apr_pkt
*pkt
, uint32_t rsp_opcode
)
294 struct apr_hdr
*hdr
= &pkt
->hdr
;
297 mutex_lock(&ac
->cmd_lock
);
298 ac
->result
.opcode
= 0;
299 ac
->result
.status
= 0;
300 rc
= apr_send_pkt(a
->adev
, pkt
);
305 rc
= wait_event_timeout(a
->mem_wait
,
306 (ac
->result
.opcode
== hdr
->opcode
) ||
307 (ac
->result
.opcode
== rsp_opcode
),
310 rc
= wait_event_timeout(a
->mem_wait
,
311 (ac
->result
.opcode
== hdr
->opcode
),
315 dev_err(a
->dev
, "CMD %x timeout\n", hdr
->opcode
);
317 } else if (ac
->result
.status
> 0) {
318 dev_err(a
->dev
, "DSP returned error[%x]\n",
324 mutex_unlock(&ac
->cmd_lock
);
328 static int __q6asm_memory_unmap(struct audio_client
*ac
,
329 phys_addr_t buf_add
, int dir
)
331 struct avs_cmd_shared_mem_unmap_regions
*mem_unmap
;
332 struct q6asm
*a
= dev_get_drvdata(ac
->dev
->parent
);
337 if (ac
->port
[dir
].mem_map_handle
== 0) {
338 dev_err(ac
->dev
, "invalid mem handle\n");
342 pkt_size
= APR_HDR_SIZE
+ sizeof(*mem_unmap
);
343 p
= kzalloc(pkt_size
, GFP_KERNEL
);
348 mem_unmap
= p
+ APR_HDR_SIZE
;
350 pkt
->hdr
.hdr_field
= APR_SEQ_CMD_HDR_FIELD
;
351 pkt
->hdr
.src_port
= 0;
352 pkt
->hdr
.dest_port
= 0;
353 pkt
->hdr
.pkt_size
= pkt_size
;
354 pkt
->hdr
.token
= ((ac
->session
<< 8) | dir
);
356 pkt
->hdr
.opcode
= ASM_CMD_SHARED_MEM_UNMAP_REGIONS
;
357 mem_unmap
->mem_map_handle
= ac
->port
[dir
].mem_map_handle
;
359 rc
= q6asm_apr_send_session_pkt(a
, ac
, pkt
, 0);
365 ac
->port
[dir
].mem_map_handle
= 0;
372 static void q6asm_audio_client_free_buf(struct audio_client
*ac
,
373 struct audio_port_data
*port
)
377 spin_lock_irqsave(&ac
->lock
, flags
);
378 port
->num_periods
= 0;
381 spin_unlock_irqrestore(&ac
->lock
, flags
);
385 * q6asm_unmap_memory_regions() - unmap memory regions in the dsp.
387 * @dir: direction of audio stream
388 * @ac: audio client instanace
390 * Return: Will be an negative value on failure or zero on success
392 int q6asm_unmap_memory_regions(unsigned int dir
, struct audio_client
*ac
)
394 struct audio_port_data
*port
;
398 port
= &ac
->port
[dir
];
404 cnt
= port
->num_periods
- 1;
406 rc
= __q6asm_memory_unmap(ac
, port
->buf
[dir
].phys
, dir
);
408 dev_err(ac
->dev
, "%s: Memory_unmap_regions failed %d\n",
414 q6asm_audio_client_free_buf(ac
, port
);
419 EXPORT_SYMBOL_GPL(q6asm_unmap_memory_regions
);
421 static int __q6asm_memory_map_regions(struct audio_client
*ac
, int dir
,
422 size_t period_sz
, unsigned int periods
,
425 struct avs_cmd_shared_mem_map_regions
*cmd
= NULL
;
426 struct avs_shared_map_region_payload
*mregions
= NULL
;
427 struct q6asm
*a
= dev_get_drvdata(ac
->dev
->parent
);
428 struct audio_port_data
*port
= NULL
;
429 struct audio_buffer
*ab
= NULL
;
433 uint32_t num_regions
, buf_sz
;
438 buf_sz
= period_sz
* periods
;
441 num_regions
= periods
;
444 /* DSP expects size should be aligned to 4K */
445 buf_sz
= ALIGN(buf_sz
, 4096);
447 pkt_size
= APR_HDR_SIZE
+ sizeof(*cmd
) +
448 (sizeof(*mregions
) * num_regions
);
450 p
= kzalloc(pkt_size
, GFP_KERNEL
);
455 cmd
= p
+ APR_HDR_SIZE
;
456 mregions
= p
+ APR_HDR_SIZE
+ sizeof(*cmd
);
458 pkt
->hdr
.hdr_field
= APR_SEQ_CMD_HDR_FIELD
;
459 pkt
->hdr
.src_port
= 0;
460 pkt
->hdr
.dest_port
= 0;
461 pkt
->hdr
.pkt_size
= pkt_size
;
462 pkt
->hdr
.token
= ((ac
->session
<< 8) | dir
);
463 pkt
->hdr
.opcode
= ASM_CMD_SHARED_MEM_MAP_REGIONS
;
465 cmd
->mem_pool_id
= ADSP_MEMORY_MAP_SHMEM8_4K_POOL
;
466 cmd
->num_regions
= num_regions
;
467 cmd
->property_flag
= 0x00;
469 spin_lock_irqsave(&ac
->lock
, flags
);
470 port
= &ac
->port
[dir
];
472 for (i
= 0; i
< num_regions
; i
++) {
474 mregions
->shm_addr_lsw
= lower_32_bits(ab
->phys
);
475 mregions
->shm_addr_msw
= upper_32_bits(ab
->phys
);
476 mregions
->mem_size_bytes
= buf_sz
;
479 spin_unlock_irqrestore(&ac
->lock
, flags
);
481 rc
= q6asm_apr_send_session_pkt(a
, ac
, pkt
,
482 ASM_CMDRSP_SHARED_MEM_MAP_REGIONS
);
490 * q6asm_map_memory_regions() - map memory regions in the dsp.
492 * @dir: direction of audio stream
493 * @ac: audio client instanace
494 * @phys: physcial address that needs mapping.
495 * @period_sz: audio period size
496 * @periods: number of periods
498 * Return: Will be an negative value on failure or zero on success
500 int q6asm_map_memory_regions(unsigned int dir
, struct audio_client
*ac
,
502 size_t period_sz
, unsigned int periods
)
504 struct audio_buffer
*buf
;
509 spin_lock_irqsave(&ac
->lock
, flags
);
510 if (ac
->port
[dir
].buf
) {
511 dev_err(ac
->dev
, "Buffer already allocated\n");
512 spin_unlock_irqrestore(&ac
->lock
, flags
);
516 buf
= kzalloc(((sizeof(struct audio_buffer
)) * periods
), GFP_ATOMIC
);
518 spin_unlock_irqrestore(&ac
->lock
, flags
);
523 ac
->port
[dir
].buf
= buf
;
526 buf
[0].size
= period_sz
;
528 for (cnt
= 1; cnt
< periods
; cnt
++) {
530 buf
[cnt
].phys
= buf
[0].phys
+ (cnt
* period_sz
);
531 buf
[cnt
].size
= period_sz
;
534 ac
->port
[dir
].num_periods
= periods
;
536 spin_unlock_irqrestore(&ac
->lock
, flags
);
538 rc
= __q6asm_memory_map_regions(ac
, dir
, period_sz
, periods
, 1);
540 dev_err(ac
->dev
, "Memory_map_regions failed\n");
541 q6asm_audio_client_free_buf(ac
, &ac
->port
[dir
]);
546 EXPORT_SYMBOL_GPL(q6asm_map_memory_regions
);
548 static void q6asm_audio_client_release(struct kref
*ref
)
550 struct audio_client
*ac
;
554 ac
= container_of(ref
, struct audio_client
, refcount
);
557 spin_lock_irqsave(&a
->slock
, flags
);
558 a
->session
[ac
->session
] = NULL
;
559 spin_unlock_irqrestore(&a
->slock
, flags
);
565 * q6asm_audio_client_free() - Freee allocated audio client
567 * @ac: audio client to free
569 void q6asm_audio_client_free(struct audio_client
*ac
)
571 kref_put(&ac
->refcount
, q6asm_audio_client_release
);
573 EXPORT_SYMBOL_GPL(q6asm_audio_client_free
);
575 static struct audio_client
*q6asm_get_audio_client(struct q6asm
*a
,
578 struct audio_client
*ac
= NULL
;
581 spin_lock_irqsave(&a
->slock
, flags
);
582 if ((session_id
<= 0) || (session_id
> MAX_SESSIONS
)) {
583 dev_err(a
->dev
, "invalid session: %d\n", session_id
);
587 /* check for valid session */
588 if (!a
->session
[session_id
])
590 else if (a
->session
[session_id
]->session
!= session_id
)
593 ac
= a
->session
[session_id
];
594 kref_get(&ac
->refcount
);
596 spin_unlock_irqrestore(&a
->slock
, flags
);
600 static int32_t q6asm_stream_callback(struct apr_device
*adev
,
601 struct apr_resp_pkt
*data
,
604 struct q6asm
*q6asm
= dev_get_drvdata(&adev
->dev
);
605 struct aprv2_ibasic_rsp_result_t
*result
;
606 struct apr_hdr
*hdr
= &data
->hdr
;
607 struct audio_port_data
*port
;
608 struct audio_client
*ac
;
609 uint32_t client_event
= 0;
612 ac
= q6asm_get_audio_client(q6asm
, session_id
);
613 if (!ac
)/* Audio client might already be freed by now */
616 result
= data
->payload
;
618 switch (hdr
->opcode
) {
619 case APR_BASIC_RSP_RESULT
:
620 switch (result
->opcode
) {
621 case ASM_SESSION_CMD_PAUSE
:
622 client_event
= ASM_CLIENT_EVENT_CMD_PAUSE_DONE
;
624 case ASM_SESSION_CMD_SUSPEND
:
625 client_event
= ASM_CLIENT_EVENT_CMD_SUSPEND_DONE
;
627 case ASM_STREAM_CMD_FLUSH
:
628 client_event
= ASM_CLIENT_EVENT_CMD_FLUSH_DONE
;
630 case ASM_SESSION_CMD_RUN_V2
:
631 client_event
= ASM_CLIENT_EVENT_CMD_RUN_DONE
;
633 case ASM_STREAM_CMD_CLOSE
:
634 client_event
= ASM_CLIENT_EVENT_CMD_CLOSE_DONE
;
636 case ASM_STREAM_CMD_FLUSH_READBUFS
:
637 client_event
= ASM_CLIENT_EVENT_CMD_OUT_FLUSH_DONE
;
639 case ASM_STREAM_CMD_OPEN_WRITE_V3
:
640 case ASM_STREAM_CMD_OPEN_READ_V3
:
641 case ASM_STREAM_CMD_OPEN_READWRITE_V2
:
642 case ASM_STREAM_CMD_SET_ENCDEC_PARAM
:
643 case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2
:
644 case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE
:
645 case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE
:
646 if (result
->status
!= 0) {
648 "cmd = 0x%x returned error = 0x%x\n",
649 result
->opcode
, result
->status
);
650 ac
->result
= *result
;
651 wake_up(&ac
->cmd_wait
);
657 dev_err(ac
->dev
, "command[0x%x] not expecting rsp\n",
662 ac
->result
= *result
;
663 wake_up(&ac
->cmd_wait
);
666 ac
->cb(client_event
, hdr
->token
,
667 data
->payload
, ac
->priv
);
672 case ASM_DATA_EVENT_WRITE_DONE_V2
:
673 client_event
= ASM_CLIENT_EVENT_DATA_WRITE_DONE
;
674 if (ac
->io_mode
& ASM_SYNC_IO_MODE
) {
677 int token
= hdr
->token
& ASM_WRITE_TOKEN_MASK
;
679 spin_lock_irqsave(&ac
->lock
, flags
);
681 port
= &ac
->port
[SNDRV_PCM_STREAM_PLAYBACK
];
684 spin_unlock_irqrestore(&ac
->lock
, flags
);
689 phys
= port
->buf
[token
].phys
;
691 if (lower_32_bits(phys
) != result
->opcode
||
692 upper_32_bits(phys
) != result
->status
) {
693 dev_err(ac
->dev
, "Expected addr %pa\n",
694 &port
->buf
[token
].phys
);
695 spin_unlock_irqrestore(&ac
->lock
, flags
);
699 spin_unlock_irqrestore(&ac
->lock
, flags
);
702 case ASM_DATA_EVENT_READ_DONE_V2
:
703 client_event
= ASM_CLIENT_EVENT_DATA_READ_DONE
;
704 if (ac
->io_mode
& ASM_SYNC_IO_MODE
) {
705 struct asm_data_cmd_read_v2_done
*done
= data
->payload
;
709 spin_lock_irqsave(&ac
->lock
, flags
);
710 port
= &ac
->port
[SNDRV_PCM_STREAM_CAPTURE
];
712 spin_unlock_irqrestore(&ac
->lock
, flags
);
717 phys
= port
->buf
[hdr
->token
].phys
;
719 if (upper_32_bits(phys
) != done
->buf_addr_msw
||
720 lower_32_bits(phys
) != done
->buf_addr_lsw
) {
721 dev_err(ac
->dev
, "Expected addr %pa %08x-%08x\n",
722 &port
->buf
[hdr
->token
].phys
,
725 spin_unlock_irqrestore(&ac
->lock
, flags
);
729 spin_unlock_irqrestore(&ac
->lock
, flags
);
733 case ASM_DATA_EVENT_RENDERED_EOS
:
734 client_event
= ASM_CLIENT_EVENT_CMD_EOS_DONE
;
739 ac
->cb(client_event
, hdr
->token
, data
->payload
, ac
->priv
);
742 kref_put(&ac
->refcount
, q6asm_audio_client_release
);
746 static int q6asm_srvc_callback(struct apr_device
*adev
,
747 struct apr_resp_pkt
*data
)
749 struct q6asm
*q6asm
= dev_get_drvdata(&adev
->dev
);
750 struct aprv2_ibasic_rsp_result_t
*result
;
751 struct audio_port_data
*port
;
752 struct audio_client
*ac
= NULL
;
753 struct apr_hdr
*hdr
= &data
->hdr
;
759 session_id
= (hdr
->dest_port
>> 8) & 0xFF;
761 return q6asm_stream_callback(adev
, data
, session_id
);
763 sid
= (hdr
->token
>> 8) & 0x0F;
764 ac
= q6asm_get_audio_client(q6asm
, sid
);
766 dev_err(&adev
->dev
, "Audio Client not active\n");
770 a
= dev_get_drvdata(ac
->dev
->parent
);
771 dir
= (hdr
->token
& 0x0F);
772 port
= &ac
->port
[dir
];
773 result
= data
->payload
;
775 switch (hdr
->opcode
) {
776 case APR_BASIC_RSP_RESULT
:
777 switch (result
->opcode
) {
778 case ASM_CMD_SHARED_MEM_MAP_REGIONS
:
779 case ASM_CMD_SHARED_MEM_UNMAP_REGIONS
:
780 ac
->result
= *result
;
781 wake_up(&a
->mem_wait
);
784 dev_err(&adev
->dev
, "command[0x%x] not expecting rsp\n",
789 case ASM_CMDRSP_SHARED_MEM_MAP_REGIONS
:
790 ac
->result
.status
= 0;
791 ac
->result
.opcode
= hdr
->opcode
;
792 port
->mem_map_handle
= result
->opcode
;
793 wake_up(&a
->mem_wait
);
795 case ASM_CMD_SHARED_MEM_UNMAP_REGIONS
:
796 ac
->result
.opcode
= hdr
->opcode
;
797 ac
->result
.status
= 0;
798 port
->mem_map_handle
= 0;
799 wake_up(&a
->mem_wait
);
802 dev_dbg(&adev
->dev
, "command[0x%x]success [0x%x]\n",
803 result
->opcode
, result
->status
);
808 ac
->cb(hdr
->opcode
, hdr
->token
, data
->payload
, ac
->priv
);
811 kref_put(&ac
->refcount
, q6asm_audio_client_release
);
817 * q6asm_get_session_id() - get session id for audio client
819 * @c: audio client pointer
821 * Return: Will be an session id of the audio client.
823 int q6asm_get_session_id(struct audio_client
*c
)
827 EXPORT_SYMBOL_GPL(q6asm_get_session_id
);
830 * q6asm_audio_client_alloc() - Allocate a new audio client
832 * @dev: Pointer to asm child device.
833 * @cb: event callback.
834 * @priv: private data associated with this client.
835 * @session_id: session id
836 * @perf_mode: performace mode for this client
838 * Return: Will be an error pointer on error or a valid audio client
841 struct audio_client
*q6asm_audio_client_alloc(struct device
*dev
, q6asm_cb cb
,
842 void *priv
, int session_id
,
845 struct q6asm
*a
= dev_get_drvdata(dev
->parent
);
846 struct audio_client
*ac
;
849 ac
= q6asm_get_audio_client(a
, session_id
+ 1);
851 dev_err(dev
, "Audio Client already active\n");
855 ac
= kzalloc(sizeof(*ac
), GFP_KERNEL
);
857 return ERR_PTR(-ENOMEM
);
859 spin_lock_irqsave(&a
->slock
, flags
);
860 a
->session
[session_id
+ 1] = ac
;
861 spin_unlock_irqrestore(&a
->slock
, flags
);
862 ac
->session
= session_id
+ 1;
867 ac
->io_mode
= ASM_SYNC_IO_MODE
;
868 ac
->perf_mode
= perf_mode
;
870 kref_init(&ac
->refcount
);
872 init_waitqueue_head(&ac
->cmd_wait
);
873 mutex_init(&ac
->cmd_lock
);
874 spin_lock_init(&ac
->lock
);
878 EXPORT_SYMBOL_GPL(q6asm_audio_client_alloc
);
880 static int q6asm_ac_send_cmd_sync(struct audio_client
*ac
, struct apr_pkt
*pkt
)
882 struct apr_hdr
*hdr
= &pkt
->hdr
;
885 mutex_lock(&ac
->cmd_lock
);
886 ac
->result
.opcode
= 0;
887 ac
->result
.status
= 0;
889 rc
= apr_send_pkt(ac
->adev
, pkt
);
893 rc
= wait_event_timeout(ac
->cmd_wait
,
894 (ac
->result
.opcode
== hdr
->opcode
), 5 * HZ
);
896 dev_err(ac
->dev
, "CMD %x timeout\n", hdr
->opcode
);
901 if (ac
->result
.status
> 0) {
902 dev_err(ac
->dev
, "DSP returned error[%x]\n",
911 mutex_unlock(&ac
->cmd_lock
);
916 * q6asm_open_write() - Open audio client for writing
917 * @ac: audio client pointer
918 * @stream_id: stream id of q6asm session
919 * @format: audio sample format
920 * @codec_profile: compressed format profile
921 * @bits_per_sample: bits per sample
922 * @is_gapless: flag to indicate if this is a gapless stream
924 * Return: Will be an negative value on error or zero on success
926 int q6asm_open_write(struct audio_client
*ac
, uint32_t stream_id
,
927 uint32_t format
, u32 codec_profile
,
928 uint16_t bits_per_sample
, bool is_gapless
)
930 struct asm_stream_cmd_open_write_v3
*open
;
935 pkt_size
= APR_HDR_SIZE
+ sizeof(*open
);
937 p
= kzalloc(pkt_size
, GFP_KERNEL
);
942 open
= p
+ APR_HDR_SIZE
;
943 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
945 pkt
->hdr
.opcode
= ASM_STREAM_CMD_OPEN_WRITE_V3
;
946 open
->mode_flags
= 0x00;
947 open
->mode_flags
|= ASM_LEGACY_STREAM_SESSION
;
949 open
->mode_flags
|= BIT(ASM_SHIFT_GAPLESS_MODE_FLAG
);
951 /* source endpoint : matrix */
952 open
->sink_endpointype
= ASM_END_POINT_DEVICE_MATRIX
;
953 open
->bits_per_sample
= bits_per_sample
;
954 open
->postprocopo_id
= ASM_NULL_POPP_TOPOLOGY
;
957 case SND_AUDIOCODEC_MP3
:
958 open
->dec_fmt_id
= ASM_MEDIA_FMT_MP3
;
960 case FORMAT_LINEAR_PCM
:
961 open
->dec_fmt_id
= ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2
;
963 case SND_AUDIOCODEC_FLAC
:
964 open
->dec_fmt_id
= ASM_MEDIA_FMT_FLAC
;
966 case SND_AUDIOCODEC_WMA
:
967 switch (codec_profile
) {
968 case SND_AUDIOPROFILE_WMA9
:
969 open
->dec_fmt_id
= ASM_MEDIA_FMT_WMA_V9
;
971 case SND_AUDIOPROFILE_WMA10
:
972 case SND_AUDIOPROFILE_WMA9_PRO
:
973 case SND_AUDIOPROFILE_WMA9_LOSSLESS
:
974 case SND_AUDIOPROFILE_WMA10_LOSSLESS
:
975 open
->dec_fmt_id
= ASM_MEDIA_FMT_WMA_V10
;
978 dev_err(ac
->dev
, "Invalid codec profile 0x%x\n",
984 case SND_AUDIOCODEC_ALAC
:
985 open
->dec_fmt_id
= ASM_MEDIA_FMT_ALAC
;
987 case SND_AUDIOCODEC_APE
:
988 open
->dec_fmt_id
= ASM_MEDIA_FMT_APE
;
991 dev_err(ac
->dev
, "Invalid format 0x%x\n", format
);
996 rc
= q6asm_ac_send_cmd_sync(ac
, pkt
);
1000 ac
->io_mode
|= ASM_TUN_WRITE_IO_MODE
;
1006 EXPORT_SYMBOL_GPL(q6asm_open_write
);
1008 static int __q6asm_run(struct audio_client
*ac
, uint32_t stream_id
,
1009 uint32_t flags
, uint32_t msw_ts
, uint32_t lsw_ts
,
1012 struct asm_session_cmd_run_v2
*run
;
1013 struct apr_pkt
*pkt
;
1017 pkt_size
= APR_HDR_SIZE
+ sizeof(*run
);
1018 p
= kzalloc(pkt_size
, GFP_ATOMIC
);
1023 run
= p
+ APR_HDR_SIZE
;
1025 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
1027 pkt
->hdr
.opcode
= ASM_SESSION_CMD_RUN_V2
;
1029 run
->time_lsw
= lsw_ts
;
1030 run
->time_msw
= msw_ts
;
1032 rc
= q6asm_ac_send_cmd_sync(ac
, pkt
);
1034 rc
= apr_send_pkt(ac
->adev
, pkt
);
1044 * q6asm_run() - start the audio client
1046 * @ac: audio client pointer
1047 * @stream_id: stream id of q6asm session
1048 * @flags: flags associated with write
1049 * @msw_ts: timestamp msw
1050 * @lsw_ts: timestamp lsw
1052 * Return: Will be an negative value on error or zero on success
1054 int q6asm_run(struct audio_client
*ac
, uint32_t stream_id
, uint32_t flags
,
1055 uint32_t msw_ts
, uint32_t lsw_ts
)
1057 return __q6asm_run(ac
, stream_id
, flags
, msw_ts
, lsw_ts
, true);
1059 EXPORT_SYMBOL_GPL(q6asm_run
);
1062 * q6asm_run_nowait() - start the audio client withou blocking
1064 * @ac: audio client pointer
1065 * @stream_id: stream id
1066 * @flags: flags associated with write
1067 * @msw_ts: timestamp msw
1068 * @lsw_ts: timestamp lsw
1070 * Return: Will be an negative value on error or zero on success
1072 int q6asm_run_nowait(struct audio_client
*ac
, uint32_t stream_id
,
1073 uint32_t flags
, uint32_t msw_ts
, uint32_t lsw_ts
)
1075 return __q6asm_run(ac
, stream_id
, flags
, msw_ts
, lsw_ts
, false);
1077 EXPORT_SYMBOL_GPL(q6asm_run_nowait
);
1080 * q6asm_media_format_block_multi_ch_pcm() - setup pcm configuration
1082 * @ac: audio client pointer
1083 * @stream_id: stream id
1084 * @rate: audio sample rate
1085 * @channels: number of audio channels.
1086 * @channel_map: channel map pointer
1087 * @bits_per_sample: bits per sample
1089 * Return: Will be an negative value on error or zero on success
1091 int q6asm_media_format_block_multi_ch_pcm(struct audio_client
*ac
,
1093 uint32_t rate
, uint32_t channels
,
1094 u8 channel_map
[PCM_MAX_NUM_CHANNEL
],
1095 uint16_t bits_per_sample
)
1097 struct asm_multi_channel_pcm_fmt_blk_v2
*fmt
;
1098 struct apr_pkt
*pkt
;
1099 u8
*channel_mapping
;
1103 pkt_size
= APR_HDR_SIZE
+ sizeof(*fmt
);
1104 p
= kzalloc(pkt_size
, GFP_KERNEL
);
1109 fmt
= p
+ APR_HDR_SIZE
;
1111 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
1113 pkt
->hdr
.opcode
= ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2
;
1114 fmt
->fmt_blk
.fmt_blk_size
= sizeof(*fmt
) - sizeof(fmt
->fmt_blk
);
1115 fmt
->num_channels
= channels
;
1116 fmt
->bits_per_sample
= bits_per_sample
;
1117 fmt
->sample_rate
= rate
;
1120 channel_mapping
= fmt
->channel_mapping
;
1123 memcpy(channel_mapping
, channel_map
, PCM_MAX_NUM_CHANNEL
);
1125 if (q6dsp_map_channels(channel_mapping
, channels
)) {
1126 dev_err(ac
->dev
, " map channels failed %d\n", channels
);
1132 rc
= q6asm_ac_send_cmd_sync(ac
, pkt
);
1138 EXPORT_SYMBOL_GPL(q6asm_media_format_block_multi_ch_pcm
);
1140 int q6asm_stream_media_format_block_flac(struct audio_client
*ac
,
1142 struct q6asm_flac_cfg
*cfg
)
1144 struct asm_flac_fmt_blk_v2
*fmt
;
1145 struct apr_pkt
*pkt
;
1149 pkt_size
= APR_HDR_SIZE
+ sizeof(*fmt
);
1150 p
= kzalloc(pkt_size
, GFP_KERNEL
);
1155 fmt
= p
+ APR_HDR_SIZE
;
1157 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
1159 pkt
->hdr
.opcode
= ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2
;
1160 fmt
->fmt_blk
.fmt_blk_size
= sizeof(*fmt
) - sizeof(fmt
->fmt_blk
);
1161 fmt
->is_stream_info_present
= cfg
->stream_info_present
;
1162 fmt
->num_channels
= cfg
->ch_cfg
;
1163 fmt
->min_blk_size
= cfg
->min_blk_size
;
1164 fmt
->max_blk_size
= cfg
->max_blk_size
;
1165 fmt
->sample_rate
= cfg
->sample_rate
;
1166 fmt
->min_frame_size
= cfg
->min_frame_size
;
1167 fmt
->max_frame_size
= cfg
->max_frame_size
;
1168 fmt
->sample_size
= cfg
->sample_size
;
1170 rc
= q6asm_ac_send_cmd_sync(ac
, pkt
);
1175 EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_flac
);
1177 int q6asm_stream_media_format_block_wma_v9(struct audio_client
*ac
,
1179 struct q6asm_wma_cfg
*cfg
)
1181 struct asm_wmastdv9_fmt_blk_v2
*fmt
;
1182 struct apr_pkt
*pkt
;
1186 pkt_size
= APR_HDR_SIZE
+ sizeof(*fmt
);
1187 p
= kzalloc(pkt_size
, GFP_KERNEL
);
1192 fmt
= p
+ APR_HDR_SIZE
;
1194 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
1196 pkt
->hdr
.opcode
= ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2
;
1197 fmt
->fmt_blk
.fmt_blk_size
= sizeof(*fmt
) - sizeof(fmt
->fmt_blk
);
1198 fmt
->fmtag
= cfg
->fmtag
;
1199 fmt
->num_channels
= cfg
->num_channels
;
1200 fmt
->sample_rate
= cfg
->sample_rate
;
1201 fmt
->bytes_per_sec
= cfg
->bytes_per_sec
;
1202 fmt
->blk_align
= cfg
->block_align
;
1203 fmt
->bits_per_sample
= cfg
->bits_per_sample
;
1204 fmt
->channel_mask
= cfg
->channel_mask
;
1205 fmt
->enc_options
= cfg
->enc_options
;
1208 rc
= q6asm_ac_send_cmd_sync(ac
, pkt
);
1213 EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_wma_v9
);
1215 int q6asm_stream_media_format_block_wma_v10(struct audio_client
*ac
,
1217 struct q6asm_wma_cfg
*cfg
)
1219 struct asm_wmaprov10_fmt_blk_v2
*fmt
;
1220 struct apr_pkt
*pkt
;
1224 pkt_size
= APR_HDR_SIZE
+ sizeof(*fmt
);
1225 p
= kzalloc(pkt_size
, GFP_KERNEL
);
1230 fmt
= p
+ APR_HDR_SIZE
;
1232 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
1234 pkt
->hdr
.opcode
= ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2
;
1235 fmt
->fmt_blk
.fmt_blk_size
= sizeof(*fmt
) - sizeof(fmt
->fmt_blk
);
1236 fmt
->fmtag
= cfg
->fmtag
;
1237 fmt
->num_channels
= cfg
->num_channels
;
1238 fmt
->sample_rate
= cfg
->sample_rate
;
1239 fmt
->bytes_per_sec
= cfg
->bytes_per_sec
;
1240 fmt
->blk_align
= cfg
->block_align
;
1241 fmt
->bits_per_sample
= cfg
->bits_per_sample
;
1242 fmt
->channel_mask
= cfg
->channel_mask
;
1243 fmt
->enc_options
= cfg
->enc_options
;
1244 fmt
->advanced_enc_options1
= cfg
->adv_enc_options
;
1245 fmt
->advanced_enc_options2
= cfg
->adv_enc_options2
;
1247 rc
= q6asm_ac_send_cmd_sync(ac
, pkt
);
1252 EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_wma_v10
);
1254 int q6asm_stream_media_format_block_alac(struct audio_client
*ac
,
1256 struct q6asm_alac_cfg
*cfg
)
1258 struct asm_alac_fmt_blk_v2
*fmt
;
1259 struct apr_pkt
*pkt
;
1263 pkt_size
= APR_HDR_SIZE
+ sizeof(*fmt
);
1264 p
= kzalloc(pkt_size
, GFP_KERNEL
);
1269 fmt
= p
+ APR_HDR_SIZE
;
1271 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
1273 pkt
->hdr
.opcode
= ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2
;
1274 fmt
->fmt_blk
.fmt_blk_size
= sizeof(*fmt
) - sizeof(fmt
->fmt_blk
);
1276 fmt
->frame_length
= cfg
->frame_length
;
1277 fmt
->compatible_version
= cfg
->compatible_version
;
1278 fmt
->bit_depth
= cfg
->bit_depth
;
1279 fmt
->num_channels
= cfg
->num_channels
;
1280 fmt
->max_run
= cfg
->max_run
;
1281 fmt
->max_frame_bytes
= cfg
->max_frame_bytes
;
1282 fmt
->avg_bit_rate
= cfg
->avg_bit_rate
;
1283 fmt
->sample_rate
= cfg
->sample_rate
;
1284 fmt
->channel_layout_tag
= cfg
->channel_layout_tag
;
1289 rc
= q6asm_ac_send_cmd_sync(ac
, pkt
);
1294 EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_alac
);
1296 int q6asm_stream_media_format_block_ape(struct audio_client
*ac
,
1298 struct q6asm_ape_cfg
*cfg
)
1300 struct asm_ape_fmt_blk_v2
*fmt
;
1301 struct apr_pkt
*pkt
;
1305 pkt_size
= APR_HDR_SIZE
+ sizeof(*fmt
);
1306 p
= kzalloc(pkt_size
, GFP_KERNEL
);
1311 fmt
= p
+ APR_HDR_SIZE
;
1313 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
1315 pkt
->hdr
.opcode
= ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2
;
1316 fmt
->fmt_blk
.fmt_blk_size
= sizeof(*fmt
) - sizeof(fmt
->fmt_blk
);
1318 fmt
->compatible_version
= cfg
->compatible_version
;
1319 fmt
->compression_level
= cfg
->compression_level
;
1320 fmt
->format_flags
= cfg
->format_flags
;
1321 fmt
->blocks_per_frame
= cfg
->blocks_per_frame
;
1322 fmt
->final_frame_blocks
= cfg
->final_frame_blocks
;
1323 fmt
->total_frames
= cfg
->total_frames
;
1324 fmt
->bits_per_sample
= cfg
->bits_per_sample
;
1325 fmt
->num_channels
= cfg
->num_channels
;
1326 fmt
->sample_rate
= cfg
->sample_rate
;
1327 fmt
->seek_table_present
= cfg
->seek_table_present
;
1329 rc
= q6asm_ac_send_cmd_sync(ac
, pkt
);
1334 EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_ape
);
1336 static int q6asm_stream_remove_silence(struct audio_client
*ac
, uint32_t stream_id
,
1338 uint32_t num_samples
)
1341 struct apr_pkt
*pkt
;
1345 pkt_size
= APR_HDR_SIZE
+ sizeof(uint32_t);
1346 p
= kzalloc(pkt_size
, GFP_ATOMIC
);
1351 samples
= p
+ APR_HDR_SIZE
;
1353 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
1355 pkt
->hdr
.opcode
= cmd
;
1356 *samples
= num_samples
;
1357 rc
= apr_send_pkt(ac
->adev
, pkt
);
1366 int q6asm_stream_remove_initial_silence(struct audio_client
*ac
,
1368 uint32_t initial_samples
)
1370 return q6asm_stream_remove_silence(ac
, stream_id
,
1371 ASM_DATA_CMD_REMOVE_INITIAL_SILENCE
,
1374 EXPORT_SYMBOL_GPL(q6asm_stream_remove_initial_silence
);
1376 int q6asm_stream_remove_trailing_silence(struct audio_client
*ac
, uint32_t stream_id
,
1377 uint32_t trailing_samples
)
1379 return q6asm_stream_remove_silence(ac
, stream_id
,
1380 ASM_DATA_CMD_REMOVE_TRAILING_SILENCE
,
1383 EXPORT_SYMBOL_GPL(q6asm_stream_remove_trailing_silence
);
1386 * q6asm_enc_cfg_blk_pcm_format_support() - setup pcm configuration for capture
1388 * @ac: audio client pointer
1389 * @stream_id: stream id
1390 * @rate: audio sample rate
1391 * @channels: number of audio channels.
1392 * @bits_per_sample: bits per sample
1394 * Return: Will be an negative value on error or zero on success
1396 int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client
*ac
,
1397 uint32_t stream_id
, uint32_t rate
,
1399 uint16_t bits_per_sample
)
1401 struct asm_multi_channel_pcm_enc_cfg_v2
*enc_cfg
;
1402 struct apr_pkt
*pkt
;
1403 u8
*channel_mapping
;
1404 u32 frames_per_buf
= 0;
1408 pkt_size
= APR_HDR_SIZE
+ sizeof(*enc_cfg
);
1409 p
= kzalloc(pkt_size
, GFP_KERNEL
);
1414 enc_cfg
= p
+ APR_HDR_SIZE
;
1415 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
1417 pkt
->hdr
.opcode
= ASM_STREAM_CMD_SET_ENCDEC_PARAM
;
1418 enc_cfg
->encdec
.param_id
= ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2
;
1419 enc_cfg
->encdec
.param_size
= sizeof(*enc_cfg
) - sizeof(enc_cfg
->encdec
);
1420 enc_cfg
->encblk
.frames_per_buf
= frames_per_buf
;
1421 enc_cfg
->encblk
.enc_cfg_blk_size
= enc_cfg
->encdec
.param_size
-
1422 sizeof(struct asm_enc_cfg_blk_param_v2
);
1424 enc_cfg
->num_channels
= channels
;
1425 enc_cfg
->bits_per_sample
= bits_per_sample
;
1426 enc_cfg
->sample_rate
= rate
;
1427 enc_cfg
->is_signed
= 1;
1428 channel_mapping
= enc_cfg
->channel_mapping
;
1430 if (q6dsp_map_channels(channel_mapping
, channels
)) {
1435 rc
= q6asm_ac_send_cmd_sync(ac
, pkt
);
1440 EXPORT_SYMBOL_GPL(q6asm_enc_cfg_blk_pcm_format_support
);
1444 * q6asm_read() - read data of period size from audio client
1446 * @ac: audio client pointer
1447 * @stream_id: stream id
1449 * Return: Will be an negative value on error or zero on success
1451 int q6asm_read(struct audio_client
*ac
, uint32_t stream_id
)
1453 struct asm_data_cmd_read_v2
*read
;
1454 struct audio_port_data
*port
;
1455 struct audio_buffer
*ab
;
1456 struct apr_pkt
*pkt
;
1457 unsigned long flags
;
1462 pkt_size
= APR_HDR_SIZE
+ sizeof(*read
);
1463 p
= kzalloc(pkt_size
, GFP_ATOMIC
);
1468 read
= p
+ APR_HDR_SIZE
;
1470 spin_lock_irqsave(&ac
->lock
, flags
);
1471 port
= &ac
->port
[SNDRV_PCM_STREAM_CAPTURE
];
1472 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, false, stream_id
);
1473 ab
= &port
->buf
[port
->dsp_buf
];
1474 pkt
->hdr
.opcode
= ASM_DATA_CMD_READ_V2
;
1475 read
->buf_addr_lsw
= lower_32_bits(ab
->phys
);
1476 read
->buf_addr_msw
= upper_32_bits(ab
->phys
);
1477 read
->mem_map_handle
= port
->mem_map_handle
;
1479 read
->buf_size
= ab
->size
;
1480 read
->seq_id
= port
->dsp_buf
;
1481 pkt
->hdr
.token
= port
->dsp_buf
;
1485 if (port
->dsp_buf
>= port
->num_periods
)
1488 spin_unlock_irqrestore(&ac
->lock
, flags
);
1489 rc
= apr_send_pkt(ac
->adev
, pkt
);
1493 pr_err("read op[0x%x]rc[%d]\n", pkt
->hdr
.opcode
, rc
);
1498 EXPORT_SYMBOL_GPL(q6asm_read
);
1500 static int __q6asm_open_read(struct audio_client
*ac
, uint32_t stream_id
,
1501 uint32_t format
, uint16_t bits_per_sample
)
1503 struct asm_stream_cmd_open_read_v3
*open
;
1504 struct apr_pkt
*pkt
;
1508 pkt_size
= APR_HDR_SIZE
+ sizeof(*open
);
1509 p
= kzalloc(pkt_size
, GFP_KERNEL
);
1514 open
= p
+ APR_HDR_SIZE
;
1516 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, true, stream_id
);
1517 pkt
->hdr
.opcode
= ASM_STREAM_CMD_OPEN_READ_V3
;
1518 /* Stream prio : High, provide meta info with encoded frames */
1519 open
->src_endpointype
= ASM_END_POINT_DEVICE_MATRIX
;
1521 open
->preprocopo_id
= ASM_STREAM_POSTPROC_TOPO_ID_NONE
;
1522 open
->bits_per_sample
= bits_per_sample
;
1523 open
->mode_flags
= 0x0;
1525 open
->mode_flags
|= ASM_LEGACY_STREAM_SESSION
<<
1526 ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ
;
1529 case FORMAT_LINEAR_PCM
:
1530 open
->mode_flags
|= 0x00;
1531 open
->enc_cfg_id
= ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2
;
1534 pr_err("Invalid format[%d]\n", format
);
1537 rc
= q6asm_ac_send_cmd_sync(ac
, pkt
);
1544 * q6asm_open_read() - Open audio client for reading
1546 * @ac: audio client pointer
1547 * @stream_id: stream id
1548 * @format: audio sample format
1549 * @bits_per_sample: bits per sample
1551 * Return: Will be an negative value on error or zero on success
1553 int q6asm_open_read(struct audio_client
*ac
, uint32_t stream_id
,
1554 uint32_t format
, uint16_t bits_per_sample
)
1556 return __q6asm_open_read(ac
, stream_id
, format
, bits_per_sample
);
1558 EXPORT_SYMBOL_GPL(q6asm_open_read
);
1561 * q6asm_write_async() - non blocking write
1563 * @ac: audio client pointer
1564 * @stream_id: stream id
1565 * @len: length in bytes
1566 * @msw_ts: timestamp msw
1567 * @lsw_ts: timestamp lsw
1568 * @wflags: flags associated with write
1570 * Return: Will be an negative value on error or zero on success
1572 int q6asm_write_async(struct audio_client
*ac
, uint32_t stream_id
, uint32_t len
,
1573 uint32_t msw_ts
, uint32_t lsw_ts
, uint32_t wflags
)
1575 struct asm_data_cmd_write_v2
*write
;
1576 struct audio_port_data
*port
;
1577 struct audio_buffer
*ab
;
1578 unsigned long flags
;
1579 struct apr_pkt
*pkt
;
1584 pkt_size
= APR_HDR_SIZE
+ sizeof(*write
);
1585 p
= kzalloc(pkt_size
, GFP_ATOMIC
);
1590 write
= p
+ APR_HDR_SIZE
;
1592 spin_lock_irqsave(&ac
->lock
, flags
);
1593 port
= &ac
->port
[SNDRV_PCM_STREAM_PLAYBACK
];
1594 q6asm_add_hdr(ac
, &pkt
->hdr
, pkt_size
, false, stream_id
);
1596 ab
= &port
->buf
[port
->dsp_buf
];
1597 pkt
->hdr
.token
= port
->dsp_buf
| (len
<< ASM_WRITE_TOKEN_LEN_SHIFT
);
1598 pkt
->hdr
.opcode
= ASM_DATA_CMD_WRITE_V2
;
1599 write
->buf_addr_lsw
= lower_32_bits(ab
->phys
);
1600 write
->buf_addr_msw
= upper_32_bits(ab
->phys
);
1601 write
->buf_size
= len
;
1602 write
->seq_id
= port
->dsp_buf
;
1603 write
->timestamp_lsw
= lsw_ts
;
1604 write
->timestamp_msw
= msw_ts
;
1605 write
->mem_map_handle
=
1606 ac
->port
[SNDRV_PCM_STREAM_PLAYBACK
].mem_map_handle
;
1608 write
->flags
= wflags
;
1612 if (port
->dsp_buf
>= port
->num_periods
)
1615 spin_unlock_irqrestore(&ac
->lock
, flags
);
1616 rc
= apr_send_pkt(ac
->adev
, pkt
);
1623 EXPORT_SYMBOL_GPL(q6asm_write_async
);
1625 static void q6asm_reset_buf_state(struct audio_client
*ac
)
1627 struct audio_port_data
*port
= NULL
;
1628 unsigned long flags
;
1630 spin_lock_irqsave(&ac
->lock
, flags
);
1631 port
= &ac
->port
[SNDRV_PCM_STREAM_PLAYBACK
];
1633 port
= &ac
->port
[SNDRV_PCM_STREAM_CAPTURE
];
1635 spin_unlock_irqrestore(&ac
->lock
, flags
);
1638 static int __q6asm_cmd(struct audio_client
*ac
, uint32_t stream_id
, int cmd
,
1644 q6asm_add_hdr(ac
, &pkt
.hdr
, APR_HDR_SIZE
, true, stream_id
);
1648 pkt
.hdr
.opcode
= ASM_SESSION_CMD_PAUSE
;
1651 pkt
.hdr
.opcode
= ASM_SESSION_CMD_SUSPEND
;
1654 pkt
.hdr
.opcode
= ASM_STREAM_CMD_FLUSH
;
1657 pkt
.hdr
.opcode
= ASM_STREAM_CMD_FLUSH_READBUFS
;
1660 pkt
.hdr
.opcode
= ASM_DATA_CMD_EOS
;
1663 pkt
.hdr
.opcode
= ASM_STREAM_CMD_CLOSE
;
1670 rc
= q6asm_ac_send_cmd_sync(ac
, &pkt
);
1672 return apr_send_pkt(ac
->adev
, &pkt
);
1677 if (cmd
== CMD_FLUSH
)
1678 q6asm_reset_buf_state(ac
);
1684 * q6asm_cmd() - run cmd on audio client
1686 * @ac: audio client pointer
1687 * @stream_id: stream id
1688 * @cmd: command to run on audio client.
1690 * Return: Will be an negative value on error or zero on success
1692 int q6asm_cmd(struct audio_client
*ac
, uint32_t stream_id
, int cmd
)
1694 return __q6asm_cmd(ac
, stream_id
, cmd
, true);
1696 EXPORT_SYMBOL_GPL(q6asm_cmd
);
1699 * q6asm_cmd_nowait() - non blocking, run cmd on audio client
1701 * @ac: audio client pointer
1702 * @stream_id: stream id
1703 * @cmd: command to run on audio client.
1705 * Return: Will be an negative value on error or zero on success
1707 int q6asm_cmd_nowait(struct audio_client
*ac
, uint32_t stream_id
, int cmd
)
1709 return __q6asm_cmd(ac
, stream_id
, cmd
, false);
1711 EXPORT_SYMBOL_GPL(q6asm_cmd_nowait
);
1713 static int q6asm_probe(struct apr_device
*adev
)
1715 struct device
*dev
= &adev
->dev
;
1716 struct q6asm
*q6asm
;
1718 q6asm
= devm_kzalloc(dev
, sizeof(*q6asm
), GFP_KERNEL
);
1722 q6core_get_svc_api_info(adev
->svc_id
, &q6asm
->ainfo
);
1726 init_waitqueue_head(&q6asm
->mem_wait
);
1727 spin_lock_init(&q6asm
->slock
);
1728 dev_set_drvdata(dev
, q6asm
);
1730 return devm_of_platform_populate(dev
);
1734 static const struct of_device_id q6asm_device_id
[] = {
1735 { .compatible
= "qcom,q6asm" },
1738 MODULE_DEVICE_TABLE(of
, q6asm_device_id
);
1741 static struct apr_driver qcom_q6asm_driver
= {
1742 .probe
= q6asm_probe
,
1743 .callback
= q6asm_srvc_callback
,
1745 .name
= "qcom-q6asm",
1746 .of_match_table
= of_match_ptr(q6asm_device_id
),
1750 module_apr_driver(qcom_q6asm_driver
);
1751 MODULE_DESCRIPTION("Q6 Audio Stream Manager driver");
1752 MODULE_LICENSE("GPL v2");