~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/qcom/qdsp6/audioreach.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 // Copyright (c) 2020, Linaro Limited
  3 
  4 #include <linux/kernel.h>
  5 #include <linux/slab.h>
  6 #include <linux/soc/qcom/apr.h>
  7 #include <sound/soc.h>
  8 #include <sound/soc-dai.h>
  9 #include <sound/pcm.h>
 10 #include <sound/pcm_params.h>
 11 #include <dt-bindings/soc/qcom,gpr.h>
 12 #include "q6apm.h"
 13 #include "audioreach.h"
 14 
 15 /* SubGraph Config */
 16 struct apm_sub_graph_data {
 17         struct apm_sub_graph_cfg sub_graph_cfg;
 18         struct apm_prop_data perf_data;
 19         struct apm_sg_prop_id_perf_mode perf;
 20         struct apm_prop_data dir_data;
 21         struct apm_sg_prop_id_direction dir;
 22         struct apm_prop_data sid_data;
 23         struct apm_sg_prop_id_scenario_id sid;
 24 
 25 } __packed;
 26 
 27 #define APM_SUB_GRAPH_CFG_NPROP 3
 28 
 29 struct apm_sub_graph_params  {
 30         struct apm_module_param_data param_data;
 31         uint32_t num_sub_graphs;
 32         struct apm_sub_graph_data sg_cfg[];
 33 } __packed;
 34 
 35 #define APM_SUB_GRAPH_PSIZE(p, n) ALIGN(struct_size(p, sg_cfg, n), 8)
 36 
 37 /* container config */
 38 struct apm_container_obj  {
 39         struct apm_container_cfg container_cfg;
 40         /* Capability ID list */
 41         struct apm_prop_data cap_data;
 42         uint32_t num_capability_id;
 43         uint32_t capability_id;
 44 
 45         /* Container graph Position */
 46         struct apm_prop_data pos_data;
 47         struct apm_cont_prop_id_graph_pos pos;
 48 
 49         /* Container Stack size */
 50         struct apm_prop_data stack_data;
 51         struct apm_cont_prop_id_stack_size stack;
 52 
 53         /* Container proc domain id */
 54         struct apm_prop_data domain_data;
 55         struct apm_cont_prop_id_domain domain;
 56 } __packed;
 57 
 58 struct apm_container_params  {
 59         struct apm_module_param_data param_data;
 60         uint32_t num_containers;
 61         struct apm_container_obj cont_obj[];
 62 } __packed;
 63 
 64 #define APM_CONTAINER_PSIZE(p, n) ALIGN(struct_size(p, cont_obj, n), 8)
 65 
 66 /* Module List config */
 67 struct apm_mod_list_obj {
 68         /* Modules list cfg */
 69         uint32_t sub_graph_id;
 70         uint32_t container_id;
 71         uint32_t num_modules;
 72         struct apm_module_obj mod_cfg[];
 73 } __packed;
 74 
 75 #define APM_MOD_LIST_OBJ_PSIZE(p, n) struct_size(p, mod_cfg, n)
 76 
 77 struct apm_module_list_params {
 78         struct apm_module_param_data param_data;
 79         uint32_t num_modules_list;
 80         /* Module list config array */
 81         struct apm_mod_list_obj mod_list_obj[];
 82 } __packed;
 83 
 84 
 85 /* Module Properties */
 86 struct apm_mod_prop_obj {
 87         u32 instance_id;
 88         u32 num_props;
 89         struct apm_prop_data prop_data_1;
 90         struct apm_module_prop_id_port_info prop_id_port;
 91 } __packed;
 92 
 93 struct apm_prop_list_params {
 94         struct apm_module_param_data param_data;
 95         u32 num_modules_prop_cfg;
 96         struct apm_mod_prop_obj mod_prop_obj[];
 97 
 98 } __packed;
 99 
