1/*
2 *  sst_stream.c - Intel SST Driver for audio engine
3 *
4 *  Copyright (C) 2008-14 Intel Corp
5 *  Authors:	Vinod Koul <vinod.koul@intel.com>
6 *		Harsha Priya <priya.harsha@intel.com>
7 *		Dharageswari R <dharageswari.r@intel.com>
8 *		KP Jeeja <jeeja.kp@intel.com>
9 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 *  This program is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License as published by
13 *  the Free Software Foundation; version 2 of the License.
14 *
15 *  This program is distributed in the hope that it will be useful, but
16 *  WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 *  General Public License for more details.
19 *
20 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 */
22#include <linux/pci.h>
23#include <linux/firmware.h>
24#include <linux/sched.h>
25#include <linux/delay.h>
26#include <linux/pm_runtime.h>
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/soc.h>
30#include <sound/compress_driver.h>
31#include <asm/platform_sst_audio.h>
32#include "../sst-mfld-platform.h"
33#include "sst.h"
34#include "../../common/sst-dsp.h"
35
36int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
37{
38	struct snd_sst_alloc_mrfld alloc_param;
39	struct snd_sst_params *str_params;
40	struct snd_sst_tstamp fw_tstamp;
41	struct stream_info *str_info;
42	struct snd_sst_alloc_response *response;
43	unsigned int str_id, pipe_id, task_id;
44	int i, num_ch, ret = 0;
45	void *data = NULL;
46
47	dev_dbg(sst_drv_ctx->dev, "Enter\n");
48	BUG_ON(!params);
49
50	str_params = (struct snd_sst_params *)params;
51	memset(&alloc_param, 0, sizeof(alloc_param));
52	alloc_param.operation = str_params->ops;
53	alloc_param.codec_type = str_params->codec;
54	alloc_param.sg_count = str_params->aparams.sg_count;
55	alloc_param.ring_buf_info[0].addr =
56		str_params->aparams.ring_buf_info[0].addr;
57	alloc_param.ring_buf_info[0].size =
58		str_params->aparams.ring_buf_info[0].size;
59	alloc_param.frag_size = str_params->aparams.frag_size;
60
61	memcpy(&alloc_param.codec_params, &str_params->sparams,
62			sizeof(struct snd_sst_stream_params));
63
64	/*
65	 * fill channel map params for multichannel support.
66	 * Ideally channel map should be received from upper layers
67	 * for multichannel support.
68	 * Currently hardcoding as per FW reqm.
69	 */
70	num_ch = sst_get_num_channel(str_params);
71	for (i = 0; i < 8; i++) {
72		if (i < num_ch)
73			alloc_param.codec_params.uc.pcm_params.channel_map[i] = i;
74		else
75			alloc_param.codec_params.uc.pcm_params.channel_map[i] = 0xFF;
76	}
77
78	str_id = str_params->stream_id;
79	str_info = get_stream_info(sst_drv_ctx, str_id);
80	if (str_info == NULL) {
81		dev_err(sst_drv_ctx->dev, "get stream info returned null\n");
82		return -EINVAL;
83	}
84
85	pipe_id = str_params->device_type;
86	task_id = str_params->task;
87	sst_drv_ctx->streams[str_id].pipe_id = pipe_id;
88	sst_drv_ctx->streams[str_id].task_id = task_id;
89	sst_drv_ctx->streams[str_id].num_ch = num_ch;
90
91	if (sst_drv_ctx->info.lpe_viewpt_rqd)
92		alloc_param.ts = sst_drv_ctx->info.mailbox_start +
93			sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
94	else
95		alloc_param.ts = sst_drv_ctx->mailbox_add +
96			sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
97
98	dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n",
99			alloc_param.ts);
100	dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n",
101			pipe_id, task_id);
102
103	/* allocate device type context */
104	sst_init_stream(&sst_drv_ctx->streams[str_id], alloc_param.codec_type,
105			str_id, alloc_param.operation, 0);
106
107	dev_info(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
108			str_id, pipe_id);
109	ret = sst_prepare_and_post_msg(sst_drv_ctx, task_id, IPC_CMD,
110			IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param),
111			&alloc_param, data, true, true, false, true);
112
113	if (ret < 0) {
114		dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
115		/* alloc failed, so reset the state to uninit */
116		str_info->status = STREAM_UN_INIT;
117		str_id = ret;
118	} else if (data) {
119		response = (struct snd_sst_alloc_response *)data;
120		ret = response->str_type.result;
121		if (!ret)
122			goto out;
123		dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
124		if (ret == SST_ERR_STREAM_IN_USE) {
125			dev_err(sst_drv_ctx->dev,
126				"FW not in clean state, send free for:%d\n", str_id);
127			sst_free_stream(sst_drv_ctx, str_id);
128		}
129		str_id = -ret;
130	}
131out:
132	kfree(data);
133	return str_id;
134}
135
136/**
137* sst_start_stream - Send msg for a starting stream
138* @str_id:	 stream ID
139*
140* This function is called by any function which wants to start
141* a stream.
142*/
143int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
144{
145	int retval = 0;
146	struct stream_info *str_info;
147	u16 data = 0;
148
149	dev_dbg(sst_drv_ctx->dev, "sst_start_stream for %d\n", str_id);
150	str_info = get_stream_info(sst_drv_ctx, str_id);
151	if (!str_info)
152		return -EINVAL;
153	if (str_info->status != STREAM_RUNNING)
154		return -EBADRQC;
155
156	retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
157			IPC_CMD, IPC_IA_START_STREAM_MRFLD, str_info->pipe_id,
158			sizeof(u16), &data, NULL, true, true, true, false);
159
160	return retval;
161}
162
163int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx,
164		struct snd_sst_bytes_v2 *bytes)
165{	struct ipc_post *msg = NULL;
166	u32 length;
167	int pvt_id, ret = 0;
168	struct sst_block *block = NULL;
169
170	dev_dbg(sst_drv_ctx->dev,
171		"type:%u ipc_msg:%u block:%u task_id:%u pipe: %#x length:%#x\n",
172		bytes->type, bytes->ipc_msg, bytes->block, bytes->task_id,
173		bytes->pipe_id, bytes->len);
174
175	if (sst_create_ipc_msg(&msg, true))
176		return -ENOMEM;
177
178	pvt_id = sst_assign_pvt_id(sst_drv_ctx);
179	sst_fill_header_mrfld(&msg->mrfld_header, bytes->ipc_msg,
180			bytes->task_id, 1, pvt_id);
181	msg->mrfld_header.p.header_high.part.res_rqd = bytes->block;
182	length = bytes->len;
183	msg->mrfld_header.p.header_low_payload = length;
184	dev_dbg(sst_drv_ctx->dev, "length is %d\n", length);
185	memcpy(msg->mailbox_data, &bytes->bytes, bytes->len);
186	if (bytes->block) {
187		block = sst_create_block(sst_drv_ctx, bytes->ipc_msg, pvt_id);
188		if (block == NULL) {
189			kfree(msg);
190			ret = -ENOMEM;
191			goto out;
192		}
193	}
194
195	sst_add_to_dispatch_list_and_post(sst_drv_ctx, msg);
196	dev_dbg(sst_drv_ctx->dev, "msg->mrfld_header.p.header_low_payload:%d",
197			msg->mrfld_header.p.header_low_payload);
198
199	if (bytes->block) {
200		ret = sst_wait_timeout(sst_drv_ctx, block);
201		if (ret) {
202			dev_err(sst_drv_ctx->dev, "fw returned err %d\n", ret);
203			sst_free_block(sst_drv_ctx, block);
204			goto out;
205		}
206	}
207	if (bytes->type == SND_SST_BYTES_GET) {
208		/*
209		 * copy the reply and send back
210		 * we need to update only sz and payload
211		 */
212		if (bytes->block) {
213			unsigned char *r = block->data;
214
215			dev_dbg(sst_drv_ctx->dev, "read back %d bytes",
216					bytes->len);
217			memcpy(bytes->bytes, r, bytes->len);
218		}
219	}
220	if (bytes->block)
221		sst_free_block(sst_drv_ctx, block);
222out:
223	test_and_clear_bit(pvt_id, &sst_drv_ctx->pvt_id);
224	return 0;
225}
226
227/*
228 * sst_pause_stream - Send msg for a pausing stream
229 * @str_id:	 stream ID
230 *
231 * This function is called by any function which wants to pause
232 * an already running stream.
233 */
234int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
235{
236	int retval = 0;
237	struct stream_info *str_info;
238
239	dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_pause_stream for %d\n", str_id);
240	str_info = get_stream_info(sst_drv_ctx, str_id);
241	if (!str_info)
242		return -EINVAL;
243	if (str_info->status == STREAM_PAUSED)
244		return 0;
245	if (str_info->status == STREAM_RUNNING ||
246		str_info->status == STREAM_INIT) {
247		if (str_info->prev == STREAM_UN_INIT)
248			return -EBADRQC;
249
250		retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
251				IPC_IA_PAUSE_STREAM_MRFLD, str_info->pipe_id,
252				0, NULL, NULL, true, true, false, true);
253
254		if (retval == 0) {
255			str_info->prev = str_info->status;
256			str_info->status = STREAM_PAUSED;
257		} else if (retval == SST_ERR_INVALID_STREAM_ID) {
258			retval = -EINVAL;
259			mutex_lock(&sst_drv_ctx->sst_lock);
260			sst_clean_stream(str_info);
261			mutex_unlock(&sst_drv_ctx->sst_lock);
262		}
263	} else {
264		retval = -EBADRQC;
265		dev_dbg(sst_drv_ctx->dev, "SST DBG:BADRQC for stream\n ");
266	}
267
268	return retval;
269}
270
271/**
272 * sst_resume_stream - Send msg for resuming stream
273 * @str_id:		stream ID
274 *
275 * This function is called by any function which wants to resume
276 * an already paused stream.
277 */
278int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
279{
280	int retval = 0;
281	struct stream_info *str_info;
282
283	dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_resume_stream for %d\n", str_id);
284	str_info = get_stream_info(sst_drv_ctx, str_id);
285	if (!str_info)
286		return -EINVAL;
287	if (str_info->status == STREAM_RUNNING)
288			return 0;
289	if (str_info->status == STREAM_PAUSED) {
290		retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
291				IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD,
292				str_info->pipe_id, 0, NULL, NULL,
293				true, true, false, true);
294
295		if (!retval) {
296			if (str_info->prev == STREAM_RUNNING)
297				str_info->status = STREAM_RUNNING;
298			else
299				str_info->status = STREAM_INIT;
300			str_info->prev = STREAM_PAUSED;
301		} else if (retval == -SST_ERR_INVALID_STREAM_ID) {
302			retval = -EINVAL;
303			mutex_lock(&sst_drv_ctx->sst_lock);
304			sst_clean_stream(str_info);
305			mutex_unlock(&sst_drv_ctx->sst_lock);
306		}
307	} else {
308		retval = -EBADRQC;
309		dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream\n");
310	}
311
312	return retval;
313}
314
315
316/**
317 * sst_drop_stream - Send msg for stopping stream
318 * @str_id:		stream ID
319 *
320 * This function is called by any function which wants to stop
321 * a stream.
322 */
323int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
324{
325	int retval = 0;
326	struct stream_info *str_info;
327
328	dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drop_stream for %d\n", str_id);
329	str_info = get_stream_info(sst_drv_ctx, str_id);
330	if (!str_info)
331		return -EINVAL;
332
333	if (str_info->status != STREAM_UN_INIT) {
334		str_info->prev = STREAM_UN_INIT;
335		str_info->status = STREAM_INIT;
336		str_info->cumm_bytes = 0;
337		retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
338				IPC_CMD, IPC_IA_DROP_STREAM_MRFLD,
339				str_info->pipe_id, 0, NULL, NULL,
340				true, true, true, false);
341	} else {
342		retval = -EBADRQC;
343		dev_dbg(sst_drv_ctx->dev, "BADQRC for stream, state %x\n",
344				str_info->status);
345	}
346	return retval;
347}
348
349/**
350* sst_drain_stream - Send msg for draining stream
351* @str_id:		stream ID
352*
353* This function is called by any function which wants to drain
354* a stream.
355*/
356int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx,
357			int str_id, bool partial_drain)
358{
359	int retval = 0;
360	struct stream_info *str_info;
361
362	dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drain_stream for %d\n", str_id);
363	str_info = get_stream_info(sst_drv_ctx, str_id);
364	if (!str_info)
365		return -EINVAL;
366	if (str_info->status != STREAM_RUNNING &&
367		str_info->status != STREAM_INIT &&
368		str_info->status != STREAM_PAUSED) {
369			dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream = %d\n",
370				       str_info->status);
371			return -EBADRQC;
372	}
373
374	retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
375			IPC_IA_DRAIN_STREAM_MRFLD, str_info->pipe_id,
376			sizeof(u8), &partial_drain, NULL, true, true, false, false);
377	/*
378	 * with new non blocked drain implementation in core we dont need to
379	 * wait for respsonse, and need to only invoke callback for drain
380	 * complete
381	 */
382
383	return retval;
384}
385
386/**
387 * sst_free_stream - Frees a stream
388 * @str_id:		stream ID
389 *
390 * This function is called by any function which wants to free
391 * a stream.
392 */
393int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
394{
395	int retval = 0;
396	struct stream_info *str_info;
397	struct intel_sst_ops *ops;
398
399	dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id);
400
401	mutex_lock(&sst_drv_ctx->sst_lock);
402	if (sst_drv_ctx->sst_state == SST_RESET) {
403		mutex_unlock(&sst_drv_ctx->sst_lock);
404		return -ENODEV;
405	}
406	mutex_unlock(&sst_drv_ctx->sst_lock);
407	str_info = get_stream_info(sst_drv_ctx, str_id);
408	if (!str_info)
409		return -EINVAL;
410	ops = sst_drv_ctx->ops;
411
412	mutex_lock(&str_info->lock);
413	if (str_info->status != STREAM_UN_INIT) {
414		str_info->prev =  str_info->status;
415		str_info->status = STREAM_UN_INIT;
416		mutex_unlock(&str_info->lock);
417
418		dev_info(sst_drv_ctx->dev, "Free for str %d pipe %#x\n",
419				str_id, str_info->pipe_id);
420		retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
421				IPC_IA_FREE_STREAM_MRFLD, str_info->pipe_id, 0,
422				NULL, NULL, true, true, false, true);
423
424		dev_dbg(sst_drv_ctx->dev, "sst: wait for free returned %d\n",
425				retval);
426		mutex_lock(&sst_drv_ctx->sst_lock);
427		sst_clean_stream(str_info);
428		mutex_unlock(&sst_drv_ctx->sst_lock);
429		dev_dbg(sst_drv_ctx->dev, "SST DBG:Stream freed\n");
430	} else {
431		mutex_unlock(&str_info->lock);
432		retval = -EBADRQC;
433		dev_dbg(sst_drv_ctx->dev, "SST DBG:BADQRC for stream\n");
434	}
435
436	return retval;
437}
438