hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/sound/soc/qcom/qdsp6/q6asm.c
....@@ -11,8 +11,8 @@
1111 #include <linux/spinlock.h>
1212 #include <linux/kref.h>
1313 #include <linux/of.h>
14
-#include <linux/of_platform.h>
1514 #include <uapi/sound/asound.h>
15
+#include <uapi/sound/compress_params.h>
1616 #include <linux/delay.h>
1717 #include <linux/slab.h>
1818 #include <linux/mm.h>
....@@ -38,6 +38,10 @@
3838 #define ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2 0x00010DA3
3939 #define ASM_SESSION_CMD_RUN_V2 0x00010DAA
4040 #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
4145 #define ASM_DATA_CMD_WRITE_V2 0x00010DAB
4246 #define ASM_DATA_CMD_READ_V2 0x00010DAC
4347 #define ASM_SESSION_CMD_SUSPEND 0x00010DEC
....@@ -45,6 +49,10 @@
4549 #define ASM_STREAM_CMD_OPEN_READ_V3 0x00010DB4
4650 #define ASM_DATA_EVENT_READ_DONE_V2 0x00010D9A
4751 #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
4856
4957
5058 #define ASM_LEGACY_STREAM_SESSION 0
....@@ -87,6 +95,77 @@
8795 u16 is_signed;
8896 u16 reserved;
8997 u8 channel_mapping[PCM_MAX_NUM_CHANNEL];
98
+} __packed;
99
+
100
+struct asm_flac_fmt_blk_v2 {
101
+ struct asm_data_cmd_media_fmt_update_v2 fmt_blk;
102
+ u16 is_stream_info_present;
103
+ u16 num_channels;
104
+ u16 min_blk_size;
105
+ u16 max_blk_size;
106
+ u16 md5_sum[8];
107
+ u32 sample_rate;
108
+ u32 min_frame_size;
109
+ u32 max_frame_size;
110
+ u16 sample_size;
111
+ u16 reserved;
112
+} __packed;
113
+
114
+struct asm_wmastdv9_fmt_blk_v2 {
115
+ struct asm_data_cmd_media_fmt_update_v2 fmt_blk;
116
+ u16 fmtag;
117
+ u16 num_channels;
118
+ u32 sample_rate;
119
+ u32 bytes_per_sec;
120
+ u16 blk_align;
121
+ u16 bits_per_sample;
122
+ u32 channel_mask;
123
+ u16 enc_options;
124
+ u16 reserved;
125
+} __packed;
126
+
127
+struct asm_wmaprov10_fmt_blk_v2 {
128
+ struct asm_data_cmd_media_fmt_update_v2 fmt_blk;
129
+ u16 fmtag;
130
+ u16 num_channels;
131
+ u32 sample_rate;
132
+ u32 bytes_per_sec;
133
+ u16 blk_align;
134
+ u16 bits_per_sample;
135
+ u32 channel_mask;
136
+ u16 enc_options;
137
+ u16 advanced_enc_options1;
138
+ u32 advanced_enc_options2;
139
+} __packed;
140
+
141
+struct asm_alac_fmt_blk_v2 {
142
+ struct asm_data_cmd_media_fmt_update_v2 fmt_blk;
143
+ u32 frame_length;
144
+ u8 compatible_version;
145
+ u8 bit_depth;
146
+ u8 pb;
147
+ u8 mb;
148
+ u8 kb;
149
+ u8 num_channels;
150
+ u16 max_run;
151
+ u32 max_frame_bytes;
152
+ u32 avg_bit_rate;
153
+ u32 sample_rate;
154
+ u32 channel_layout_tag;
155
+} __packed;
156
+
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;
161
+ u32 format_flags;
162
+ u32 blocks_per_frame;
163
+ u32 final_frame_blocks;
164
+ u32 total_frames;
165
+ u16 bits_per_sample;
166
+ u16 num_channels;
167
+ u32 sample_rate;
168
+ u32 seek_table_present;
90169 } __packed;
91170
92171 struct asm_stream_cmd_set_encdec_param {
....@@ -193,7 +272,6 @@
193272 wait_queue_head_t cmd_wait;
194273 struct aprv2_ibasic_rsp_result_t result;
195274 int perf_mode;
196
- int stream_id;
197275 struct q6asm *q6asm;
198276 struct device *dev;
199277 };
....@@ -234,7 +312,7 @@
234312 5 * HZ);
235313
236314 if (!rc) {
237
- dev_err(a->dev, "CMD timeout\n");
315
+ dev_err(a->dev, "CMD %x timeout\n", hdr->opcode);
238316 rc = -ETIMEDOUT;
239317 } else if (ac->result.status > 0) {
240318 dev_err(a->dev, "DSP returned error[%x]\n",
....@@ -563,6 +641,8 @@
563641 case ASM_STREAM_CMD_OPEN_READWRITE_V2:
564642 case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
565643 case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
644
+ case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:
645
+ case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
566646 if (result->status != 0) {
567647 dev_err(ac->dev,
568648 "cmd = 0x%x returned error = 0x%x\n",
....@@ -594,6 +674,7 @@
594674 if (ac->io_mode & ASM_SYNC_IO_MODE) {
595675 phys_addr_t phys;
596676 unsigned long flags;
677
+ int token = hdr->token & ASM_WRITE_TOKEN_MASK;
597678
598679 spin_lock_irqsave(&ac->lock, flags);
599680
....@@ -605,12 +686,12 @@
605686 goto done;
606687 }
607688
608
- phys = port->buf[hdr->token].phys;
689
+ phys = port->buf[token].phys;
609690
610691 if (lower_32_bits(phys) != result->opcode ||
611692 upper_32_bits(phys) != result->status) {
612693 dev_err(ac->dev, "Expected addr %pa\n",
613
- &port->buf[hdr->token].phys);
694
+ &port->buf[token].phys);
614695 spin_unlock_irqrestore(&ac->lock, flags);
615696 ret = -EINVAL;
616697 goto done;
....@@ -751,21 +832,21 @@
751832 * @dev: Pointer to asm child device.
752833 * @cb: event callback.
753834 * @priv: private data associated with this client.
754
- * @stream_id: stream id
835
+ * @session_id: session id
755836 * @perf_mode: performace mode for this client
756837 *
757838 * Return: Will be an error pointer on error or a valid audio client
758839 * on success.
759840 */
760841 struct audio_client *q6asm_audio_client_alloc(struct device *dev, q6asm_cb cb,
761
- void *priv, int stream_id,
842
+ void *priv, int session_id,
762843 int perf_mode)
763844 {
764845 struct q6asm *a = dev_get_drvdata(dev->parent);
765846 struct audio_client *ac;
766847 unsigned long flags;
767848
768
- ac = q6asm_get_audio_client(a, stream_id + 1);
849
+ ac = q6asm_get_audio_client(a, session_id + 1);
769850 if (ac) {
770851 dev_err(dev, "Audio Client already active\n");
771852 return ac;
....@@ -776,17 +857,15 @@
776857 return ERR_PTR(-ENOMEM);
777858
778859 spin_lock_irqsave(&a->slock, flags);
779
- a->session[stream_id + 1] = ac;
860
+ a->session[session_id + 1] = ac;
780861 spin_unlock_irqrestore(&a->slock, flags);
781
- ac->session = stream_id + 1;
862
+ ac->session = session_id + 1;
782863 ac->cb = cb;
783864 ac->dev = dev;
784865 ac->q6asm = a;
785866 ac->priv = priv;
786867 ac->io_mode = ASM_SYNC_IO_MODE;
787868 ac->perf_mode = perf_mode;
788
- /* DSP expects stream id from 1 */
789
- ac->stream_id = 1;
790869 ac->adev = a->adev;
791870 kref_init(&ac->refcount);
792871
....@@ -814,7 +893,7 @@
814893 rc = wait_event_timeout(ac->cmd_wait,
815894 (ac->result.opcode == hdr->opcode), 5 * HZ);
816895 if (!rc) {
817
- dev_err(ac->dev, "CMD timeout\n");
896
+ dev_err(ac->dev, "CMD %x timeout\n", hdr->opcode);
818897 rc = -ETIMEDOUT;
819898 goto err;
820899 }
....@@ -835,15 +914,18 @@
835914
836915 /**
837916 * q6asm_open_write() - Open audio client for writing
838
- *
839917 * @ac: audio client pointer
918
+ * @stream_id: stream id of q6asm session
840919 * @format: audio sample format
920
+ * @codec_profile: compressed format profile
841921 * @bits_per_sample: bits per sample
922
+ * @is_gapless: flag to indicate if this is a gapless stream
842923 *
843924 * Return: Will be an negative value on error or zero on success
844925 */
845
-int q6asm_open_write(struct audio_client *ac, uint32_t format,
846
- uint16_t bits_per_sample)
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)
847929 {
848930 struct asm_stream_cmd_open_write_v3 *open;
849931 struct apr_pkt *pkt;
....@@ -858,11 +940,13 @@
858940
859941 pkt = p;
860942 open = p + APR_HDR_SIZE;
861
- q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id);
943
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
862944
863945 pkt->hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3;
864946 open->mode_flags = 0x00;
865947 open->mode_flags |= ASM_LEGACY_STREAM_SESSION;
948
+ if (is_gapless)
949
+ open->mode_flags |= BIT(ASM_SHIFT_GAPLESS_MODE_FLAG);
866950
867951 /* source endpoint : matrix */
868952 open->sink_endpointype = ASM_END_POINT_DEVICE_MATRIX;
....@@ -870,8 +954,38 @@
870954 open->postprocopo_id = ASM_NULL_POPP_TOPOLOGY;
871955
872956 switch (format) {
957
+ case SND_AUDIOCODEC_MP3:
958
+ open->dec_fmt_id = ASM_MEDIA_FMT_MP3;
959
+ break;
873960 case FORMAT_LINEAR_PCM:
874961 open->dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
962
+ break;
963
+ case SND_AUDIOCODEC_FLAC:
964
+ open->dec_fmt_id = ASM_MEDIA_FMT_FLAC;
965
+ break;
966
+ case SND_AUDIOCODEC_WMA:
967
+ switch (codec_profile) {
968
+ case SND_AUDIOPROFILE_WMA9:
969
+ open->dec_fmt_id = ASM_MEDIA_FMT_WMA_V9;
970
+ break;
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;
976
+ break;
977
+ default:
978
+ dev_err(ac->dev, "Invalid codec profile 0x%x\n",
979
+ codec_profile);
980
+ rc = -EINVAL;
981
+ goto err;
982
+ }
983
+ break;
984
+ case SND_AUDIOCODEC_ALAC:
985
+ open->dec_fmt_id = ASM_MEDIA_FMT_ALAC;
986
+ break;
987
+ case SND_AUDIOCODEC_APE:
988
+ open->dec_fmt_id = ASM_MEDIA_FMT_APE;
875989 break;
876990 default:
877991 dev_err(ac->dev, "Invalid format 0x%x\n", format);
....@@ -891,8 +1005,9 @@
8911005 }
8921006 EXPORT_SYMBOL_GPL(q6asm_open_write);
8931007
894
-static int __q6asm_run(struct audio_client *ac, uint32_t flags,
895
- uint32_t msw_ts, uint32_t lsw_ts, bool wait)
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,
1010
+ bool wait)
8961011 {
8971012 struct asm_session_cmd_run_v2 *run;
8981013 struct apr_pkt *pkt;
....@@ -907,7 +1022,7 @@
9071022 pkt = p;
9081023 run = p + APR_HDR_SIZE;
9091024
910
- q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id);
1025
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
9111026
9121027 pkt->hdr.opcode = ASM_SESSION_CMD_RUN_V2;
9131028 run->flags = flags;
....@@ -929,16 +1044,17 @@
9291044 * q6asm_run() - start the audio client
9301045 *
9311046 * @ac: audio client pointer
1047
+ * @stream_id: stream id of q6asm session
9321048 * @flags: flags associated with write
9331049 * @msw_ts: timestamp msw
9341050 * @lsw_ts: timestamp lsw
9351051 *
9361052 * Return: Will be an negative value on error or zero on success
9371053 */
938
-int q6asm_run(struct audio_client *ac, uint32_t flags,
1054
+int q6asm_run(struct audio_client *ac, uint32_t stream_id, uint32_t flags,
9391055 uint32_t msw_ts, uint32_t lsw_ts)
9401056 {
941
- return __q6asm_run(ac, flags, msw_ts, lsw_ts, true);
1057
+ return __q6asm_run(ac, stream_id, flags, msw_ts, lsw_ts, true);
9421058 }
9431059 EXPORT_SYMBOL_GPL(q6asm_run);
9441060
....@@ -946,16 +1062,17 @@
9461062 * q6asm_run_nowait() - start the audio client withou blocking
9471063 *
9481064 * @ac: audio client pointer
1065
+ * @stream_id: stream id
9491066 * @flags: flags associated with write
9501067 * @msw_ts: timestamp msw
9511068 * @lsw_ts: timestamp lsw
9521069 *
9531070 * Return: Will be an negative value on error or zero on success
9541071 */
955
-int q6asm_run_nowait(struct audio_client *ac, uint32_t flags,
956
- uint32_t msw_ts, uint32_t lsw_ts)
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)
9571074 {
958
- return __q6asm_run(ac, flags, msw_ts, lsw_ts, false);
1075
+ return __q6asm_run(ac, stream_id, flags, msw_ts, lsw_ts, false);
9591076 }
9601077 EXPORT_SYMBOL_GPL(q6asm_run_nowait);
9611078
....@@ -963,6 +1080,7 @@
9631080 * q6asm_media_format_block_multi_ch_pcm() - setup pcm configuration
9641081 *
9651082 * @ac: audio client pointer
1083
+ * @stream_id: stream id
9661084 * @rate: audio sample rate
9671085 * @channels: number of audio channels.
9681086 * @channel_map: channel map pointer
....@@ -971,6 +1089,7 @@
9711089 * Return: Will be an negative value on error or zero on success
9721090 */
9731091 int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
1092
+ uint32_t stream_id,
9741093 uint32_t rate, uint32_t channels,
9751094 u8 channel_map[PCM_MAX_NUM_CHANNEL],
9761095 uint16_t bits_per_sample)
....@@ -989,7 +1108,7 @@
9891108 pkt = p;
9901109 fmt = p + APR_HDR_SIZE;
9911110
992
- q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id);
1111
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
9931112
9941113 pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
9951114 fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk);
....@@ -1018,10 +1137,256 @@
10181137 }
10191138 EXPORT_SYMBOL_GPL(q6asm_media_format_block_multi_ch_pcm);
10201139
1140
+int q6asm_stream_media_format_block_flac(struct audio_client *ac,
1141
+ uint32_t stream_id,
1142
+ struct q6asm_flac_cfg *cfg)
1143
+{
1144
+ struct asm_flac_fmt_blk_v2 *fmt;
1145
+ struct apr_pkt *pkt;
1146
+ void *p;
1147
+ int rc, pkt_size;
1148
+
1149
+ pkt_size = APR_HDR_SIZE + sizeof(*fmt);
1150
+ p = kzalloc(pkt_size, GFP_KERNEL);
1151
+ if (!p)
1152
+ return -ENOMEM;
1153
+
1154
+ pkt = p;
1155
+ fmt = p + APR_HDR_SIZE;
1156
+
1157
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
1158
+
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;
1169
+
1170
+ rc = q6asm_ac_send_cmd_sync(ac, pkt);
1171
+ kfree(pkt);
1172
+
1173
+ return rc;
1174
+}
1175
+EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_flac);
1176
+
1177
+int q6asm_stream_media_format_block_wma_v9(struct audio_client *ac,
1178
+ uint32_t stream_id,
1179
+ struct q6asm_wma_cfg *cfg)
1180
+{
1181
+ struct asm_wmastdv9_fmt_blk_v2 *fmt;
1182
+ struct apr_pkt *pkt;
1183
+ void *p;
1184
+ int rc, pkt_size;
1185
+
1186
+ pkt_size = APR_HDR_SIZE + sizeof(*fmt);
1187
+ p = kzalloc(pkt_size, GFP_KERNEL);
1188
+ if (!p)
1189
+ return -ENOMEM;
1190
+
1191
+ pkt = p;
1192
+ fmt = p + APR_HDR_SIZE;
1193
+
1194
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
1195
+
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;
1206
+ fmt->reserved = 0;
1207
+
1208
+ rc = q6asm_ac_send_cmd_sync(ac, pkt);
1209
+ kfree(pkt);
1210
+
1211
+ return rc;
1212
+}
1213
+EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_wma_v9);
1214
+
1215
+int q6asm_stream_media_format_block_wma_v10(struct audio_client *ac,
1216
+ uint32_t stream_id,
1217
+ struct q6asm_wma_cfg *cfg)
1218
+{
1219
+ struct asm_wmaprov10_fmt_blk_v2 *fmt;
1220
+ struct apr_pkt *pkt;
1221
+ void *p;
1222
+ int rc, pkt_size;
1223
+
1224
+ pkt_size = APR_HDR_SIZE + sizeof(*fmt);
1225
+ p = kzalloc(pkt_size, GFP_KERNEL);
1226
+ if (!p)
1227
+ return -ENOMEM;
1228
+
1229
+ pkt = p;
1230
+ fmt = p + APR_HDR_SIZE;
1231
+
1232
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
1233
+
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;
1246
+
1247
+ rc = q6asm_ac_send_cmd_sync(ac, pkt);
1248
+ kfree(pkt);
1249
+
1250
+ return rc;
1251
+}
1252
+EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_wma_v10);
1253
+
1254
+int q6asm_stream_media_format_block_alac(struct audio_client *ac,
1255
+ uint32_t stream_id,
1256
+ struct q6asm_alac_cfg *cfg)
1257
+{
1258
+ struct asm_alac_fmt_blk_v2 *fmt;
1259
+ struct apr_pkt *pkt;
1260
+ void *p;
1261
+ int rc, pkt_size;
1262
+
1263
+ pkt_size = APR_HDR_SIZE + sizeof(*fmt);
1264
+ p = kzalloc(pkt_size, GFP_KERNEL);
1265
+ if (!p)
1266
+ return -ENOMEM;
1267
+
1268
+ pkt = p;
1269
+ fmt = p + APR_HDR_SIZE;
1270
+
1271
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
1272
+
1273
+ pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
1274
+ fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk);
1275
+
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;
1285
+ fmt->pb = cfg->pb;
1286
+ fmt->mb = cfg->mb;
1287
+ fmt->kb = cfg->kb;
1288
+
1289
+ rc = q6asm_ac_send_cmd_sync(ac, pkt);
1290
+ kfree(pkt);
1291
+
1292
+ return rc;
1293
+}
1294
+EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_alac);
1295
+
1296
+int q6asm_stream_media_format_block_ape(struct audio_client *ac,
1297
+ uint32_t stream_id,
1298
+ struct q6asm_ape_cfg *cfg)
1299
+{
1300
+ struct asm_ape_fmt_blk_v2 *fmt;
1301
+ struct apr_pkt *pkt;
1302
+ void *p;
1303
+ int rc, pkt_size;
1304
+
1305
+ pkt_size = APR_HDR_SIZE + sizeof(*fmt);
1306
+ p = kzalloc(pkt_size, GFP_KERNEL);
1307
+ if (!p)
1308
+ return -ENOMEM;
1309
+
1310
+ pkt = p;
1311
+ fmt = p + APR_HDR_SIZE;
1312
+
1313
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
1314
+
1315
+ pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
1316
+ fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk);
1317
+
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;
1328
+
1329
+ rc = q6asm_ac_send_cmd_sync(ac, pkt);
1330
+ kfree(pkt);
1331
+
1332
+ return rc;
1333
+}
1334
+EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_ape);
1335
+
1336
+static int q6asm_stream_remove_silence(struct audio_client *ac, uint32_t stream_id,
1337
+ uint32_t cmd,
1338
+ uint32_t num_samples)
1339
+{
1340
+ uint32_t *samples;
1341
+ struct apr_pkt *pkt;
1342
+ void *p;
1343
+ int rc, pkt_size;
1344
+
1345
+ pkt_size = APR_HDR_SIZE + sizeof(uint32_t);
1346
+ p = kzalloc(pkt_size, GFP_ATOMIC);
1347
+ if (!p)
1348
+ return -ENOMEM;
1349
+
1350
+ pkt = p;
1351
+ samples = p + APR_HDR_SIZE;
1352
+
1353
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
1354
+
1355
+ pkt->hdr.opcode = cmd;
1356
+ *samples = num_samples;
1357
+ rc = apr_send_pkt(ac->adev, pkt);
1358
+ if (rc == pkt_size)
1359
+ rc = 0;
1360
+
1361
+ kfree(pkt);
1362
+
1363
+ return rc;
1364
+}
1365
+
1366
+int q6asm_stream_remove_initial_silence(struct audio_client *ac,
1367
+ uint32_t stream_id,
1368
+ uint32_t initial_samples)
1369
+{
1370
+ return q6asm_stream_remove_silence(ac, stream_id,
1371
+ ASM_DATA_CMD_REMOVE_INITIAL_SILENCE,
1372
+ initial_samples);
1373
+}
1374
+EXPORT_SYMBOL_GPL(q6asm_stream_remove_initial_silence);
1375
+
1376
+int q6asm_stream_remove_trailing_silence(struct audio_client *ac, uint32_t stream_id,
1377
+ uint32_t trailing_samples)
1378
+{
1379
+ return q6asm_stream_remove_silence(ac, stream_id,
1380
+ ASM_DATA_CMD_REMOVE_TRAILING_SILENCE,
1381
+ trailing_samples);
1382
+}
1383
+EXPORT_SYMBOL_GPL(q6asm_stream_remove_trailing_silence);
1384
+
10211385 /**
10221386 * q6asm_enc_cfg_blk_pcm_format_support() - setup pcm configuration for capture
10231387 *
10241388 * @ac: audio client pointer
1389
+ * @stream_id: stream id
10251390 * @rate: audio sample rate
10261391 * @channels: number of audio channels.
10271392 * @bits_per_sample: bits per sample
....@@ -1029,7 +1394,9 @@
10291394 * Return: Will be an negative value on error or zero on success
10301395 */
10311396 int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
1032
- uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
1397
+ uint32_t stream_id, uint32_t rate,
1398
+ uint32_t channels,
1399
+ uint16_t bits_per_sample)
10331400 {
10341401 struct asm_multi_channel_pcm_enc_cfg_v2 *enc_cfg;
10351402 struct apr_pkt *pkt;
....@@ -1045,7 +1412,7 @@
10451412
10461413 pkt = p;
10471414 enc_cfg = p + APR_HDR_SIZE;
1048
- q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id);
1415
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
10491416
10501417 pkt->hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
10511418 enc_cfg->encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
....@@ -1072,14 +1439,16 @@
10721439 }
10731440 EXPORT_SYMBOL_GPL(q6asm_enc_cfg_blk_pcm_format_support);
10741441
1442
+
10751443 /**
10761444 * q6asm_read() - read data of period size from audio client
10771445 *
10781446 * @ac: audio client pointer
1447
+ * @stream_id: stream id
10791448 *
10801449 * Return: Will be an negative value on error or zero on success
10811450 */
1082
-int q6asm_read(struct audio_client *ac)
1451
+int q6asm_read(struct audio_client *ac, uint32_t stream_id)
10831452 {
10841453 struct asm_data_cmd_read_v2 *read;
10851454 struct audio_port_data *port;
....@@ -1100,7 +1469,7 @@
11001469
11011470 spin_lock_irqsave(&ac->lock, flags);
11021471 port = &ac->port[SNDRV_PCM_STREAM_CAPTURE];
1103
- q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, ac->stream_id);
1472
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, stream_id);
11041473 ab = &port->buf[port->dsp_buf];
11051474 pkt->hdr.opcode = ASM_DATA_CMD_READ_V2;
11061475 read->buf_addr_lsw = lower_32_bits(ab->phys);
....@@ -1128,7 +1497,7 @@
11281497 }
11291498 EXPORT_SYMBOL_GPL(q6asm_read);
11301499
1131
-static int __q6asm_open_read(struct audio_client *ac,
1500
+static int __q6asm_open_read(struct audio_client *ac, uint32_t stream_id,
11321501 uint32_t format, uint16_t bits_per_sample)
11331502 {
11341503 struct asm_stream_cmd_open_read_v3 *open;
....@@ -1144,7 +1513,7 @@
11441513 pkt = p;
11451514 open = p + APR_HDR_SIZE;
11461515
1147
- q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id);
1516
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id);
11481517 pkt->hdr.opcode = ASM_STREAM_CMD_OPEN_READ_V3;
11491518 /* Stream prio : High, provide meta info with encoded frames */
11501519 open->src_endpointype = ASM_END_POINT_DEVICE_MATRIX;
....@@ -1175,15 +1544,16 @@
11751544 * q6asm_open_read() - Open audio client for reading
11761545 *
11771546 * @ac: audio client pointer
1547
+ * @stream_id: stream id
11781548 * @format: audio sample format
11791549 * @bits_per_sample: bits per sample
11801550 *
11811551 * Return: Will be an negative value on error or zero on success
11821552 */
1183
-int q6asm_open_read(struct audio_client *ac, uint32_t format,
1184
- uint16_t bits_per_sample)
1553
+int q6asm_open_read(struct audio_client *ac, uint32_t stream_id,
1554
+ uint32_t format, uint16_t bits_per_sample)
11851555 {
1186
- return __q6asm_open_read(ac, format, bits_per_sample);
1556
+ return __q6asm_open_read(ac, stream_id, format, bits_per_sample);
11871557 }
11881558 EXPORT_SYMBOL_GPL(q6asm_open_read);
11891559
....@@ -1191,15 +1561,16 @@
11911561 * q6asm_write_async() - non blocking write
11921562 *
11931563 * @ac: audio client pointer
1194
- * @len: lenght in bytes
1564
+ * @stream_id: stream id
1565
+ * @len: length in bytes
11951566 * @msw_ts: timestamp msw
11961567 * @lsw_ts: timestamp lsw
11971568 * @wflags: flags associated with write
11981569 *
11991570 * Return: Will be an negative value on error or zero on success
12001571 */
1201
-int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
1202
- uint32_t lsw_ts, uint32_t wflags)
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)
12031574 {
12041575 struct asm_data_cmd_write_v2 *write;
12051576 struct audio_port_data *port;
....@@ -1220,10 +1591,10 @@
12201591
12211592 spin_lock_irqsave(&ac->lock, flags);
12221593 port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK];
1223
- q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, ac->stream_id);
1594
+ q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, stream_id);
12241595
12251596 ab = &port->buf[port->dsp_buf];
1226
- pkt->hdr.token = port->dsp_buf;
1597
+ pkt->hdr.token = port->dsp_buf | (len << ASM_WRITE_TOKEN_LEN_SHIFT);
12271598 pkt->hdr.opcode = ASM_DATA_CMD_WRITE_V2;
12281599 write->buf_addr_lsw = lower_32_bits(ab->phys);
12291600 write->buf_addr_msw = upper_32_bits(ab->phys);
....@@ -1234,10 +1605,7 @@
12341605 write->mem_map_handle =
12351606 ac->port[SNDRV_PCM_STREAM_PLAYBACK].mem_map_handle;
12361607
1237
- if (wflags == NO_TIMESTAMP)
1238
- write->flags = (wflags & 0x800000FF);
1239
- else
1240
- write->flags = (0x80000000 | wflags);
1608
+ write->flags = wflags;
12411609
12421610 port->dsp_buf++;
12431611
....@@ -1267,9 +1635,9 @@
12671635 spin_unlock_irqrestore(&ac->lock, flags);
12681636 }
12691637
1270
-static int __q6asm_cmd(struct audio_client *ac, int cmd, bool wait)
1638
+static int __q6asm_cmd(struct audio_client *ac, uint32_t stream_id, int cmd,
1639
+ bool wait)
12711640 {
1272
- int stream_id = ac->stream_id;
12731641 struct apr_pkt pkt;
12741642 int rc;
12751643
....@@ -1316,13 +1684,14 @@
13161684 * q6asm_cmd() - run cmd on audio client
13171685 *
13181686 * @ac: audio client pointer
1687
+ * @stream_id: stream id
13191688 * @cmd: command to run on audio client.
13201689 *
13211690 * Return: Will be an negative value on error or zero on success
13221691 */
1323
-int q6asm_cmd(struct audio_client *ac, int cmd)
1692
+int q6asm_cmd(struct audio_client *ac, uint32_t stream_id, int cmd)
13241693 {
1325
- return __q6asm_cmd(ac, cmd, true);
1694
+ return __q6asm_cmd(ac, stream_id, cmd, true);
13261695 }
13271696 EXPORT_SYMBOL_GPL(q6asm_cmd);
13281697
....@@ -1330,13 +1699,14 @@
13301699 * q6asm_cmd_nowait() - non blocking, run cmd on audio client
13311700 *
13321701 * @ac: audio client pointer
1702
+ * @stream_id: stream id
13331703 * @cmd: command to run on audio client.
13341704 *
13351705 * Return: Will be an negative value on error or zero on success
13361706 */
1337
-int q6asm_cmd_nowait(struct audio_client *ac, int cmd)
1707
+int q6asm_cmd_nowait(struct audio_client *ac, uint32_t stream_id, int cmd)
13381708 {
1339
- return __q6asm_cmd(ac, cmd, false);
1709
+ return __q6asm_cmd(ac, stream_id, cmd, false);
13401710 }
13411711 EXPORT_SYMBOL_GPL(q6asm_cmd_nowait);
13421712
....@@ -1366,11 +1736,14 @@
13661736
13671737 return 0;
13681738 }
1739
+
1740
+#ifdef CONFIG_OF
13691741 static const struct of_device_id q6asm_device_id[] = {
13701742 { .compatible = "qcom,q6asm" },
13711743 {},
13721744 };
13731745 MODULE_DEVICE_TABLE(of, q6asm_device_id);
1746
+#endif
13741747
13751748 static struct apr_driver qcom_q6asm_driver = {
13761749 .probe = q6asm_probe,