100 #define APM_MOD_PROP_PSIZE(p, n) ALIGN(struct_size(p, mod_prop_obj, n), 8)
101 
102 /* Module Connections */
103 struct apm_mod_conn_list_params {
104         struct apm_module_param_data param_data;
105         u32 num_connections;
106         struct apm_module_conn_obj conn_obj[];
107 
108 } __packed;
109 
110 #define APM_MOD_CONN_PSIZE(p, n) ALIGN(struct_size(p, conn_obj, n), 8)
111 
112 struct apm_graph_open_params {
113         struct apm_cmd_header *cmd_header;
114         struct apm_sub_graph_params *sg_data;
115         struct apm_container_params *cont_data;
116         struct apm_module_list_params *mod_list_data;
117         struct apm_prop_list_params *mod_prop_data;
118         struct apm_mod_conn_list_params *mod_conn_list_data;
119 } __packed;
120 
121 struct apm_pcm_module_media_fmt_cmd {
122         struct apm_module_param_data param_data;
123         struct param_id_pcm_output_format_cfg header;
124         struct payload_pcm_output_format_cfg media_cfg;
125 } __packed;
126 
127 struct apm_rd_shmem_module_config_cmd {
128         struct apm_module_param_data param_data;
129         struct param_id_rd_sh_mem_cfg cfg;
130 } __packed;
131 
132 struct apm_sh_module_media_fmt_cmd {
133         struct media_format header;
134         struct payload_media_fmt_pcm cfg;
135 } __packed;
136 
137 #define APM_SHMEM_FMT_CFG_PSIZE(ch) ALIGN( \
138                                 sizeof(struct apm_sh_module_media_fmt_cmd) + \
139                                 ch * sizeof(uint8_t), 8)
140 
141 /* num of channels as argument */
142 #define APM_PCM_MODULE_FMT_CMD_PSIZE(ch) ALIGN( \
143                                 sizeof(struct apm_pcm_module_media_fmt_cmd) + \
144                                 ch * sizeof(uint8_t), 8)
145 
146 #define APM_PCM_OUT_FMT_CFG_PSIZE(p, n) ALIGN(struct_size(p, channel_mapping, n), 4)
147 
148 struct apm_i2s_module_intf_cfg {
149         struct apm_module_param_data param_data;
150         struct param_id_i2s_intf_cfg cfg;
151 } __packed;
152 
153 #define APM_I2S_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_i2s_module_intf_cfg), 8)
154 
155 struct apm_module_hw_ep_mf_cfg {
156         struct apm_module_param_data param_data;
157         struct param_id_hw_ep_mf mf;
158 } __packed;
159 
160 #define APM_HW_EP_CFG_PSIZE ALIGN(sizeof(struct apm_module_hw_ep_mf_cfg), 8)
161 
162 #define APM_MFC_CFG_PSIZE(p, n) ALIGN(struct_size(p, channel_mapping, n), 4)
163 
164 struct apm_module_frame_size_factor_cfg {
165         struct apm_module_param_data param_data;
166         uint32_t frame_size_factor;
167 } __packed;
168 
169 #define APM_FS_CFG_PSIZE ALIGN(sizeof(struct apm_module_frame_size_factor_cfg), 8)
170 
171 struct apm_module_hw_ep_power_mode_cfg {
172         struct apm_module_param_data param_data;
173         struct param_id_hw_ep_power_mode_cfg power_mode;
174 } __packed;
175 
176 #define APM_HW_EP_PMODE_CFG_PSIZE ALIGN(sizeof(struct apm_module_hw_ep_power_mode_cfg), 8)
177 
178 struct apm_module_hw_ep_dma_data_align_cfg {
179         struct apm_module_param_data param_data;
180         struct param_id_hw_ep_dma_data_align align;
181 } __packed;
182 
183 #define APM_HW_EP_DALIGN_CFG_PSIZE ALIGN(sizeof(struct apm_module_hw_ep_dma_data_align_cfg), 8)
184 
185 struct apm_gain_module_cfg {
186         struct apm_module_param_data param_data;
187         struct param_id_gain_cfg gain_cfg;
188 } __packed;
189 
190 #define APM_GAIN_CFG_PSIZE ALIGN(sizeof(struct apm_gain_module_cfg), 8)
191 
192 struct apm_codec_dma_module_intf_cfg {
193         struct apm_module_param_data param_data;
194         struct param_id_codec_dma_intf_cfg cfg;
195 } __packed;
196 
197 #define APM_CDMA_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_codec_dma_module_intf_cfg), 8)
198 
199 struct apm_display_port_module_intf_cfg {
200         struct apm_module_param_data param_data;
201         struct param_id_display_port_intf_cfg cfg;
202 } __packed;
203 #define APM_DP_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_display_port_module_intf_cfg), 8)
204 
205 static void *__audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token,
206                                     uint32_t src_port, uint32_t dest_port, bool has_cmd_hdr)
207 {
208         struct gpr_pkt *pkt;
209         void *p;
210         int pkt_size = GPR_HDR_SIZE + payload_size;
211 
212         if (has_cmd_hdr)
213                 pkt_size += APM_CMD_HDR_SIZE;
214 
215         p = kzalloc(pkt_size, GFP_KERNEL);
216         if (!p)
217                 return ERR_PTR(-ENOMEM);
218 
219         pkt = p;
220         pkt->hdr.version = GPR_PKT_VER;
221         pkt->hdr.hdr_size = GPR_PKT_HEADER_WORD_SIZE;
222         pkt->hdr.pkt_size = pkt_size;
223         pkt->hdr.dest_port = dest_port;
224         pkt->hdr.src_port = src_port;
225 
226         pkt->hdr.dest_domain = GPR_DOMAIN_ID_ADSP;
227         pkt->hdr.src_domain = GPR_DOMAIN_ID_APPS;
228         pkt->hdr.token = token;
229         pkt->hdr.opcode = opcode;
230 
231         if (has_cmd_hdr) {
232                 struct apm_cmd_header *cmd_header;
233 
234                 p = p + GPR_HDR_SIZE;
235                 cmd_header = p;
236                 cmd_header->payload_size = payload_size;
237         }
238 
239         return pkt;
240 }
241 
242 void *audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token,
243                            uint32_t src_port, uint32_t dest_port)
244 {
245         return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, false);
246 }
247 EXPORT_SYMBOL_GPL(audioreach_alloc_pkt);
248 
249 void *audioreach_alloc_apm_pkt(int pkt_size, uint32_t opcode, uint32_t token, uint32_t src_port)
250 {
251         return __audioreach_alloc_pkt(pkt_size, opcode, token, src_port, APM_MODULE_INSTANCE_ID,
252                                       false);
253 }
254 EXPORT_SYMBOL_GPL(audioreach_alloc_apm_pkt);
255 
256 void *audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode, uint32_t token,
257                                uint32_t src_port, uint32_t dest_port)
258 {
259         return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, true);
260 }
261 EXPORT_SYMBOL_GPL(audioreach_alloc_cmd_pkt);
262 
263 void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t token)
264 {
265         return __audioreach_alloc_pkt(pkt_size, opcode, token, GPR_APM_MODULE_IID,
266                                        APM_MODULE_INSTANCE_ID, true);
267 }
268 EXPORT_SYMBOL_GPL(audioreach_alloc_apm_cmd_pkt);
269 
270 void audioreach_set_default_channel_mapping(u8 *ch_map, int num_channels)
271 {
272         if (num_channels == 1) {
273                 ch_map[0] =  PCM_CHANNEL_FL;
274         } else if (num_channels == 2) {
275                 ch_map[0] =  PCM_CHANNEL_FL;
276                 ch_map[1] =  PCM_CHANNEL_FR;
277         } else if (num_channels == 4) {
278                 ch_map[0] =  PCM_CHANNEL_FL;
279                 ch_map[1] =  PCM_CHANNEL_FR;
280                 ch_map[2] =  PCM_CHANNEL_LS;
281                 ch_map[3] =  PCM_CHANNEL_RS;
282         }
283 }
284 EXPORT_SYMBOL_GPL(audioreach_set_default_channel_mapping);
285 
286 static void apm_populate_container_config(struct apm_container_obj *cfg,
287                                           struct audioreach_container *cont)
288 {
289 
290         /* Container Config */
291         cfg->container_cfg.container_id = cont->container_id;
292         cfg->container_cfg.num_prop = 4;
293 
294         /* Capability list */
295         cfg->cap_data.prop_id = APM_CONTAINER_PROP_ID_CAPABILITY_LIST;
296         cfg->cap_data.prop_size = APM_CONTAINER_PROP_ID_CAPABILITY_SIZE;
297         cfg->num_capability_id = 1;
298         cfg->capability_id = cont->capability_id;
299 
300         /* Graph Position */
301         cfg->pos_data.prop_id = APM_CONTAINER_PROP_ID_GRAPH_POS;
302         cfg->pos_data.prop_size = sizeof(struct apm_cont_prop_id_graph_pos);
303         cfg->pos.graph_pos = cont->graph_pos;
304 
305         /* Stack size */
306         cfg->stack_data.prop_id = APM_CONTAINER_PROP_ID_STACK_SIZE;
307         cfg->stack_data.prop_size = sizeof(struct apm_cont_prop_id_stack_size);
308         cfg->stack.stack_size = cont->stack_size;
309 
310         /* Proc domain */
311         cfg->domain_data.prop_id = APM_CONTAINER_PROP_ID_PROC_DOMAIN;
312         cfg->domain_data.prop_size = sizeof(struct apm_cont_prop_id_domain);
313         cfg->domain.proc_domain = cont->proc_domain;
314 }
315 
316 static void apm_populate_sub_graph_config(struct apm_sub_graph_data *cfg,
317                                           struct audioreach_sub_graph *sg)
318 {
319         cfg->sub_graph_cfg.sub_graph_id = sg->sub_graph_id;
320         cfg->sub_graph_cfg.num_sub_graph_prop = APM_SUB_GRAPH_CFG_NPROP;
321 
322         /* Perf Mode */
323         cfg->perf_data.prop_id = APM_SUB_GRAPH_PROP_ID_PERF_MODE;
324         cfg->perf_data.prop_size = APM_SG_PROP_ID_PERF_MODE_SIZE;
325         cfg->perf.perf_mode = sg->perf_mode;
326 
327         /* Direction */
328         cfg->dir_data.prop_id = APM_SUB_GRAPH_PROP_ID_DIRECTION;
329         cfg->dir_data.prop_size = APM_SG_PROP_ID_DIR_SIZE;
330         cfg->dir.direction = sg->direction;
331 
332         /* Scenario ID */
333         cfg->sid_data.prop_id = APM_SUB_GRAPH_PROP_ID_SCENARIO_ID;
334         cfg->sid_data.prop_size = APM_SG_PROP_ID_SID_SIZE;
335         cfg->sid.scenario_id = sg->scenario_id;
336 }
337 
338 static void apm_populate_module_prop_obj(struct apm_mod_prop_obj *obj,
339                                          struct audioreach_module *module)
340 {
341 
342         obj->instance_id = module->instance_id;
343         obj->num_props = 1;
344         obj->prop_data_1.prop_id = APM_MODULE_PROP_ID_PORT_INFO;
345         obj->prop_data_1.prop_size = APM_MODULE_PROP_ID_PORT_INFO_SZ;
346         obj->prop_id_port.max_ip_port = module->max_ip_port;
347         obj->prop_id_port.max_op_port = module->max_op_port;
348 }
349 
350 static void apm_populate_module_list_obj(struct apm_mod_list_obj *obj,
351                                          struct audioreach_container *container,
352                                          int sub_graph_id)
353 {
354         struct audioreach_module *module;
355         int i;
356 
357         obj->sub_graph_id = sub_graph_id;
358         obj->container_id = container->container_id;
359         obj->num_modules = container->num_modules;
360         i = 0;
361         list_for_each_entry(module, &container->modules_list, node) {
362                 obj->mod_cfg[i].module_id = module->module_id;
363                 obj->mod_cfg[i].instance_id = module->instance_id;
364                 i++;
365         }
366 }
367 
368 static void audioreach_populate_graph(struct q6apm *apm, struct audioreach_graph_info *info,
369                                       struct apm_graph_open_params *open,
370                                       struct list_head *sg_list,
371                                       int num_sub_graphs)
372 {
373         struct apm_mod_conn_list_params *mc_data = open->mod_conn_list_data;
374         struct apm_module_list_params *ml_data = open->mod_list_data;
375         struct apm_prop_list_params *mp_data = open->mod_prop_data;
376         struct apm_container_params *c_data = open->cont_data;
377         struct apm_sub_graph_params *sg_data = open->sg_data;
378         int ncontainer = 0, nmodule = 0, nconn = 0;
379         struct apm_mod_prop_obj *module_prop_obj;
380         struct audioreach_container *container;
381         struct apm_module_conn_obj *conn_obj;
382         struct audioreach_module *module;
383         struct audioreach_sub_graph *sg;
384         struct apm_container_obj *cobj;
385         struct apm_mod_list_obj *mlobj;
386         int i = 0;
387 
388         mlobj = &ml_data->mod_list_obj[0];
389 
390 
391         if (info->dst_mod_inst_id && info->src_mod_inst_id) {
392                 conn_obj = &mc_data->conn_obj[nconn];
393                 conn_obj->src_mod_inst_id = info->src_mod_inst_id;
394                 conn_obj->src_mod_op_port_id = info->src_mod_op_port_id;
395                 conn_obj->dst_mod_inst_id = info->dst_mod_inst_id;
396                 conn_obj->dst_mod_ip_port_id = info->dst_mod_ip_port_id;
397                 nconn++;
398         }
399 
400         list_for_each_entry(sg, sg_list, node) {
401                 struct apm_sub_graph_data *sg_cfg = &sg_data->sg_cfg[i++];
402 
403                 apm_populate_sub_graph_config(sg_cfg, sg);
404 
405                 list_for_each_entry(container, &sg->container_list, node) {
406                         cobj = &c_data->cont_obj[ncontainer];
407 
408                         apm_populate_container_config(cobj, container);
409                         apm_populate_module_list_obj(mlobj, container, sg->sub_graph_id);
410 
411                         list_for_each_entry(module, &container->modules_list, node) {
412                                 int pn;
413 
414                                 module_prop_obj = &mp_data->mod_prop_obj[nmodule++];
415                                 apm_populate_module_prop_obj(module_prop_obj, module);
416 
417                                 if (!module->max_op_port)
418                                         continue;
419 
420                                 for (pn = 0; pn < module->max_op_port; pn++) {
421                                         if (module->dst_mod_inst_id[pn]) {
422                                                 conn_obj = &mc_data->conn_obj[nconn];
423                                                 conn_obj->src_mod_inst_id = module->instance_id;
424                                                 conn_obj->src_mod_op_port_id =
425                                                                 module->src_mod_op_port_id[pn];
426                                                 conn_obj->dst_mod_inst_id =
427                                                                 module->dst_mod_inst_id[pn];
428                                                 conn_obj->dst_mod_ip_port_id =
429                                                                 module->dst_mod_ip_port_id[pn];
430                                                 nconn++;
431                                         }
432                                 }
433                         }
434                         mlobj = (void *) mlobj + APM_MOD_LIST_OBJ_PSIZE(mlobj,
435                                                                         container->num_modules);
436 
437                         ncontainer++;
438                 }
439         }
440 }
441 
442 void *audioreach_alloc_graph_pkt(struct q6apm *apm, struct audioreach_graph_info *info)
443 {
444         int payload_size, sg_sz, cont_sz, ml_sz, mp_sz, mc_sz;
445         struct apm_module_param_data  *param_data;
446         struct apm_container_params *cont_params;
447         struct audioreach_container *container;
448         struct apm_sub_graph_params *sg_params;
449         struct apm_mod_conn_list_params *mcon;
450         struct apm_graph_open_params params;
451         struct apm_prop_list_params *mprop;
452         struct audioreach_module *module;
453         struct audioreach_sub_graph *sgs;
454         struct apm_mod_list_obj *mlobj;
455         struct list_head *sg_list;
456         int num_connections = 0;
457         int num_containers = 0;
458         int num_sub_graphs = 0;
459         int num_modules = 0;
460         int num_modules_list;
461         struct gpr_pkt *pkt;
462         void *p;
463 
464         sg_list = &info->sg_list;
465         ml_sz = 0;
466 
467         /* add FE-BE connections */
468         if (info->dst_mod_inst_id && info->src_mod_inst_id)
469                 num_connections++;
470 
471         list_for_each_entry(sgs, sg_list, node) {
472                 num_sub_graphs++;
473                 list_for_each_entry(container, &sgs->container_list, node) {
474                         num_containers++;
475                         num_modules += container->num_modules;
476                         ml_sz = ml_sz + sizeof(struct apm_module_list_params) +
477                                 APM_MOD_LIST_OBJ_PSIZE(mlobj, container->num_modules);
478 
479                         list_for_each_entry(module, &container->modules_list, node) {
480                                 num_connections += module->num_connections;
481                         }
482                 }
483         }
484 
485         num_modules_list = num_containers;
486         sg_sz = APM_SUB_GRAPH_PSIZE(sg_params, num_sub_graphs);
487         cont_sz = APM_CONTAINER_PSIZE(cont_params, num_containers);
488 
489         ml_sz = ALIGN(ml_sz, 8);
490 
491         mp_sz = APM_MOD_PROP_PSIZE(mprop, num_modules);
492         mc_sz = APM_MOD_CONN_PSIZE(mcon, num_connections);
493 
494         payload_size = sg_sz + cont_sz + ml_sz + mp_sz + mc_sz;
495         pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_GRAPH_OPEN, 0);
496         if (IS_ERR(pkt))
497                 return pkt;
498 
499         p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
500 
501         /* SubGraph */
502         params.sg_data = p;
503         param_data = &params.sg_data->param_data;
504         param_data->module_instance_id = APM_MODULE_INSTANCE_ID;
505         param_data->param_id = APM_PARAM_ID_SUB_GRAPH_CONFIG;
506         param_data->param_size = sg_sz - APM_MODULE_PARAM_DATA_SIZE;
507         params.sg_data->num_sub_graphs = num_sub_graphs;
508         p += sg_sz;
509 
510         /* Container */
511         params.cont_data = p;
512         param_data = &params.cont_data->param_data;
513         param_data->module_instance_id = APM_MODULE_INSTANCE_ID;
514         param_data->param_id = APM_PARAM_ID_CONTAINER_CONFIG;
515         param_data->param_size = cont_sz - APM_MODULE_PARAM_DATA_SIZE;
516         params.cont_data->num_containers = num_containers;
517         p += cont_sz;
518 
519         /* Module List*/
520         params.mod_list_data = p;
521         param_data = &params.mod_list_data->param_data;
522         param_data->module_instance_id = APM_MODULE_INSTANCE_ID;
523         param_data->param_id = APM_PARAM_ID_MODULE_LIST;
524         param_data->param_size = ml_sz - APM_MODULE_PARAM_DATA_SIZE;
525         params.mod_list_data->num_modules_list = num_modules_list;
526         p += ml_sz;
527 
528         /* Module Properties */
529         params.mod_prop_data = p;
530         param_data = &params.mod_prop_data->param_data;
531         param_data->module_instance_id = APM_MODULE_INSTANCE_ID;
532         param_data->param_id = APM_PARAM_ID_MODULE_PROP;
533         param_data->param_size = mp_sz - APM_MODULE_PARAM_DATA_SIZE;
534         params.mod_prop_data->num_modules_prop_cfg = num_modules;
535         p += mp_sz;
536 
537         /* Module Connections */
538         params.mod_conn_list_data = p;
539         param_data = &params.mod_conn_list_data->param_data;
540         param_data->module_instance_id = APM_MODULE_INSTANCE_ID;
541         param_data->param_id = APM_PARAM_ID_MODULE_CONN;
542         param_data->param_size = mc_sz - APM_MODULE_PARAM_DATA_SIZE;
543         params.mod_conn_list_data->num_connections = num_connections;
544         p += mc_sz;
545 
546         audioreach_populate_graph(apm, info, &params, sg_list, num_sub_graphs);
547 
548         return pkt;
549 }
550 EXPORT_SYMBOL_GPL(audioreach_alloc_graph_pkt);
551 
552 int audioreach_send_cmd_sync(struct device *dev, gpr_device_t *gdev,
553                              struct gpr_ibasic_rsp_result_t *result, struct mutex *cmd_lock,
554                              gpr_port_t *port, wait_queue_head_t *cmd_wait,
555                              struct gpr_pkt *pkt, uint32_t rsp_opcode)
556 {
557 
558         struct gpr_hdr *hdr = &pkt->hdr;
559         int rc;
560 
561         mutex_lock(cmd_lock);
562         result->opcode = 0;
563         result->status = 0;
564 
565         if (port)
566                 rc = gpr_send_port_pkt(port, pkt);
567         else if (gdev)
568                 rc = gpr_send_pkt(gdev, pkt);
569         else
570                 rc = -EINVAL;
571 
572         if (rc < 0)
573                 goto err;
574 
575         if (rsp_opcode)
576                 rc = wait_event_timeout(*cmd_wait, (result->opcode == hdr->opcode) ||
577                                         (result->opcode == rsp_opcode), 5 * HZ);
578         else
579                 rc = wait_event_timeout(*cmd_wait, (result->opcode == hdr->opcode), 5 * HZ);
580 
581         if (!rc) {
582                 dev_err(dev, "CMD timeout for [%x] opcode\n", hdr->opcode);
583                 rc = -ETIMEDOUT;
584         } else if (result->status > 0) {
585                 dev_err(dev, "DSP returned error[%x] %x\n", hdr->opcode, result->status);
586                 rc = -EINVAL;
587         } else {
588                 /* DSP successfully finished the command */
589                 rc = 0;
590         }
591 
592 err:
593         mutex_unlock(cmd_lock);
594         return rc;
595 }
596 EXPORT_SYMBOL_GPL(audioreach_send_cmd_sync);
597 
598 int audioreach_graph_send_cmd_sync(struct q6apm_graph *graph, struct gpr_pkt *pkt,
599                                    uint32_t rsp_opcode)
600 {
601 
602         return audioreach_send_cmd_sync(graph->dev, NULL,  &graph->result, &graph->lock,
603                                         graph->port, &graph->cmd_wait, pkt, rsp_opcode);
604 }
605 EXPORT_SYMBOL_GPL(audioreach_graph_send_cmd_sync);
606 
607 static int audioreach_display_port_set_media_format(struct q6apm_graph *graph,
608                                                     struct audioreach_module *module,
609                                                     struct audioreach_module_config *cfg)
610 {
611         struct apm_display_port_module_intf_cfg *intf_cfg;
612         struct apm_module_frame_size_factor_cfg *fs_cfg;
613         struct apm_module_param_data *param_data;
614         struct apm_module_hw_ep_mf_cfg *hw_cfg;
615         int ic_sz, ep_sz, fs_sz, dl_sz;
616         int rc, payload_size;
617         struct gpr_pkt *pkt;
618         void *p;
619 
620         ic_sz = APM_DP_INTF_CFG_PSIZE;
621         ep_sz = APM_HW_EP_CFG_PSIZE;
622         fs_sz = APM_FS_CFG_PSIZE;
623         dl_sz = 0;
624 
625         payload_size = ic_sz + ep_sz + fs_sz + dl_sz;
626 
627         pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
628         if (IS_ERR(pkt))
629                 return PTR_ERR(pkt);
630 
631         p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
632 
633         hw_cfg = p;
634         param_data = &hw_cfg->param_data;
635         param_data->module_instance_id = module->instance_id;
636         param_data->error_code = 0;
637         param_data->param_id = PARAM_ID_HW_EP_MF_CFG;
638         param_data->param_size = ep_sz - APM_MODULE_PARAM_DATA_SIZE;
639 
640         hw_cfg->mf.sample_rate = cfg->sample_rate;
641         hw_cfg->mf.bit_width = cfg->bit_width;
642         hw_cfg->mf.num_channels = cfg->num_channels;
643         hw_cfg->mf.data_format = module->data_format;
644         p += ep_sz;
645 
646         fs_cfg = p;
647         param_data = &fs_cfg->param_data;
648         param_data->module_instance_id = module->instance_id;
649         param_data->error_code = 0;
650         param_data->param_id = PARAM_ID_HW_EP_FRAME_SIZE_FACTOR;
651         param_data->param_size = fs_sz - APM_MODULE_PARAM_DATA_SIZE;
652         fs_cfg->frame_size_factor = 1;
653         p += fs_sz;
654 
655         intf_cfg = p;
656         param_data = &intf_cfg->param_data;
657         param_data->module_instance_id = module->instance_id;
658         param_data->error_code = 0;
659         param_data->param_id = PARAM_ID_DISPLAY_PORT_INTF_CFG;
660         param_data->param_size = ic_sz - APM_MODULE_PARAM_DATA_SIZE;
661 
662         intf_cfg->cfg.channel_allocation = cfg->channel_allocation;
663         intf_cfg->cfg.mst_idx = 0;
664         intf_cfg->cfg.dptx_idx = cfg->dp_idx;
665 
666         rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
667 
668         kfree(pkt);
669 
670         return rc;
671 }
672 
673 /* LPASS Codec DMA port Module Media Format Setup */
674 static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
675                                                  struct audioreach_module *module,
676                                                  struct audioreach_module_config *cfg)
677 {
678         struct apm_codec_dma_module_intf_cfg *intf_cfg;
679         struct apm_module_frame_size_factor_cfg *fs_cfg;
680         struct apm_module_hw_ep_power_mode_cfg *pm_cfg;
681         struct apm_module_param_data *param_data;
682         struct apm_module_hw_ep_mf_cfg *hw_cfg;
683         int ic_sz, ep_sz, fs_sz, pm_sz, dl_sz;
684         int rc, payload_size;
685         struct gpr_pkt *pkt;
686         void *p;
687 
688         ic_sz = APM_CDMA_INTF_CFG_PSIZE;
689         ep_sz = APM_HW_EP_CFG_PSIZE;
690         fs_sz = APM_FS_CFG_PSIZE;
691         pm_sz = APM_HW_EP_PMODE_CFG_PSIZE;
692         dl_sz = 0;
693 
694         payload_size = ic_sz + ep_sz + fs_sz + pm_sz + dl_sz;
695 
696         pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
697         if (IS_ERR(pkt))
698                 return PTR_ERR(pkt);
699 
700         p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
701 
702         hw_cfg = p;
703         param_data = &hw_cfg->param_data;
704         param_data->module_instance_id = module->instance_id;
705         param_data->error_code = 0;
706         param_data->param_id = PARAM_ID_HW_EP_MF_CFG;
707         param_data->param_size = ep_sz - APM_MODULE_PARAM_DATA_SIZE;
708 
709         hw_cfg->mf.sample_rate = cfg->sample_rate;
710         hw_cfg->mf.bit_width = cfg->bit_width;
711         hw_cfg->mf.num_channels = cfg->num_channels;
712         hw_cfg->mf.data_format = module->data_format;
713         p += ep_sz;
714 
715         fs_cfg = p;
716         param_data = &fs_cfg->param_data;
717         param_data->module_instance_id = module->instance_id;
718         param_data->error_code = 0;
719         param_data->param_id = PARAM_ID_HW_EP_FRAME_SIZE_FACTOR;
720         param_data->param_size = fs_sz - APM_MODULE_PARAM_DATA_SIZE;
721         fs_cfg->frame_size_factor = 1;
722         p += fs_sz;
723 
724         intf_cfg = p;
725         param_data = &intf_cfg->param_data;
726         param_data->module_instance_id = module->instance_id;
727         param_data->error_code = 0;
728         param_data->param_id = PARAM_ID_CODEC_DMA_INTF_CFG;
729         param_data->param_size = ic_sz - APM_MODULE_PARAM_DATA_SIZE;
730 
731         intf_cfg->cfg.lpaif_type = module->hw_interface_type;
732         intf_cfg->cfg.intf_index = module->hw_interface_idx;
733         intf_cfg->cfg.active_channels_mask = (1 << cfg->num_channels) - 1;
734         p += ic_sz;
735 
736         pm_cfg = p;
737         param_data = &pm_cfg->param_data;
738         param_data->module_instance_id = module->instance_id;
739         param_data->error_code = 0;
740         param_data->param_id = PARAM_ID_HW_EP_POWER_MODE_CFG;
741         param_data->param_size = pm_sz - APM_MODULE_PARAM_DATA_SIZE;
742         pm_cfg->power_mode.power_mode = 0;
743 
744         rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
745 
746         kfree(pkt);
747 
748         return rc;
749 }
750 
751 int audioreach_send_u32_param(struct q6apm_graph *graph, struct audioreach_module *module,
752                               uint32_t param_id, uint32_t param_val)
753 {
754         struct apm_module_param_data *param_data;
755         struct gpr_pkt *pkt;
756         uint32_t *param;
757         int rc, payload_size;
758         void *p;
759 
760         payload_size = sizeof(uint32_t) + APM_MODULE_PARAM_DATA_SIZE;
761         p = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
762         if (IS_ERR(p))
763                 return -ENOMEM;
764 
765         pkt = p;
766         p = p + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
767 
768         param_data = p;
769         param_data->module_instance_id = module->instance_id;
770         param_data->error_code = 0;
771         param_data->param_id = param_id;
772         param_data->param_size = sizeof(uint32_t);
773 
774         p = p + APM_MODULE_PARAM_DATA_SIZE;
775         param = p;
776         *param = param_val;
777 
778         rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
779 
780         kfree(pkt);
781 
782         return rc;
783 }
784 EXPORT_SYMBOL_GPL(audioreach_send_u32_param);
785 
786 static int audioreach_sal_limiter_enable(struct q6apm_graph *graph,
787                                          struct audioreach_module *module, bool enable)
788 {
789         return audioreach_send_u32_param(graph, module, PARAM_ID_SAL_LIMITER_ENABLE, enable);
790 }
791 
792 static int audioreach_sal_set_media_format(struct q6apm_graph *graph,
793                                            struct audioreach_module *module,
794                                            struct audioreach_module_config *cfg)
795 {
796         return audioreach_send_u32_param(graph, module, PARAM_ID_SAL_OUTPUT_CFG,  cfg->bit_width);
797 }
798 
799 static int audioreach_module_enable(struct q6apm_graph *graph,
800                                     struct audioreach_module *module,
801                                     bool enable)
802 {
803         return audioreach_send_u32_param(graph, module, PARAM_ID_MODULE_ENABLE, enable);
804 }
805 
806 static int audioreach_gapless_set_media_format(struct q6apm_graph *graph,
807                                                struct audioreach_module *module,
808                                                struct audioreach_module_config *cfg)
809 {
810         return audioreach_send_u32_param(graph, module, PARAM_ID_EARLY_EOS_DELAY,
811                                          EARLY_EOS_DELAY_MS);
812 }
813 
814 static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
815                                            struct audioreach_module *module,
816                                            struct audioreach_module_config *cfg)
817 {
818         struct apm_module_param_data *param_data;
819         struct param_id_mfc_media_format *media_format;
820         uint32_t num_channels = cfg->num_channels;
821         int payload_size;
822         struct gpr_pkt *pkt;
823         int rc, i;
824         void *p;
825 
826         payload_size = APM_MFC_CFG_PSIZE(media_format, num_channels) +
827                 APM_MODULE_PARAM_DATA_SIZE;
828 
829         pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
830         if (IS_ERR(pkt))
831                 return PTR_ERR(pkt);
832 
833         p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
834 
835         param_data = p;
836         param_data->module_instance_id = module->instance_id;
837         param_data->error_code = 0;
838         param_data->param_id = PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
839         param_data->param_size = APM_MFC_CFG_PSIZE(media_format, num_channels);
840         p = p + APM_MODULE_PARAM_DATA_SIZE;
841         media_format = p;
842 
843         media_format->sample_rate = cfg->sample_rate;
844         media_format->bit_width = cfg->bit_width;
845         media_format->num_channels = cfg->num_channels;
846         for (i = 0; i < num_channels; i++)
847                 media_format->channel_mapping[i] = cfg->channel_map[i];
848 
849         rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
850 
851         kfree(pkt);
852 
853         return rc;
854 }
855 
856 static int audioreach_set_compr_media_format(struct media_format *media_fmt_hdr,
857                                              void *p, struct audioreach_module_config *mcfg)
858 {
859         struct payload_media_fmt_aac_t *aac_cfg;
860         struct payload_media_fmt_pcm *mp3_cfg;
861         struct payload_media_fmt_flac_t *flac_cfg;
862 
863         switch (mcfg->fmt) {
864         case SND_AUDIOCODEC_MP3:
865                 media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED;
866                 media_fmt_hdr->fmt_id = MEDIA_FMT_ID_MP3;
867                 media_fmt_hdr->payload_size = 0;
868                 p = p + sizeof(*media_fmt_hdr);
869                 mp3_cfg = p;
870                 mp3_cfg->sample_rate = mcfg->sample_rate;
871                 mp3_cfg->bit_width = mcfg->bit_width;
872                 mp3_cfg->alignment = PCM_LSB_ALIGNED;
873                 mp3_cfg->bits_per_sample = mcfg->bit_width;
874                 mp3_cfg->q_factor = mcfg->bit_width - 1;
875                 mp3_cfg->endianness = PCM_LITTLE_ENDIAN;
876                 mp3_cfg->num_channels = mcfg->num_channels;
877                 break;
878         case SND_AUDIOCODEC_AAC:
879                 media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED;
880                 media_fmt_hdr->fmt_id = MEDIA_FMT_ID_AAC;
881                 media_fmt_hdr->payload_size = sizeof(struct payload_media_fmt_aac_t);
882                 p = p + sizeof(*media_fmt_hdr);
883                 aac_cfg = p;
884                 aac_cfg->aac_fmt_flag = 0;
885                 aac_cfg->audio_obj_type = 5;
886                 aac_cfg->num_channels = mcfg->num_channels;
887                 aac_cfg->total_size_of_PCE_bits = 0;
888                 aac_cfg->sample_rate = mcfg->sample_rate;
889                 break;
890         case SND_AUDIOCODEC_FLAC:
891                 media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED;
892                 media_fmt_hdr->fmt_id = MEDIA_FMT_ID_FLAC;
893                 media_fmt_hdr->payload_size = sizeof(struct payload_media_fmt_flac_t);
894                 p = p + sizeof(*media_fmt_hdr);
895                 flac_cfg = p;
896                 flac_cfg->sample_size = mcfg->codec.options.flac_d.sample_size;
897                 flac_cfg->num_channels = mcfg->num_channels;
898                 flac_cfg->min_blk_size = mcfg->codec.options.flac_d.min_blk_size;
899                 flac_cfg->max_blk_size = mcfg->codec.options.flac_d.max_blk_size;
900                 flac_cfg->sample_rate = mcfg->sample_rate;
901                 flac_cfg->min_frame_size = mcfg->codec.options.flac_d.min_frame_size;
902                 flac_cfg->max_frame_size = mcfg->codec.options.flac_d.max_frame_size;
903                 break;
904         default:
905                 return -EINVAL;
906         }
907 
908         return 0;
909 }
910 
911 int audioreach_compr_set_param(struct q6apm_graph *graph, struct audioreach_module_config *mcfg)
912 {
913         struct media_format *header;
914         struct gpr_pkt *pkt;
915         int iid, payload_size, rc;
916         void *p;
917 
918         payload_size = sizeof(struct apm_sh_module_media_fmt_cmd);
919 
920         iid = q6apm_graph_get_rx_shmem_module_iid(graph);
921         pkt = audioreach_alloc_cmd_pkt(payload_size, DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT,
922                         0, graph->port->id, iid);
923 
924         if (IS_ERR(pkt))
925                 return -ENOMEM;
926 
927         p = (void *)pkt + GPR_HDR_SIZE;
928         header = p;
929         rc = audioreach_set_compr_media_format(header, p, mcfg);
930         if (rc) {
931                 kfree(pkt);
932                 return rc;
933         }
934 
935         rc = gpr_send_port_pkt(graph->port, pkt);
936         kfree(pkt);
937 
938         return rc;
939 }
940 EXPORT_SYMBOL_GPL(audioreach_compr_set_param);
941 
942 static int audioreach_i2s_set_media_format(struct q6apm_graph *graph,
943                                            struct audioreach_module *module,
944                                            struct audioreach_module_config *cfg)
945 {
946         struct apm_module_frame_size_factor_cfg *fs_cfg;
947         struct apm_module_param_data *param_data;
948         struct apm_i2s_module_intf_cfg *intf_cfg;
949         struct apm_module_hw_ep_mf_cfg *hw_cfg;
950         int ic_sz, ep_sz, fs_sz;
951         int rc, payload_size;
952         struct gpr_pkt *pkt;
953         void *p;
954 
955         ic_sz = APM_I2S_INTF_CFG_PSIZE;
956         ep_sz = APM_HW_EP_CFG_PSIZE;
957         fs_sz = APM_FS_CFG_PSIZE;
958 
959         payload_size = ic_sz + ep_sz + fs_sz;
960 
961         pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
962         if (IS_ERR(pkt))
963                 return PTR_ERR(pkt);
964 
965         p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
966         intf_cfg = p;
967 
968         param_data = &intf_cfg->param_data;
969         param_data->module_instance_id = module->instance_id;
970         param_data->error_code = 0;
971         param_data->param_id = PARAM_ID_I2S_INTF_CFG;
972         param_data->param_size = ic_sz - APM_MODULE_PARAM_DATA_SIZE;
973 
974         intf_cfg->cfg.intf_idx = module->hw_interface_idx;
975         intf_cfg->cfg.sd_line_idx = module->sd_line_idx;
976 
977         switch (cfg->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
978         case SND_SOC_DAIFMT_BP_FP:
979                 intf_cfg->cfg.ws_src = CONFIG_I2S_WS_SRC_INTERNAL;
980                 break;
981         case SND_SOC_DAIFMT_BC_FC:
982                 /* CPU is slave */
983                 intf_cfg->cfg.ws_src = CONFIG_I2S_WS_SRC_EXTERNAL;
984                 break;
985         default:
986                 break;
987         }
988 
989         p += ic_sz;
990         hw_cfg = p;
991         param_data = &hw_cfg->param_data;
992         param_data->module_instance_id = module->instance_id;
993         param_data->error_code = 0;
994         param_data->param_id = PARAM_ID_HW_EP_MF_CFG;
995         param_data->param_size = ep_sz - APM_MODULE_PARAM_DATA_SIZE;
996 
997         hw_cfg->mf.sample_rate = cfg->sample_rate;
998         hw_cfg->mf.bit_width = cfg->bit_width;
999         hw_cfg->mf.num_channels = cfg->num_channels;
1000         hw_cfg->mf.data_format = module->data_format;
1001 
1002         p += ep_sz;
1003         fs_cfg = p;
1004         param_data = &fs_cfg->param_data;
1005         param_data->module_instance_id = module->instance_id;
1006         param_data->error_code = 0;
1007         param_data->param_id = PARAM_ID_HW_EP_FRAME_SIZE_FACTOR;
1008         param_data->param_size = fs_sz - APM_MODULE_PARAM_DATA_SIZE;
1009         fs_cfg->frame_size_factor = 1;
1010 
1011         rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
1012 
1013         kfree(pkt);
1014 
1015         return rc;
1016 }
1017 
1018 static int audioreach_logging_set_media_format(struct q6apm_graph *graph,
1019                                                struct audioreach_module *module)
1020 {
1021         struct apm_module_param_data *param_data;
1022         struct data_logging_config *cfg;
1023         int rc, payload_size;
1024         struct gpr_pkt *pkt;
1025         void *p;
1026 
1027         payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE;
1028         pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
1029         if (IS_ERR(pkt))
1030                 return PTR_ERR(pkt);
1031 
1032         p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
1033 
1034         param_data = p;
1035         param_data->module_instance_id = module->instance_id;
1036         param_data->error_code = 0;
1037         param_data->param_id = PARAM_ID_DATA_LOGGING_CONFIG;
1038         param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
1039 
1040         p = p + APM_MODULE_PARAM_DATA_SIZE;
1041         cfg = p;
1042         cfg->log_code = module->log_code;
1043         cfg->log_tap_point_id = module->log_tap_point_id;
1044         cfg->mode = module->log_mode;
1045 
1046         rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
1047 
1048         kfree(pkt);
1049 
1050         return rc;
1051 }
1052 
1053 static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
1054                                            struct audioreach_module *module,
1055                                            struct audioreach_module_config *mcfg)
1056 {
1057         struct payload_pcm_output_format_cfg *media_cfg;
1058         uint32_t num_channels = mcfg->num_channels;
1059         struct apm_pcm_module_media_fmt_cmd *cfg;
1060         struct apm_module_param_data *param_data;
1061         int rc, payload_size;
1062         struct gpr_pkt *pkt;
1063 
1064         if (num_channels > 4) {
1065                 dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels);
1066                 return -EINVAL;
1067         }
1068 
1069         payload_size = APM_PCM_MODULE_FMT_CMD_PSIZE(num_channels);
1070 
1071         pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
1072         if (IS_ERR(pkt))
1073                 return PTR_ERR(pkt);
1074 
1075         cfg = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
1076 
1077         param_data = &cfg->param_data;
1078         param_data->module_instance_id = module->instance_id;
1079         param_data->error_code = 0;
1080         param_data->param_id = PARAM_ID_PCM_OUTPUT_FORMAT_CFG;
1081         param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
1082 
1083         cfg->header.data_format = DATA_FORMAT_FIXED_POINT;
1084         cfg->header.fmt_id = MEDIA_FMT_ID_PCM;
1085         cfg->header.payload_size = APM_PCM_OUT_FMT_CFG_PSIZE(media_cfg, num_channels);
1086 
1087         media_cfg = &cfg->media_cfg;
1088         media_cfg->alignment = PCM_LSB_ALIGNED;
1089         media_cfg->bit_width = mcfg->bit_width;
1090         media_cfg->endianness = PCM_LITTLE_ENDIAN;
1091         media_cfg->interleaved = module->interleave_type;
1092         media_cfg->num_channels = mcfg->num_channels;
1093         media_cfg->q_factor = mcfg->bit_width - 1;
1094         media_cfg->bits_per_sample = mcfg->bit_width;
1095         memcpy(media_cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels);
1096 
1097         rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
1098 
1099         kfree(pkt);
1100 
1101         return rc;
1102 }
1103 
1104 static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
1105                                              struct audioreach_module *module,
1106                                              struct audioreach_module_config *mcfg)
1107 {
1108         uint32_t num_channels = mcfg->num_channels;
1109         struct apm_module_param_data *param_data;
1110         struct payload_media_fmt_pcm *cfg;
1111         struct media_format *header;
1112         int rc, payload_size;
1113         struct gpr_pkt *pkt;
1114         void *p;
1115 
1116         if (num_channels > 4) {
1117                 dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels);
1118                 return -EINVAL;
1119         }
1120 
1121         payload_size = APM_SHMEM_FMT_CFG_PSIZE(num_channels) + APM_MODULE_PARAM_DATA_SIZE;
1122 
1123         pkt = audioreach_alloc_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0,
1124                                      graph->port->id, module->instance_id);
1125         if (IS_ERR(pkt))
1126                 return PTR_ERR(pkt);
1127 
1128         p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
1129 
1130         param_data = p;
1131         param_data->module_instance_id = module->instance_id;
1132         param_data->error_code = 0;
1133         param_data->param_id = PARAM_ID_MEDIA_FORMAT;
1134         param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
1135         p = p + APM_MODULE_PARAM_DATA_SIZE;
1136 
1137         header = p;
1138         if (mcfg->fmt == SND_AUDIOCODEC_PCM) {
1139                 header->data_format = DATA_FORMAT_FIXED_POINT;
1140                 header->fmt_id =  MEDIA_FMT_ID_PCM;
1141                 header->payload_size = payload_size - sizeof(*header);
1142 
1143                 p = p + sizeof(*header);
1144                 cfg = p;
1145                 cfg->sample_rate = mcfg->sample_rate;
1146                 cfg->bit_width = mcfg->bit_width;
1147                 cfg->alignment = PCM_LSB_ALIGNED;
1148                 cfg->bits_per_sample = mcfg->bit_width;
1149                 cfg->q_factor = mcfg->bit_width - 1;
1150                 cfg->endianness = PCM_LITTLE_ENDIAN;
1151                 cfg->num_channels = mcfg->num_channels;
1152                 memcpy(cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels);
1153         } else {
1154                 rc = audioreach_set_compr_media_format(header, p, mcfg);
1155                 if (rc) {
1156                         kfree(pkt);
1157                         return rc;
1158                 }
1159         }
1160 
1161         rc = audioreach_graph_send_cmd_sync(graph, pkt, 0);
1162 
1163         kfree(pkt);
1164 
1165         return rc;
1166 }
1167 
1168 int audioreach_gain_set_vol_ctrl(struct q6apm *apm, struct audioreach_module *module, int vol)
1169 {
1170         struct param_id_vol_ctrl_master_gain *cfg;
1171         struct apm_module_param_data *param_data;
1172         int rc, payload_size;
1173         struct gpr_pkt *pkt;
1174         void *p;
1175 
1176         payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE;
1177         pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
1178         if (IS_ERR(pkt))
1179                 return PTR_ERR(pkt);
1180 
1181         p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
1182 
1183         param_data = p;
1184         param_data->module_instance_id = module->instance_id;
1185         param_data->error_code = 0;
1186         param_data->param_id = PARAM_ID_VOL_CTRL_MASTER_GAIN;
1187         param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
1188 
1189         p = p + APM_MODULE_PARAM_DATA_SIZE;
1190         cfg = p;
1191         cfg->master_gain =  vol;
1192         rc = q6apm_send_cmd_sync(apm, pkt, 0);
1193 
1194         kfree(pkt);
1195 
1196         return rc;
1197 }
1198 EXPORT_SYMBOL_GPL(audioreach_gain_set_vol_ctrl);
1199 
1200 static int audioreach_gain_set(struct q6apm_graph *graph, struct audioreach_module *module)
1201 {
1202         struct apm_module_param_data *param_data;
1203         struct apm_gain_module_cfg *cfg;
1204         int rc, payload_size;
1205         struct gpr_pkt *pkt;
1206 
1207         payload_size = APM_GAIN_CFG_PSIZE;
1208         pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
1209         if (IS_ERR(pkt))
1210                 return PTR_ERR(pkt);
1211 
1212         cfg = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
1213 
1214         param_data = &cfg->param_data;
1215         param_data->module_instance_id = module->instance_id;
1216         param_data->error_code = 0;
1217         param_data->param_id = APM_PARAM_ID_GAIN;
1218         param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
1219 
1220         cfg->gain_cfg.gain = module->gain;
1221 
1222         rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
1223 
1224         kfree(pkt);
1225 
1226         return rc;
1227 }
1228 
1229 int audioreach_set_media_format(struct q6apm_graph *graph, struct audioreach_module *module,
1230                                 struct audioreach_module_config *cfg)
1231 {
1232         int rc;
1233 
1234         switch (module->module_id) {
1235         case MODULE_ID_DATA_LOGGING:
1236                 rc = audioreach_module_enable(graph, module, true);
1237                 if (!rc)
1238                         rc = audioreach_logging_set_media_format(graph, module);
1239                 break;
1240         case MODULE_ID_PCM_DEC:
1241         case MODULE_ID_PCM_ENC:
1242         case MODULE_ID_PCM_CNV:
1243         case MODULE_ID_PLACEHOLDER_DECODER:
1244         case MODULE_ID_PLACEHOLDER_ENCODER:
1245                 rc = audioreach_pcm_set_media_format(graph, module, cfg);
1246                 break;
1247         case MODULE_ID_DISPLAY_PORT_SINK:
1248                 rc = audioreach_display_port_set_media_format(graph, module, cfg);
1249                 break;
1250         case MODULE_ID_I2S_SOURCE:
1251         case MODULE_ID_I2S_SINK:
1252                 rc = audioreach_i2s_set_media_format(graph, module, cfg);
1253                 break;
1254         case MODULE_ID_WR_SHARED_MEM_EP:
1255                 rc = audioreach_shmem_set_media_format(graph, module, cfg);
1256                 break;
1257         case MODULE_ID_GAIN:
1258                 rc = audioreach_gain_set(graph, module);
1259                 break;
1260         case MODULE_ID_CODEC_DMA_SINK:
1261         case MODULE_ID_CODEC_DMA_SOURCE:
1262                 rc = audioreach_codec_dma_set_media_format(graph, module, cfg);
1263                 break;
1264         case MODULE_ID_SAL:
1265                 rc = audioreach_sal_set_media_format(graph, module, cfg);
1266                 if (!rc)
1267                         rc = audioreach_sal_limiter_enable(graph, module, true);
1268                 break;
1269         case MODULE_ID_MFC:
1270                 rc = audioreach_mfc_set_media_format(graph, module, cfg);
1271                 break;
1272         case MODULE_ID_GAPLESS:
1273                 rc = audioreach_gapless_set_media_format(graph, module, cfg);
1274                 break;
1275         default:
1276                 rc = 0;
1277         }
1278 
1279         return rc;
1280 }
1281 EXPORT_SYMBOL_GPL(audioreach_set_media_format);
1282 
1283 void audioreach_graph_free_buf(struct q6apm_graph *graph)
1284 {
1285         struct audioreach_graph_data *port;
1286 
1287         mutex_lock(&graph->lock);
1288         port = &graph->rx_data;
1289         port->num_periods = 0;
1290         kfree(port->buf);
1291         port->buf = NULL;
1292 
1293         port = &graph->tx_data;
1294         port->num_periods = 0;
1295         kfree(port->buf);
1296         port->buf = NULL;
1297         mutex_unlock(&graph->lock);
1298 }
1299 EXPORT_SYMBOL_GPL(audioreach_graph_free_buf);
1300 
1301 int audioreach_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, size_t period_sz,
1302                                   unsigned int periods, bool is_contiguous)
1303 {
1304         struct apm_shared_map_region_payload *mregions;
1305         struct apm_cmd_shared_mem_map_regions *cmd;
1306         uint32_t num_regions, buf_sz, payload_size;
1307         struct audioreach_graph_data *data;
1308         struct gpr_pkt *pkt;
1309         void *p;
1310         int rc, i;
1311 
1312         if (dir == SNDRV_PCM_STREAM_PLAYBACK)
1313                 data = &graph->rx_data;
1314         else
1315                 data = &graph->tx_data;
1316 
1317         if (is_contiguous) {
1318                 num_regions = 1;
1319                 buf_sz = period_sz * periods;
1320         } else {
1321                 buf_sz = period_sz;
1322                 num_regions = periods;
1323         }
1324 
1325         /* DSP expects size should be aligned to 4K */
1326         buf_sz = ALIGN(buf_sz, 4096);
1327 
1328         payload_size = sizeof(*cmd) + (sizeof(*mregions) * num_regions);
1329 
1330         pkt = audioreach_alloc_apm_pkt(payload_size, APM_CMD_SHARED_MEM_MAP_REGIONS, dir,
1331                                      graph->port->id);
1332         if (IS_ERR(pkt))
1333                 return PTR_ERR(pkt);
1334 
1335         p = (void *)pkt + GPR_HDR_SIZE;
1336         cmd = p;
1337         cmd->mem_pool_id = APM_MEMORY_MAP_SHMEM8_4K_POOL;
1338         cmd->num_regions = num_regions;
1339 
1340         cmd->property_flag = 0x0;
1341 
1342         mregions = p + sizeof(*cmd);
1343 
1344         mutex_lock(&graph->lock);
1345 
1346         for (i = 0; i < num_regions; i++) {
1347                 struct audio_buffer *ab;
1348 
1349                 ab = &data->buf[i];
1350                 mregions->shm_addr_lsw = lower_32_bits(ab->phys);
1351                 mregions->shm_addr_msw = upper_32_bits(ab->phys);
1352                 mregions->mem_size_bytes = buf_sz;
1353                 ++mregions;
1354         }
1355         mutex_unlock(&graph->lock);
1356 
1357         rc = audioreach_graph_send_cmd_sync(graph, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS);
1358 
1359         kfree(pkt);
1360 
1361         return rc;
1362 }
1363 EXPORT_SYMBOL_GPL(audioreach_map_memory_regions);
1364 
1365 int audioreach_shared_memory_send_eos(struct q6apm_graph *graph)
1366 {
1367         struct data_cmd_wr_sh_mem_ep_eos *eos;
1368         struct gpr_pkt *pkt;
1369         int rc = 0, iid;
1370 
1371         iid = q6apm_graph_get_rx_shmem_module_iid(graph);
1372         pkt = audioreach_alloc_cmd_pkt(sizeof(*eos), DATA_CMD_WR_SH_MEM_EP_EOS, 0,
1373                                        graph->port->id, iid);
1374         if (IS_ERR(pkt))
1375                 return PTR_ERR(pkt);
1376 
1377         eos = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
1378 
1379         eos->policy = WR_SH_MEM_EP_EOS_POLICY_LAST;
1380 
1381         rc = gpr_send_port_pkt(graph->port, pkt);
1382         kfree(pkt);
1383 
1384         return rc;
1385 }
1386 EXPORT_SYMBOL_GPL(audioreach_shared_memory_send_eos);
1387 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php