brintos

brintos / linux-shallow public Read only

0
0
Text · 7.6 KiB · 30eec2d Raw
314 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// Copyright(c) 2020 Intel Corporation4//5// Author: Cezary Rojewski <cezary.rojewski@intel.com>6//7 8#include <linux/slab.h>9#include "core.h"10#include "messages.h"11#include "registers.h"12 13int catpt_ipc_get_fw_version(struct catpt_dev *cdev,14			     struct catpt_fw_version *version)15{16	union catpt_global_msg msg = CATPT_GLOBAL_MSG(GET_FW_VERSION);17	struct catpt_ipc_msg request = {{0}}, reply;18	int ret;19 20	request.header = msg.val;21	reply.size = sizeof(*version);22	reply.data = version;23 24	ret = catpt_dsp_send_msg(cdev, request, &reply);25	if (ret)26		dev_err(cdev->dev, "get fw version failed: %d\n", ret);27 28	return ret;29}30 31struct catpt_alloc_stream_input {32	enum catpt_path_id path_id:8;33	enum catpt_stream_type stream_type:8;34	enum catpt_format_id format_id:8;35	u8 reserved;36	struct catpt_audio_format input_format;37	struct catpt_ring_info ring_info;38	u8 num_entries;39	/* flex array with entries here */40	struct catpt_memory_info persistent_mem;41	struct catpt_memory_info scratch_mem;42	u32 num_notifications; /* obsolete */43} __packed;44 45int catpt_ipc_alloc_stream(struct catpt_dev *cdev,46			   enum catpt_path_id path_id,47			   enum catpt_stream_type type,48			   struct catpt_audio_format *afmt,49			   struct catpt_ring_info *rinfo,50			   u8 num_modules,51			   struct catpt_module_entry *modules,52			   struct resource *persistent,53			   struct resource *scratch,54			   struct catpt_stream_info *sinfo)55{56	union catpt_global_msg msg = CATPT_GLOBAL_MSG(ALLOCATE_STREAM);57	struct catpt_alloc_stream_input input;58	struct catpt_ipc_msg request, reply;59	size_t size, arrsz;60	u8 *payload;61	off_t off;62	int ret;63 64	off = offsetof(struct catpt_alloc_stream_input, persistent_mem);65	arrsz = sizeof(*modules) * num_modules;66	size = sizeof(input) + arrsz;67 68	payload = kzalloc(size, GFP_KERNEL);69	if (!payload)70		return -ENOMEM;71 72	memset(&input, 0, sizeof(input));73	input.path_id = path_id;74	input.stream_type = type;75	input.format_id = CATPT_FORMAT_PCM;76	input.input_format = *afmt;77	input.ring_info = *rinfo;78	input.num_entries = num_modules;79	input.persistent_mem.offset = catpt_to_dsp_offset(persistent->start);80	input.persistent_mem.size = resource_size(persistent);81	if (scratch) {82		input.scratch_mem.offset = catpt_to_dsp_offset(scratch->start);83		input.scratch_mem.size = resource_size(scratch);84	}85 86	/* re-arrange the input: account for flex array 'entries' */87	memcpy(payload, &input, sizeof(input));88	memmove(payload + off + arrsz, payload + off, sizeof(input) - off);89	memcpy(payload + off, modules, arrsz);90 91	request.header = msg.val;92	request.size = size;93	request.data = payload;94	reply.size = sizeof(*sinfo);95	reply.data = sinfo;96 97	ret = catpt_dsp_send_msg(cdev, request, &reply);98	if (ret)99		dev_err(cdev->dev, "alloc stream type %d failed: %d\n",100			type, ret);101 102	kfree(payload);103	return ret;104}105 106int catpt_ipc_free_stream(struct catpt_dev *cdev, u8 stream_hw_id)107{108	union catpt_global_msg msg = CATPT_GLOBAL_MSG(FREE_STREAM);109	struct catpt_ipc_msg request;110	int ret;111 112	request.header = msg.val;113	request.size = sizeof(stream_hw_id);114	request.data = &stream_hw_id;115 116	ret = catpt_dsp_send_msg(cdev, request, NULL);117	if (ret)118		dev_err(cdev->dev, "free stream %d failed: %d\n",119			stream_hw_id, ret);120 121	return ret;122}123 124int catpt_ipc_set_device_format(struct catpt_dev *cdev,125				struct catpt_ssp_device_format *devfmt)126{127	union catpt_global_msg msg = CATPT_GLOBAL_MSG(SET_DEVICE_FORMATS);128	struct catpt_ipc_msg request;129	int ret;130 131	request.header = msg.val;132	request.size = sizeof(*devfmt);133	request.data = devfmt;134 135	ret = catpt_dsp_send_msg(cdev, request, NULL);136	if (ret)137		dev_err(cdev->dev, "set device format failed: %d\n", ret);138 139	return ret;140}141 142int catpt_ipc_enter_dxstate(struct catpt_dev *cdev, enum catpt_dx_state state,143			    struct catpt_dx_context *context)144{145	union catpt_global_msg msg = CATPT_GLOBAL_MSG(ENTER_DX_STATE);146	struct catpt_ipc_msg request, reply;147	int ret;148 149	request.header = msg.val;150	request.size = sizeof(state);151	request.data = &state;152	reply.size = sizeof(*context);153	reply.data = context;154 155	ret = catpt_dsp_send_msg(cdev, request, &reply);156	if (ret)157		dev_err(cdev->dev, "enter dx state failed: %d\n", ret);158 159	return ret;160}161 162int catpt_ipc_get_mixer_stream_info(struct catpt_dev *cdev,163				    struct catpt_mixer_stream_info *info)164{165	union catpt_global_msg msg = CATPT_GLOBAL_MSG(GET_MIXER_STREAM_INFO);166	struct catpt_ipc_msg request = {{0}}, reply;167	int ret;168 169	request.header = msg.val;170	reply.size = sizeof(*info);171	reply.data = info;172 173	ret = catpt_dsp_send_msg(cdev, request, &reply);174	if (ret)175		dev_err(cdev->dev, "get mixer info failed: %d\n", ret);176 177	return ret;178}179 180int catpt_ipc_reset_stream(struct catpt_dev *cdev, u8 stream_hw_id)181{182	union catpt_stream_msg msg = CATPT_STREAM_MSG(RESET_STREAM);183	struct catpt_ipc_msg request = {{0}};184	int ret;185 186	msg.stream_hw_id = stream_hw_id;187	request.header = msg.val;188 189	ret = catpt_dsp_send_msg(cdev, request, NULL);190	if (ret)191		dev_err(cdev->dev, "reset stream %d failed: %d\n",192			stream_hw_id, ret);193 194	return ret;195}196 197int catpt_ipc_pause_stream(struct catpt_dev *cdev, u8 stream_hw_id)198{199	union catpt_stream_msg msg = CATPT_STREAM_MSG(PAUSE_STREAM);200	struct catpt_ipc_msg request = {{0}};201	int ret;202 203	msg.stream_hw_id = stream_hw_id;204	request.header = msg.val;205 206	ret = catpt_dsp_send_msg(cdev, request, NULL);207	if (ret)208		dev_err(cdev->dev, "pause stream %d failed: %d\n",209			stream_hw_id, ret);210 211	return ret;212}213 214int catpt_ipc_resume_stream(struct catpt_dev *cdev, u8 stream_hw_id)215{216	union catpt_stream_msg msg = CATPT_STREAM_MSG(RESUME_STREAM);217	struct catpt_ipc_msg request = {{0}};218	int ret;219 220	msg.stream_hw_id = stream_hw_id;221	request.header = msg.val;222 223	ret = catpt_dsp_send_msg(cdev, request, NULL);224	if (ret)225		dev_err(cdev->dev, "resume stream %d failed: %d\n",226			stream_hw_id, ret);227 228	return ret;229}230 231struct catpt_set_volume_input {232	u32 channel;233	u32 target_volume;234	u64 curve_duration;235	u32 curve_type;236} __packed;237 238int catpt_ipc_set_volume(struct catpt_dev *cdev, u8 stream_hw_id,239			 u32 channel, u32 volume,240			 u32 curve_duration,241			 enum catpt_audio_curve_type curve_type)242{243	union catpt_stream_msg msg = CATPT_STAGE_MSG(SET_VOLUME);244	struct catpt_ipc_msg request;245	struct catpt_set_volume_input input;246	int ret;247 248	msg.stream_hw_id = stream_hw_id;249	input.channel = channel;250	input.target_volume = volume;251	input.curve_duration = curve_duration;252	input.curve_type = curve_type;253 254	request.header = msg.val;255	request.size = sizeof(input);256	request.data = &input;257 258	ret = catpt_dsp_send_msg(cdev, request, NULL);259	if (ret)260		dev_err(cdev->dev, "set stream %d volume failed: %d\n",261			stream_hw_id, ret);262 263	return ret;264}265 266struct catpt_set_write_pos_input {267	u32 new_write_pos;268	bool end_of_buffer;269	bool low_latency;270} __packed;271 272int catpt_ipc_set_write_pos(struct catpt_dev *cdev, u8 stream_hw_id,273			    u32 pos, bool eob, bool ll)274{275	union catpt_stream_msg msg = CATPT_STAGE_MSG(SET_WRITE_POSITION);276	struct catpt_ipc_msg request;277	struct catpt_set_write_pos_input input;278	int ret;279 280	msg.stream_hw_id = stream_hw_id;281	input.new_write_pos = pos;282	input.end_of_buffer = eob;283	input.low_latency = ll;284 285	request.header = msg.val;286	request.size = sizeof(input);287	request.data = &input;288 289	ret = catpt_dsp_send_msg(cdev, request, NULL);290	if (ret)291		dev_err(cdev->dev, "set stream %d write pos failed: %d\n",292			stream_hw_id, ret);293 294	return ret;295}296 297int catpt_ipc_mute_loopback(struct catpt_dev *cdev, u8 stream_hw_id, bool mute)298{299	union catpt_stream_msg msg = CATPT_STAGE_MSG(MUTE_LOOPBACK);300	struct catpt_ipc_msg request;301	int ret;302 303	msg.stream_hw_id = stream_hw_id;304	request.header = msg.val;305	request.size = sizeof(mute);306	request.data = &mute;307 308	ret = catpt_dsp_send_msg(cdev, request, NULL);309	if (ret)310		dev_err(cdev->dev, "mute loopback failed: %d\n", ret);311 312	return ret;313}314