cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

audioreach.c (32672B)


      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 */
     16struct 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
     29struct 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 */
     38struct 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
     58struct 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 */
     67struct 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
     77struct 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 */
     86struct 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
     93struct 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 */
    103struct 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
    112struct 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
    121struct 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
    127struct 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
    132struct 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
    148struct 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
    155struct 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
    162struct apm_module_frame_size_factor_cfg {
    163	struct apm_module_param_data param_data;
    164	uint32_t frame_size_factor;
    165} __packed;
    166
    167#define APM_FS_CFG_PSIZE ALIGN(sizeof(struct apm_module_frame_size_factor_cfg), 8)
    168
    169struct apm_module_hw_ep_power_mode_cfg {
    170	struct apm_module_param_data param_data;
    171	struct param_id_hw_ep_power_mode_cfg power_mode;
    172} __packed;
    173
    174#define APM_HW_EP_PMODE_CFG_PSIZE ALIGN(sizeof(struct apm_module_hw_ep_power_mode_cfg),	8)
    175
    176struct apm_module_hw_ep_dma_data_align_cfg {
    177	struct apm_module_param_data param_data;
    178	struct param_id_hw_ep_dma_data_align align;
    179} __packed;
    180
    181#define APM_HW_EP_DALIGN_CFG_PSIZE ALIGN(sizeof(struct apm_module_hw_ep_dma_data_align_cfg), 8)
    182
    183struct apm_gain_module_cfg {
    184	struct apm_module_param_data param_data;
    185	struct param_id_gain_cfg gain_cfg;
    186} __packed;
    187
    188#define APM_GAIN_CFG_PSIZE ALIGN(sizeof(struct apm_gain_module_cfg), 8)
    189
    190struct apm_codec_dma_module_intf_cfg {
    191	struct apm_module_param_data param_data;
    192	struct param_id_codec_dma_intf_cfg cfg;
    193} __packed;
    194
    195#define APM_CDMA_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_codec_dma_module_intf_cfg), 8)
    196
    197static void *__audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token,
    198				    uint32_t src_port, uint32_t dest_port, bool has_cmd_hdr)
    199{
    200	struct gpr_pkt *pkt;
    201	void *p;
    202	int pkt_size = GPR_HDR_SIZE + payload_size;
    203
    204	if (has_cmd_hdr)
    205		pkt_size += APM_CMD_HDR_SIZE;
    206
    207	p = kzalloc(pkt_size, GFP_KERNEL);
    208	if (!p)
    209		return ERR_PTR(-ENOMEM);
    210
    211	pkt = p;
    212	pkt->hdr.version = GPR_PKT_VER;
    213	pkt->hdr.hdr_size = GPR_PKT_HEADER_WORD_SIZE;
    214	pkt->hdr.pkt_size = pkt_size;
    215	pkt->hdr.dest_port = dest_port;
    216	pkt->hdr.src_port = src_port;
    217
    218	pkt->hdr.dest_domain = GPR_DOMAIN_ID_ADSP;
    219	pkt->hdr.src_domain = GPR_DOMAIN_ID_APPS;
    220	pkt->hdr.token = token;
    221	pkt->hdr.opcode = opcode;
    222
    223	if (has_cmd_hdr) {
    224		struct apm_cmd_header *cmd_header;
    225
    226		p = p + GPR_HDR_SIZE;
    227		cmd_header = p;
    228		cmd_header->payload_size = payload_size;
    229	}
    230
    231	return pkt;
    232}
    233
    234void *audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token,
    235			   uint32_t src_port, uint32_t dest_port)
    236{
    237	return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, false);
    238}
    239EXPORT_SYMBOL_GPL(audioreach_alloc_pkt);
    240
    241void *audioreach_alloc_apm_pkt(int pkt_size, uint32_t opcode, uint32_t token, uint32_t src_port)
    242{
    243	return __audioreach_alloc_pkt(pkt_size, opcode, token, src_port, APM_MODULE_INSTANCE_ID,
    244				      false);
    245}
    246EXPORT_SYMBOL_GPL(audioreach_alloc_apm_pkt);
    247
    248void *audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode, uint32_t token,
    249			       uint32_t src_port, uint32_t dest_port)
    250{
    251	return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, true);
    252}
    253EXPORT_SYMBOL_GPL(audioreach_alloc_cmd_pkt);
    254
    255void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t token)
    256{
    257	return __audioreach_alloc_pkt(pkt_size, opcode, token, GPR_APM_MODULE_IID,
    258				       APM_MODULE_INSTANCE_ID, true);
    259}
    260EXPORT_SYMBOL_GPL(audioreach_alloc_apm_cmd_pkt);
    261
    262static void apm_populate_container_config(struct apm_container_obj *cfg,
    263					  struct audioreach_container *cont)
    264{
    265
    266	/* Container Config */
    267	cfg->container_cfg.container_id = cont->container_id;
    268	cfg->container_cfg.num_prop = 4;
    269
    270	/* Capability list */
    271	cfg->cap_data.prop_id = APM_CONTAINER_PROP_ID_CAPABILITY_LIST;
    272	cfg->cap_data.prop_size = APM_CONTAINER_PROP_ID_CAPABILITY_SIZE;
    273	cfg->num_capability_id = 1;
    274	cfg->capability_id = cont->capability_id;
    275
    276	/* Graph Position */
    277	cfg->pos_data.prop_id = APM_CONTAINER_PROP_ID_GRAPH_POS;
    278	cfg->pos_data.prop_size = sizeof(struct apm_cont_prop_id_graph_pos);
    279	cfg->pos.graph_pos = cont->graph_pos;
    280
    281	/* Stack size */
    282	cfg->stack_data.prop_id = APM_CONTAINER_PROP_ID_STACK_SIZE;
    283	cfg->stack_data.prop_size = sizeof(struct apm_cont_prop_id_stack_size);
    284	cfg->stack.stack_size = cont->stack_size;
    285
    286	/* Proc domain */
    287	cfg->domain_data.prop_id = APM_CONTAINER_PROP_ID_PROC_DOMAIN;
    288	cfg->domain_data.prop_size = sizeof(struct apm_cont_prop_id_domain);
    289	cfg->domain.proc_domain = cont->proc_domain;
    290}
    291
    292static void apm_populate_sub_graph_config(struct apm_sub_graph_data *cfg,
    293					  struct audioreach_sub_graph *sg)
    294{
    295	cfg->sub_graph_cfg.sub_graph_id = sg->sub_graph_id;
    296	cfg->sub_graph_cfg.num_sub_graph_prop = APM_SUB_GRAPH_CFG_NPROP;
    297
    298	/* Perf Mode */
    299	cfg->perf_data.prop_id = APM_SUB_GRAPH_PROP_ID_PERF_MODE;
    300	cfg->perf_data.prop_size = APM_SG_PROP_ID_PERF_MODE_SIZE;
    301	cfg->perf.perf_mode = sg->perf_mode;
    302
    303	/* Direction */
    304	cfg->dir_data.prop_id = APM_SUB_GRAPH_PROP_ID_DIRECTION;
    305	cfg->dir_data.prop_size = APM_SG_PROP_ID_DIR_SIZE;
    306	cfg->dir.direction = sg->direction;
    307
    308	/* Scenario ID */
    309	cfg->sid_data.prop_id = APM_SUB_GRAPH_PROP_ID_SCENARIO_ID;
    310	cfg->sid_data.prop_size = APM_SG_PROP_ID_SID_SIZE;
    311	cfg->sid.scenario_id = sg->scenario_id;
    312}
    313
    314static void apm_populate_connection_obj(struct apm_module_conn_obj *obj,
    315					struct audioreach_module *module)
    316{
    317	obj->src_mod_inst_id = module->src_mod_inst_id;
    318	obj->src_mod_op_port_id = module->src_mod_op_port_id;
    319	obj->dst_mod_inst_id = module->instance_id;
    320	obj->dst_mod_ip_port_id = module->in_port;
    321}
    322
    323static void apm_populate_module_prop_obj(struct apm_mod_prop_obj *obj,
    324					 struct audioreach_module *module)
    325{
    326
    327	obj->instance_id = module->instance_id;
    328	obj->num_props = 1;
    329	obj->prop_data_1.prop_id = APM_MODULE_PROP_ID_PORT_INFO;
    330	obj->prop_data_1.prop_size = APM_MODULE_PROP_ID_PORT_INFO_SZ;
    331	obj->prop_id_port.max_ip_port = module->max_ip_port;
    332	obj->prop_id_port.max_op_port = module->max_op_port;
    333}
    334
    335struct audioreach_module *audioreach_get_container_last_module(
    336							struct audioreach_container *container)
    337{
    338	struct audioreach_module *module;
    339
    340	list_for_each_entry(module, &container->modules_list, node) {
    341		if (module->dst_mod_inst_id == 0)
    342			return module;
    343	}
    344
    345	return NULL;
    346}
    347EXPORT_SYMBOL_GPL(audioreach_get_container_last_module);
    348
    349static bool is_module_in_container(struct audioreach_container *container, int module_iid)
    350{
    351	struct audioreach_module *module;
    352
    353	list_for_each_entry(module, &container->modules_list, node) {
    354		if (module->instance_id == module_iid)
    355			return true;
    356	}
    357
    358	return false;
    359}
    360
    361struct audioreach_module *audioreach_get_container_first_module(
    362							struct audioreach_container *container)
    363{
    364	struct audioreach_module *module;
    365
    366	/* get the first module from both connected or un-connected containers */
    367	list_for_each_entry(module, &container->modules_list, node) {
    368		if (module->src_mod_inst_id == 0 ||
    369		    !is_module_in_container(container, module->src_mod_inst_id))
    370			return module;
    371	}
    372	return NULL;
    373}
    374EXPORT_SYMBOL_GPL(audioreach_get_container_first_module);
    375
    376struct audioreach_module *audioreach_get_container_next_module(
    377						struct audioreach_container *container,
    378						struct audioreach_module *module)
    379{
    380	int nmodule_iid = module->dst_mod_inst_id;
    381	struct audioreach_module *nmodule;
    382
    383	list_for_each_entry(nmodule, &container->modules_list, node) {
    384		if (nmodule->instance_id == nmodule_iid)
    385			return nmodule;
    386	}
    387
    388	return NULL;
    389}
    390EXPORT_SYMBOL_GPL(audioreach_get_container_next_module);
    391
    392static void apm_populate_module_list_obj(struct apm_mod_list_obj *obj,
    393					 struct audioreach_container *container,
    394					 int sub_graph_id)
    395{
    396	struct audioreach_module *module;
    397	int i;
    398
    399	obj->sub_graph_id = sub_graph_id;
    400	obj->container_id = container->container_id;
    401	obj->num_modules = container->num_modules;
    402	i = 0;
    403	list_for_each_container_module(module, container) {
    404		obj->mod_cfg[i].module_id = module->module_id;
    405		obj->mod_cfg[i].instance_id = module->instance_id;
    406		i++;
    407	}
    408}
    409
    410static void audioreach_populate_graph(struct apm_graph_open_params *open,
    411				      struct list_head *sg_list,
    412				      int num_sub_graphs)
    413{
    414	struct apm_mod_conn_list_params *mc_data = open->mod_conn_list_data;
    415	struct apm_module_list_params *ml_data = open->mod_list_data;
    416	struct apm_prop_list_params *mp_data = open->mod_prop_data;
    417	struct apm_container_params *c_data = open->cont_data;
    418	struct apm_sub_graph_params *sg_data = open->sg_data;
    419	int ncontainer = 0, nmodule = 0, nconn = 0;
    420	struct apm_mod_prop_obj *module_prop_obj;
    421	struct audioreach_container *container;
    422	struct apm_module_conn_obj *conn_obj;
    423	struct audioreach_module *module;
    424	struct audioreach_sub_graph *sg;
    425	struct apm_container_obj *cobj;
    426	struct apm_mod_list_obj *mlobj;
    427	int i = 0;
    428
    429	mlobj = &ml_data->mod_list_obj[0];
    430
    431	list_for_each_entry(sg, sg_list, node) {
    432		struct apm_sub_graph_data *sg_cfg = &sg_data->sg_cfg[i++];
    433
    434		apm_populate_sub_graph_config(sg_cfg, sg);
    435
    436		list_for_each_entry(container, &sg->container_list, node) {
    437			cobj = &c_data->cont_obj[ncontainer];
    438
    439			apm_populate_container_config(cobj, container);
    440			apm_populate_module_list_obj(mlobj, container, sg->sub_graph_id);
    441
    442			list_for_each_container_module(module, container) {
    443				uint32_t src_mod_inst_id;
    444
    445				src_mod_inst_id = module->src_mod_inst_id;
    446
    447				module_prop_obj = &mp_data->mod_prop_obj[nmodule];
    448				apm_populate_module_prop_obj(module_prop_obj, module);
    449
    450				if (src_mod_inst_id) {
    451					conn_obj = &mc_data->conn_obj[nconn];
    452					apm_populate_connection_obj(conn_obj, module);
    453					nconn++;
    454				}
    455
    456				nmodule++;
    457			}
    458			mlobj = (void *) mlobj + APM_MOD_LIST_OBJ_PSIZE(mlobj, container->num_modules);
    459
    460			ncontainer++;
    461		}
    462	}
    463}
    464
    465void *audioreach_alloc_graph_pkt(struct q6apm *apm, struct list_head *sg_list, int graph_id)
    466{
    467	int payload_size, sg_sz, cont_sz, ml_sz, mp_sz, mc_sz;
    468	struct apm_module_param_data  *param_data;
    469	struct apm_container_params *cont_params;
    470	struct audioreach_container *container;
    471	struct apm_sub_graph_params *sg_params;
    472	struct apm_mod_conn_list_params *mcon;
    473	struct apm_graph_open_params params;
    474	struct apm_prop_list_params *mprop;
    475	struct audioreach_module *module;
    476	struct audioreach_sub_graph *sgs;
    477	struct apm_mod_list_obj *mlobj;
    478	int num_modules_per_list;
    479	int num_connections = 0;
    480	int num_containers = 0;
    481	int num_sub_graphs = 0;
    482	int num_modules = 0;
    483	int num_modules_list;
    484	struct gpr_pkt *pkt;
    485	void *p;
    486
    487	list_for_each_entry(sgs, sg_list, node) {
    488		num_sub_graphs++;
    489		list_for_each_entry(container, &sgs->container_list, node) {
    490			num_containers++;
    491			num_modules += container->num_modules;
    492			list_for_each_container_module(module, container) {
    493				if (module->src_mod_inst_id)
    494					num_connections++;
    495			}
    496		}
    497	}
    498
    499	num_modules_list = num_containers;
    500	num_modules_per_list = num_modules/num_containers;
    501	sg_sz = APM_SUB_GRAPH_PSIZE(sg_params, num_sub_graphs);
    502	cont_sz = APM_CONTAINER_PSIZE(cont_params, num_containers);
    503	ml_sz =	ALIGN(sizeof(struct apm_module_list_params) +
    504		num_modules_list * APM_MOD_LIST_OBJ_PSIZE(mlobj,  num_modules_per_list), 8);
    505	mp_sz = APM_MOD_PROP_PSIZE(mprop, num_modules);
    506	mc_sz =	APM_MOD_CONN_PSIZE(mcon, num_connections);
    507
    508	payload_size = sg_sz + cont_sz + ml_sz + mp_sz + mc_sz;
    509	pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_GRAPH_OPEN, 0);
    510	if (IS_ERR(pkt))
    511		return pkt;
    512
    513	p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
    514
    515	/* SubGraph */
    516	params.sg_data = p;
    517	param_data = &params.sg_data->param_data;
    518	param_data->module_instance_id = APM_MODULE_INSTANCE_ID;
    519	param_data->param_id = APM_PARAM_ID_SUB_GRAPH_CONFIG;
    520	param_data->param_size = sg_sz - APM_MODULE_PARAM_DATA_SIZE;
    521	params.sg_data->num_sub_graphs = num_sub_graphs;
    522	p += sg_sz;
    523
    524	/* Container */
    525	params.cont_data = p;
    526	param_data = &params.cont_data->param_data;
    527	param_data->module_instance_id = APM_MODULE_INSTANCE_ID;
    528	param_data->param_id = APM_PARAM_ID_CONTAINER_CONFIG;
    529	param_data->param_size = cont_sz - APM_MODULE_PARAM_DATA_SIZE;
    530	params.cont_data->num_containers = num_containers;
    531	p += cont_sz;
    532
    533	/* Module List*/
    534	params.mod_list_data = p;
    535	param_data = &params.mod_list_data->param_data;
    536	param_data->module_instance_id = APM_MODULE_INSTANCE_ID;
    537	param_data->param_id = APM_PARAM_ID_MODULE_LIST;
    538	param_data->param_size = ml_sz - APM_MODULE_PARAM_DATA_SIZE;
    539	params.mod_list_data->num_modules_list = num_sub_graphs;
    540	p += ml_sz;
    541
    542	/* Module Properties */
    543	params.mod_prop_data = p;
    544	param_data = &params.mod_prop_data->param_data;
    545	param_data->module_instance_id = APM_MODULE_INSTANCE_ID;
    546	param_data->param_id = APM_PARAM_ID_MODULE_PROP;
    547	param_data->param_size = mp_sz - APM_MODULE_PARAM_DATA_SIZE;
    548	params.mod_prop_data->num_modules_prop_cfg = num_modules;
    549	p += mp_sz;
    550
    551	/* Module Connections */
    552	params.mod_conn_list_data = p;
    553	param_data = &params.mod_conn_list_data->param_data;
    554	param_data->module_instance_id = APM_MODULE_INSTANCE_ID;
    555	param_data->param_id = APM_PARAM_ID_MODULE_CONN;
    556	param_data->param_size = mc_sz - APM_MODULE_PARAM_DATA_SIZE;
    557	params.mod_conn_list_data->num_connections = num_connections;
    558	p += mc_sz;
    559
    560	audioreach_populate_graph(&params, sg_list, num_sub_graphs);
    561
    562	return pkt;
    563}
    564EXPORT_SYMBOL_GPL(audioreach_alloc_graph_pkt);
    565
    566int audioreach_send_cmd_sync(struct device *dev, gpr_device_t *gdev,
    567			     struct gpr_ibasic_rsp_result_t *result, struct mutex *cmd_lock,
    568			     gpr_port_t *port, wait_queue_head_t *cmd_wait,
    569			     struct gpr_pkt *pkt, uint32_t rsp_opcode)
    570{
    571
    572	struct gpr_hdr *hdr = &pkt->hdr;
    573	int rc;
    574
    575	mutex_lock(cmd_lock);
    576	result->opcode = 0;
    577	result->status = 0;
    578
    579	if (port)
    580		rc = gpr_send_port_pkt(port, pkt);
    581	else if (gdev)
    582		rc = gpr_send_pkt(gdev, pkt);
    583	else
    584		rc = -EINVAL;
    585
    586	if (rc < 0)
    587		goto err;
    588
    589	if (rsp_opcode)
    590		rc = wait_event_timeout(*cmd_wait, (result->opcode == hdr->opcode) ||
    591					(result->opcode == rsp_opcode),	5 * HZ);
    592	else
    593		rc = wait_event_timeout(*cmd_wait, (result->opcode == hdr->opcode), 5 * HZ);
    594
    595	if (!rc) {
    596		dev_err(dev, "CMD timeout for [%x] opcode\n", hdr->opcode);
    597		rc = -ETIMEDOUT;
    598	} else if (result->status > 0) {
    599		dev_err(dev, "DSP returned error[%x] %x\n", hdr->opcode, result->status);
    600		rc = -EINVAL;
    601	} else {
    602		/* DSP successfully finished the command */
    603		rc = 0;
    604	}
    605
    606err:
    607	mutex_unlock(cmd_lock);
    608	return rc;
    609}
    610EXPORT_SYMBOL_GPL(audioreach_send_cmd_sync);
    611
    612int audioreach_graph_send_cmd_sync(struct q6apm_graph *graph, struct gpr_pkt *pkt,
    613				   uint32_t rsp_opcode)
    614{
    615
    616	return audioreach_send_cmd_sync(graph->dev, NULL,  &graph->result, &graph->lock,
    617					graph->port, &graph->cmd_wait, pkt, rsp_opcode);
    618}
    619EXPORT_SYMBOL_GPL(audioreach_graph_send_cmd_sync);
    620
    621/* LPASS Codec DMA port Module Media Format Setup */
    622static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
    623						 struct audioreach_module *module,
    624						 struct audioreach_module_config *cfg)
    625{
    626	struct apm_codec_dma_module_intf_cfg *intf_cfg;
    627	struct apm_module_frame_size_factor_cfg *fs_cfg;
    628	struct apm_module_hw_ep_power_mode_cfg *pm_cfg;
    629	struct apm_module_param_data *param_data;
    630	struct apm_module_hw_ep_mf_cfg *hw_cfg;
    631	int ic_sz, ep_sz, fs_sz, pm_sz, dl_sz;
    632	int rc, payload_size;
    633	struct gpr_pkt *pkt;
    634	void *p;
    635
    636	ic_sz = APM_CDMA_INTF_CFG_PSIZE;
    637	ep_sz = APM_HW_EP_CFG_PSIZE;
    638	fs_sz = APM_FS_CFG_PSIZE;
    639	pm_sz = APM_HW_EP_PMODE_CFG_PSIZE;
    640	dl_sz = 0;
    641
    642	payload_size = ic_sz + ep_sz + fs_sz + pm_sz + dl_sz;
    643
    644	pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
    645	if (IS_ERR(pkt))
    646		return PTR_ERR(pkt);
    647
    648	p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
    649
    650	hw_cfg = p;
    651	param_data = &hw_cfg->param_data;
    652	param_data->module_instance_id = module->instance_id;
    653	param_data->error_code = 0;
    654	param_data->param_id = PARAM_ID_HW_EP_MF_CFG;
    655	param_data->param_size = ep_sz - APM_MODULE_PARAM_DATA_SIZE;
    656
    657	hw_cfg->mf.sample_rate = cfg->sample_rate;
    658	hw_cfg->mf.bit_width = cfg->bit_width;
    659	hw_cfg->mf.num_channels = cfg->num_channels;
    660	hw_cfg->mf.data_format = module->data_format;
    661	p += ep_sz;
    662
    663	fs_cfg = p;
    664	param_data = &fs_cfg->param_data;
    665	param_data->module_instance_id = module->instance_id;
    666	param_data->error_code = 0;
    667	param_data->param_id = PARAM_ID_HW_EP_FRAME_SIZE_FACTOR;
    668	param_data->param_size = fs_sz - APM_MODULE_PARAM_DATA_SIZE;
    669	fs_cfg->frame_size_factor = 1;
    670	p += fs_sz;
    671
    672	intf_cfg = p;
    673	param_data = &intf_cfg->param_data;
    674	param_data->module_instance_id = module->instance_id;
    675	param_data->error_code = 0;
    676	param_data->param_id = PARAM_ID_CODEC_DMA_INTF_CFG;
    677	param_data->param_size = ic_sz - APM_MODULE_PARAM_DATA_SIZE;
    678
    679	intf_cfg->cfg.lpaif_type = module->hw_interface_type;
    680	intf_cfg->cfg.intf_index = module->hw_interface_idx;
    681	intf_cfg->cfg.active_channels_mask = (1 << cfg->num_channels) - 1;
    682	p += ic_sz;
    683
    684	pm_cfg = p;
    685	param_data = &pm_cfg->param_data;
    686	param_data->module_instance_id = module->instance_id;
    687	param_data->error_code = 0;
    688	param_data->param_id = PARAM_ID_HW_EP_POWER_MODE_CFG;
    689	param_data->param_size = pm_sz - APM_MODULE_PARAM_DATA_SIZE;
    690	pm_cfg->power_mode.power_mode = 0;
    691
    692	rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
    693
    694	kfree(pkt);
    695
    696	return rc;
    697}
    698
    699static int audioreach_i2s_set_media_format(struct q6apm_graph *graph,
    700					   struct audioreach_module *module,
    701					   struct audioreach_module_config *cfg)
    702{
    703	struct apm_module_frame_size_factor_cfg *fs_cfg;
    704	struct apm_module_param_data *param_data;
    705	struct apm_i2s_module_intf_cfg *intf_cfg;
    706	struct apm_module_hw_ep_mf_cfg *hw_cfg;
    707	int ic_sz, ep_sz, fs_sz;
    708	int rc, payload_size;
    709	struct gpr_pkt *pkt;
    710	void *p;
    711
    712	ic_sz = APM_I2S_INTF_CFG_PSIZE;
    713	ep_sz = APM_HW_EP_CFG_PSIZE;
    714	fs_sz = APM_FS_CFG_PSIZE;
    715
    716	payload_size = ic_sz + ep_sz + fs_sz;
    717
    718	pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
    719	if (IS_ERR(pkt))
    720		return PTR_ERR(pkt);
    721
    722	p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
    723	intf_cfg = p;
    724
    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_I2S_INTF_CFG;
    729	param_data->param_size = ic_sz - APM_MODULE_PARAM_DATA_SIZE;
    730
    731	intf_cfg->cfg.intf_idx = module->hw_interface_idx;
    732	intf_cfg->cfg.sd_line_idx = module->sd_line_idx;
    733
    734	switch (cfg->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
    735	case SND_SOC_DAIFMT_CBC_CFC:
    736		intf_cfg->cfg.ws_src = CONFIG_I2S_WS_SRC_INTERNAL;
    737		break;
    738	case SND_SOC_DAIFMT_CBP_CFP:
    739		/* CPU is slave */
    740		intf_cfg->cfg.ws_src = CONFIG_I2S_WS_SRC_EXTERNAL;
    741		break;
    742	default:
    743		break;
    744	}
    745
    746	p += ic_sz;
    747	hw_cfg = p;
    748	param_data = &hw_cfg->param_data;
    749	param_data->module_instance_id = module->instance_id;
    750	param_data->error_code = 0;
    751	param_data->param_id = PARAM_ID_HW_EP_MF_CFG;
    752	param_data->param_size = ep_sz - APM_MODULE_PARAM_DATA_SIZE;
    753
    754	hw_cfg->mf.sample_rate = cfg->sample_rate;
    755	hw_cfg->mf.bit_width = cfg->bit_width;
    756	hw_cfg->mf.num_channels = cfg->num_channels;
    757	hw_cfg->mf.data_format = module->data_format;
    758
    759	p += ep_sz;
    760	fs_cfg = p;
    761	param_data = &fs_cfg->param_data;
    762	param_data->module_instance_id = module->instance_id;
    763	param_data->error_code = 0;
    764	param_data->param_id = PARAM_ID_HW_EP_FRAME_SIZE_FACTOR;
    765	param_data->param_size = fs_sz - APM_MODULE_PARAM_DATA_SIZE;
    766	fs_cfg->frame_size_factor = 1;
    767
    768	rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
    769
    770	kfree(pkt);
    771
    772	return rc;
    773}
    774
    775static int audioreach_logging_set_media_format(struct q6apm_graph *graph,
    776					       struct audioreach_module *module)
    777{
    778	struct apm_module_param_data *param_data;
    779	struct data_logging_config *cfg;
    780	int rc, payload_size;
    781	struct gpr_pkt *pkt;
    782	void *p;
    783
    784	payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE;
    785	pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
    786	if (IS_ERR(pkt))
    787		return PTR_ERR(pkt);
    788
    789	p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
    790
    791	param_data = p;
    792	param_data->module_instance_id = module->instance_id;
    793	param_data->error_code = 0;
    794	param_data->param_id = PARAM_ID_DATA_LOGGING_CONFIG;
    795	param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
    796
    797	p = p + APM_MODULE_PARAM_DATA_SIZE;
    798	cfg = p;
    799	cfg->log_code = module->log_code;
    800	cfg->log_tap_point_id = module->log_tap_point_id;
    801	cfg->mode = module->log_mode;
    802
    803	rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
    804
    805	kfree(pkt);
    806
    807	return rc;
    808}
    809
    810static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
    811					   struct audioreach_module *module,
    812					   struct audioreach_module_config *mcfg)
    813{
    814	struct payload_pcm_output_format_cfg *media_cfg;
    815	uint32_t num_channels = mcfg->num_channels;
    816	struct apm_pcm_module_media_fmt_cmd *cfg;
    817	struct apm_module_param_data *param_data;
    818	int rc, payload_size;
    819	struct gpr_pkt *pkt;
    820
    821	if (num_channels > 2) {
    822		dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels);
    823		return -EINVAL;
    824	}
    825
    826	payload_size = APM_PCM_MODULE_FMT_CMD_PSIZE(num_channels);
    827
    828	pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
    829	if (IS_ERR(pkt))
    830		return PTR_ERR(pkt);
    831
    832	cfg = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
    833
    834	param_data = &cfg->param_data;
    835	param_data->module_instance_id = module->instance_id;
    836	param_data->error_code = 0;
    837	param_data->param_id = PARAM_ID_PCM_OUTPUT_FORMAT_CFG;
    838	param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
    839
    840	cfg->header.data_format = DATA_FORMAT_FIXED_POINT;
    841	cfg->header.fmt_id = MEDIA_FMT_ID_PCM;
    842	cfg->header.payload_size = APM_PCM_OUT_FMT_CFG_PSIZE(media_cfg, num_channels);
    843
    844	media_cfg = &cfg->media_cfg;
    845	media_cfg->alignment = PCM_LSB_ALIGNED;
    846	media_cfg->bit_width = mcfg->bit_width;
    847	media_cfg->endianness = PCM_LITTLE_ENDIAN;
    848	media_cfg->interleaved = module->interleave_type;
    849	media_cfg->num_channels = mcfg->num_channels;
    850	media_cfg->q_factor = mcfg->bit_width - 1;
    851	media_cfg->bits_per_sample = mcfg->bit_width;
    852
    853	if (num_channels == 1) {
    854		media_cfg->channel_mapping[0] = PCM_CHANNEL_L;
    855	} else if (num_channels == 2) {
    856		media_cfg->channel_mapping[0] = PCM_CHANNEL_L;
    857		media_cfg->channel_mapping[1] = PCM_CHANNEL_R;
    858
    859	}
    860
    861	rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
    862
    863	kfree(pkt);
    864
    865	return rc;
    866}
    867
    868static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
    869					     struct audioreach_module *module,
    870					     struct audioreach_module_config *mcfg)
    871{
    872	uint32_t num_channels = mcfg->num_channels;
    873	struct apm_module_param_data *param_data;
    874	struct payload_media_fmt_pcm *cfg;
    875	struct media_format *header;
    876	int rc, payload_size;
    877	struct gpr_pkt *pkt;
    878	void *p;
    879
    880	if (num_channels > 2) {
    881		dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels);
    882		return -EINVAL;
    883	}
    884
    885	payload_size = APM_SHMEM_FMT_CFG_PSIZE(num_channels) + APM_MODULE_PARAM_DATA_SIZE;
    886
    887	pkt = audioreach_alloc_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0,
    888				     graph->port->id, module->instance_id);
    889	if (IS_ERR(pkt))
    890		return PTR_ERR(pkt);
    891
    892	p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
    893
    894	param_data = p;
    895	param_data->module_instance_id = module->instance_id;
    896	param_data->error_code = 0;
    897	param_data->param_id = PARAM_ID_MEDIA_FORMAT;
    898	param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
    899	p = p + APM_MODULE_PARAM_DATA_SIZE;
    900
    901	header = p;
    902	header->data_format = DATA_FORMAT_FIXED_POINT;
    903	header->fmt_id = MEDIA_FMT_ID_PCM;
    904	header->payload_size = payload_size - sizeof(*header);
    905
    906	p = p + sizeof(*header);
    907	cfg = p;
    908	cfg->sample_rate = mcfg->sample_rate;
    909	cfg->bit_width = mcfg->bit_width;
    910	cfg->alignment = PCM_LSB_ALIGNED;
    911	cfg->bits_per_sample = mcfg->bit_width;
    912	cfg->q_factor = mcfg->bit_width - 1;
    913	cfg->endianness = PCM_LITTLE_ENDIAN;
    914	cfg->num_channels = mcfg->num_channels;
    915
    916	if (mcfg->num_channels == 1) {
    917		cfg->channel_mapping[0] =  PCM_CHANNEL_L;
    918	} else if (num_channels == 2) {
    919		cfg->channel_mapping[0] =  PCM_CHANNEL_L;
    920		cfg->channel_mapping[1] =  PCM_CHANNEL_R;
    921	}
    922
    923	rc = audioreach_graph_send_cmd_sync(graph, pkt, 0);
    924
    925	kfree(pkt);
    926
    927	return rc;
    928}
    929
    930int audioreach_gain_set_vol_ctrl(struct q6apm *apm, struct audioreach_module *module, int vol)
    931{
    932	struct param_id_vol_ctrl_master_gain *cfg;
    933	struct apm_module_param_data *param_data;
    934	int rc, payload_size;
    935	struct gpr_pkt *pkt;
    936	void *p;
    937
    938	payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE;
    939	pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
    940	if (IS_ERR(pkt))
    941		return PTR_ERR(pkt);
    942
    943	p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
    944
    945	param_data = p;
    946	param_data->module_instance_id = module->instance_id;
    947	param_data->error_code = 0;
    948	param_data->param_id = PARAM_ID_VOL_CTRL_MASTER_GAIN;
    949	param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
    950
    951	p = p + APM_MODULE_PARAM_DATA_SIZE;
    952	cfg = p;
    953	cfg->master_gain =  vol;
    954	rc = q6apm_send_cmd_sync(apm, pkt, 0);
    955
    956	kfree(pkt);
    957
    958	return rc;
    959}
    960EXPORT_SYMBOL_GPL(audioreach_gain_set_vol_ctrl);
    961
    962static int audioreach_gain_set(struct q6apm_graph *graph, struct audioreach_module *module)
    963{
    964	struct apm_module_param_data *param_data;
    965	struct apm_gain_module_cfg *cfg;
    966	int rc, payload_size;
    967	struct gpr_pkt *pkt;
    968
    969	payload_size = APM_GAIN_CFG_PSIZE;
    970	pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
    971	if (IS_ERR(pkt))
    972		return PTR_ERR(pkt);
    973
    974	cfg = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
    975
    976	param_data = &cfg->param_data;
    977	param_data->module_instance_id = module->instance_id;
    978	param_data->error_code = 0;
    979	param_data->param_id = APM_PARAM_ID_GAIN;
    980	param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
    981
    982	cfg->gain_cfg.gain = module->gain;
    983
    984	rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
    985
    986	kfree(pkt);
    987
    988	return rc;
    989}
    990
    991int audioreach_set_media_format(struct q6apm_graph *graph, struct audioreach_module *module,
    992				struct audioreach_module_config *cfg)
    993{
    994	int rc;
    995
    996	switch (module->module_id) {
    997	case MODULE_ID_DATA_LOGGING:
    998		rc = audioreach_logging_set_media_format(graph, module);
    999		break;
   1000	case MODULE_ID_PCM_DEC:
   1001	case MODULE_ID_PCM_ENC:
   1002	case MODULE_ID_PCM_CNV:
   1003		rc = audioreach_pcm_set_media_format(graph, module, cfg);
   1004		break;
   1005	case MODULE_ID_I2S_SOURCE:
   1006	case MODULE_ID_I2S_SINK:
   1007		rc = audioreach_i2s_set_media_format(graph, module, cfg);
   1008		break;
   1009	case MODULE_ID_WR_SHARED_MEM_EP:
   1010		rc = audioreach_shmem_set_media_format(graph, module, cfg);
   1011		break;
   1012	case MODULE_ID_GAIN:
   1013		rc = audioreach_gain_set(graph, module);
   1014		break;
   1015	case MODULE_ID_CODEC_DMA_SINK:
   1016	case MODULE_ID_CODEC_DMA_SOURCE:
   1017		rc = audioreach_codec_dma_set_media_format(graph, module, cfg);
   1018		break;
   1019	default:
   1020		rc = 0;
   1021	}
   1022
   1023	return rc;
   1024}
   1025EXPORT_SYMBOL_GPL(audioreach_set_media_format);
   1026
   1027void audioreach_graph_free_buf(struct q6apm_graph *graph)
   1028{
   1029	struct audioreach_graph_data *port;
   1030
   1031	mutex_lock(&graph->lock);
   1032	port = &graph->rx_data;
   1033	port->num_periods = 0;
   1034	kfree(port->buf);
   1035	port->buf = NULL;
   1036
   1037	port = &graph->tx_data;
   1038	port->num_periods = 0;
   1039	kfree(port->buf);
   1040	port->buf = NULL;
   1041	mutex_unlock(&graph->lock);
   1042}
   1043EXPORT_SYMBOL_GPL(audioreach_graph_free_buf);
   1044
   1045int audioreach_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, size_t period_sz,
   1046				  unsigned int periods, bool is_contiguous)
   1047{
   1048	struct apm_shared_map_region_payload *mregions;
   1049	struct apm_cmd_shared_mem_map_regions *cmd;
   1050	uint32_t num_regions, buf_sz, payload_size;
   1051	struct audioreach_graph_data *data;
   1052	struct gpr_pkt *pkt;
   1053	void *p;
   1054	int rc, i;
   1055
   1056	if (dir == SNDRV_PCM_STREAM_PLAYBACK)
   1057		data = &graph->rx_data;
   1058	else
   1059		data = &graph->tx_data;
   1060
   1061	if (is_contiguous) {
   1062		num_regions = 1;
   1063		buf_sz = period_sz * periods;
   1064	} else {
   1065		buf_sz = period_sz;
   1066		num_regions = periods;
   1067	}
   1068
   1069	/* DSP expects size should be aligned to 4K */
   1070	buf_sz = ALIGN(buf_sz, 4096);
   1071
   1072	payload_size = sizeof(*cmd) + (sizeof(*mregions) * num_regions);
   1073
   1074	pkt = audioreach_alloc_apm_pkt(payload_size, APM_CMD_SHARED_MEM_MAP_REGIONS, dir,
   1075				     graph->port->id);
   1076	if (IS_ERR(pkt))
   1077		return PTR_ERR(pkt);
   1078
   1079	p = (void *)pkt + GPR_HDR_SIZE;
   1080	cmd = p;
   1081	cmd->mem_pool_id = APM_MEMORY_MAP_SHMEM8_4K_POOL;
   1082	cmd->num_regions = num_regions;
   1083
   1084	cmd->property_flag = 0x0;
   1085
   1086	mregions = p + sizeof(*cmd);
   1087
   1088	mutex_lock(&graph->lock);
   1089
   1090	for (i = 0; i < num_regions; i++) {
   1091		struct audio_buffer *ab;
   1092
   1093		ab = &data->buf[i];
   1094		mregions->shm_addr_lsw = lower_32_bits(ab->phys);
   1095		mregions->shm_addr_msw = upper_32_bits(ab->phys);
   1096		mregions->mem_size_bytes = buf_sz;
   1097		++mregions;
   1098	}
   1099	mutex_unlock(&graph->lock);
   1100
   1101	rc = audioreach_graph_send_cmd_sync(graph, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS);
   1102
   1103	kfree(pkt);
   1104
   1105	return rc;
   1106}
   1107EXPORT_SYMBOL_GPL(audioreach_map_memory_regions);
   1108
   1109int audioreach_shared_memory_send_eos(struct q6apm_graph *graph)
   1110{
   1111	struct data_cmd_wr_sh_mem_ep_eos *eos;
   1112	struct gpr_pkt *pkt;
   1113	int rc = 0, iid;
   1114
   1115	iid = q6apm_graph_get_rx_shmem_module_iid(graph);
   1116	pkt = audioreach_alloc_cmd_pkt(sizeof(*eos), DATA_CMD_WR_SH_MEM_EP_EOS, 0,
   1117				       graph->port->id, iid);
   1118	if (IS_ERR(pkt))
   1119		return PTR_ERR(pkt);
   1120
   1121	eos = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
   1122
   1123	eos->policy = WR_SH_MEM_EP_EOS_POLICY_LAST;
   1124
   1125	rc = gpr_send_port_pkt(graph->port, pkt);
   1126	kfree(pkt);
   1127
   1128	return rc;
   1129}
   1130EXPORT_SYMBOL_GPL(audioreach_shared_memory_send_eos);