Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / sound / soc / intel / atom / sst / sst_stream.c
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
36 int 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         }
131 out:
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 */
143 int 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
163 int 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);
222 out:
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  */
234 int 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  */
278 int 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  */
323 int 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 */
356 int 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  */
393 int 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 }