staging: r8712u: Fix regression caused by commit 8c213fa
[pandora-kernel.git] / drivers / staging / intel_sst / intel_sst_pvt.c
1 /*
2  *  intel_sst_pvt.c - Intel SST Driver for audio engine
3  *
4  *  Copyright (C) 2008-10       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  *  You should have received a copy of the GNU General Public License along
21  *  with this program; if not, write to the Free Software Foundation, Inc.,
22  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23  *
24  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25  *
26  *  This driver exposes the audio engine functionalities to the ALSA
27  *      and middleware.
28  *
29  *  This file contains all private functions
30  */
31
32 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33
34 #include <linux/pci.h>
35 #include <linux/fs.h>
36 #include <linux/firmware.h>
37 #include <linux/sched.h>
38 #include "intel_sst.h"
39 #include "intel_sst_ioctl.h"
40 #include "intel_sst_fw_ipc.h"
41 #include "intel_sst_common.h"
42
43 /*
44  * sst_get_block_stream - get a new block stream
45  *
46  * @sst_drv_ctx: Driver context structure
47  *
48  * This function assigns a block for the calls that dont have stream context yet
49  * the blocks are used for waiting on Firmware's response for any operation
50  * Should be called with stream lock held
51  */
52 int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx)
53 {
54         int i;
55
56         for (i = 0; i < MAX_ACTIVE_STREAM; i++) {
57                 if (sst_drv_ctx->alloc_block[i].sst_id == BLOCK_UNINIT) {
58                         sst_drv_ctx->alloc_block[i].ops_block.condition = false;
59                         sst_drv_ctx->alloc_block[i].ops_block.ret_code = 0;
60                         sst_drv_ctx->alloc_block[i].sst_id = 0;
61                         break;
62                 }
63         }
64         if (i == MAX_ACTIVE_STREAM) {
65                 pr_err("max alloc_stream reached\n");
66                 i = -EBUSY; /* active stream limit reached */
67         }
68         return i;
69 }
70
71 /*
72  * sst_wait_interruptible - wait on event
73  *
74  * @sst_drv_ctx: Driver context
75  * @block: Driver block to wait on
76  *
77  * This function waits without a timeout (and is interruptable) for a
78  * given block event
79  */
80 int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
81                                 struct sst_block *block)
82 {
83         int retval = 0;
84
85         if (!wait_event_interruptible(sst_drv_ctx->wait_queue,
86                                 block->condition)) {
87                 /* event wake */
88                 if (block->ret_code < 0) {
89                         pr_err("stream failed %d\n", block->ret_code);
90                         retval = -EBUSY;
91                 } else {
92                         pr_debug("event up\n");
93                         retval = 0;
94                 }
95         } else {
96                 pr_err("signal interrupted\n");
97                 retval = -EINTR;
98         }
99         return retval;
100
101 }
102
103
104 /*
105  * sst_wait_interruptible_timeout - wait on event interruptable
106  *
107  * @sst_drv_ctx: Driver context
108  * @block: Driver block to wait on
109  * @timeout: time for wait on
110  *
111  * This function waits with a timeout value (and is interruptible) on a
112  * given block event
113  */
114 int sst_wait_interruptible_timeout(
115                         struct intel_sst_drv *sst_drv_ctx,
116                         struct sst_block *block, int timeout)
117 {
118         int retval = 0;
119
120         pr_debug("sst_wait_interruptible_timeout - waiting....\n");
121         if (wait_event_interruptible_timeout(sst_drv_ctx->wait_queue,
122                                                 block->condition,
123                                                 msecs_to_jiffies(timeout))) {
124                 if (block->ret_code < 0)
125                         pr_err("stream failed %d\n", block->ret_code);
126                 else
127                         pr_debug("event up\n");
128                 retval = block->ret_code;
129         } else {
130                 block->on = false;
131                 pr_err("timeout occurred...\n");
132                 /*setting firmware state as uninit so that the
133                 firmware will get re-downloaded on next request
134                 this is because firmare not responding for 5 sec
135                 is equalant to some unrecoverable error of FW
136                 sst_drv_ctx->sst_state = SST_UN_INIT;*/
137                 retval = -EBUSY;
138         }
139         return retval;
140
141 }
142
143
144 /*
145  * sst_wait_timeout - wait on event for timeout
146  *
147  * @sst_drv_ctx: Driver context
148  * @block: Driver block to wait on
149  *
150  * This function waits with a timeout value (and is not interruptible) on a
151  * given block event
152  */
153 int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx,
154                 struct stream_alloc_block *block)
155 {
156         int retval = 0;
157
158         /* NOTE:
159         Observed that FW processes the alloc msg and replies even
160         before the alloc thread has finished execution */
161         pr_debug("waiting for %x, condition %x\n",
162                        block->sst_id, block->ops_block.condition);
163         if (wait_event_interruptible_timeout(sst_drv_ctx->wait_queue,
164                                 block->ops_block.condition,
165                                 msecs_to_jiffies(SST_BLOCK_TIMEOUT))) {
166                 /* event wake */
167                 pr_debug("Event wake %x\n", block->ops_block.condition);
168                 pr_debug("message ret: %d\n", block->ops_block.ret_code);
169                 retval = block->ops_block.ret_code;
170         } else {
171                 block->ops_block.on = false;
172                 pr_err("Wait timed-out %x\n", block->ops_block.condition);
173                 /* settign firmware state as uninit so that the
174                 firmware will get redownloaded on next request
175                 this is because firmare not responding for 5 sec
176                 is equalant to some unrecoverable error of FW
177                 sst_drv_ctx->sst_state = SST_UN_INIT;*/
178                 retval = -EBUSY;
179         }
180         return retval;
181
182 }
183
184 /*
185  * sst_create_large_msg - create a large IPC message
186  *
187  * @arg: ipc message
188  *
189  * this function allocates structures to send a large message to the firmware
190  */
191 int sst_create_large_msg(struct ipc_post **arg)
192 {
193         struct ipc_post *msg;
194
195         msg = kzalloc(sizeof(struct ipc_post), GFP_ATOMIC);
196         if (!msg) {
197                 pr_err("kzalloc msg failed\n");
198                 return -ENOMEM;
199         }
200
201         msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC);
202         if (!msg->mailbox_data) {
203                 kfree(msg);
204                 pr_err("kzalloc mailbox_data failed");
205                 return -ENOMEM;
206         }
207         *arg = msg;
208         return 0;
209 }
210
211 /*
212  * sst_create_short_msg - create a short IPC message
213  *
214  * @arg: ipc message
215  *
216  * this function allocates structures to send a short message to the firmware
217  */
218 int sst_create_short_msg(struct ipc_post **arg)
219 {
220         struct ipc_post *msg;
221
222         msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
223         if (!msg) {
224                 pr_err("kzalloc msg failed\n");
225                 return -ENOMEM;
226         }
227         msg->mailbox_data = NULL;
228         *arg = msg;
229         return 0;
230 }
231
232 /*
233  * sst_clean_stream - clean the stream context
234  *
235  * @stream: stream structure
236  *
237  * this function resets the stream contexts
238  * should be called in free
239  */
240 void sst_clean_stream(struct stream_info *stream)
241 {
242         struct sst_stream_bufs *bufs = NULL, *_bufs;
243         stream->status = STREAM_UN_INIT;
244         stream->prev = STREAM_UN_INIT;
245         mutex_lock(&stream->lock);
246         list_for_each_entry_safe(bufs, _bufs, &stream->bufs, node) {
247                 list_del(&bufs->node);
248                 kfree(bufs);
249         }
250         mutex_unlock(&stream->lock);
251
252         if (stream->ops != STREAM_OPS_PLAYBACK_DRM)
253                 kfree(stream->decode_ibuf);
254 }
255
256 /*
257  * sst_wake_up_alloc_block - wake up waiting block
258  *
259  * @sst_drv_ctx: Driver context
260  * @sst_id: stream id
261  * @status: status of wakeup
262  * @data: data pointer of wakeup
263  *
264  * This function wakes up a sleeping block event based on the response
265  */
266 void sst_wake_up_alloc_block(struct intel_sst_drv *sst_drv_ctx,
267                 u8 sst_id, int status, void *data)
268 {
269         int i;
270
271         /* Unblock with retval code */
272         for (i = 0; i < MAX_ACTIVE_STREAM; i++) {
273                 if (sst_id == sst_drv_ctx->alloc_block[i].sst_id) {
274                         sst_drv_ctx->alloc_block[i].ops_block.condition = true;
275                         sst_drv_ctx->alloc_block[i].ops_block.ret_code = status;
276                         sst_drv_ctx->alloc_block[i].ops_block.data = data;
277                         wake_up(&sst_drv_ctx->wait_queue);
278                         break;
279                 }
280         }
281 }
282
283 /*
284  * sst_enable_rx_timeslot - Send msg to query for stream parameters
285  * @status: rx timeslot to be enabled
286  *
287  * This function is called when the RX timeslot is required to be enabled
288  */
289 int sst_enable_rx_timeslot(int status)
290 {
291         int retval = 0;
292         struct ipc_post *msg = NULL;
293
294         if (sst_create_short_msg(&msg)) {
295                 pr_err("mem allocation failed\n");
296                         return -ENOMEM;
297         }
298         pr_debug("ipc message sending: ENABLE_RX_TIME_SLOT\n");
299         sst_fill_header(&msg->header, IPC_IA_ENABLE_RX_TIME_SLOT, 0, 0);
300         msg->header.part.data = status;
301         sst_drv_ctx->hs_info_blk.condition = false;
302         sst_drv_ctx->hs_info_blk.ret_code = 0;
303         sst_drv_ctx->hs_info_blk.on = true;
304         spin_lock(&sst_drv_ctx->list_spin_lock);
305         list_add_tail(&msg->node,
306                         &sst_drv_ctx->ipc_dispatch_list);
307         spin_unlock(&sst_drv_ctx->list_spin_lock);
308         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
309         retval = sst_wait_interruptible_timeout(sst_drv_ctx,
310                                 &sst_drv_ctx->hs_info_blk, SST_BLOCK_TIMEOUT);
311         return retval;
312 }
313