2 * intel_sst_pvt.c - Intel SST Driver for audio engine
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 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.
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.
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 * This driver exposes the audio engine functionalities to the ALSA
29 * This file contains all private functions
32 #include <linux/pci.h>
34 #include <linux/firmware.h>
35 #include <linux/sched.h>
36 #include "intel_sst.h"
37 #include "intel_sst_ioctl.h"
38 #include "intel_sst_fw_ipc.h"
39 #include "intel_sst_common.h"
42 * sst_get_block_stream - get a new block stream
44 * @sst_drv_ctx: Driver context structure
46 * This function assigns a block for the calls that dont have stream context yet
47 * the blocks are used for waiting on Firmware's response for any operation
48 * Should be called with stream lock held
50 int sst_get_block_stream(struct intel_sst_drv
*sst_drv_ctx
)
54 for (i
= 0; i
< MAX_ACTIVE_STREAM
; i
++) {
55 if (sst_drv_ctx
->alloc_block
[i
].sst_id
== BLOCK_UNINIT
) {
56 sst_drv_ctx
->alloc_block
[i
].ops_block
.condition
= false;
57 sst_drv_ctx
->alloc_block
[i
].ops_block
.ret_code
= 0;
58 sst_drv_ctx
->alloc_block
[i
].sst_id
= 0;
62 if (i
== MAX_ACTIVE_STREAM
) {
63 pr_err("sst: max alloc_stream reached");
64 i
= -EBUSY
; /* active stream limit reached */
70 * sst_wait_interruptible - wait on event
72 * @sst_drv_ctx: Driver context
73 * @block: Driver block to wait on
75 * This function waits without a timeout (and is interruptable) for a
78 int sst_wait_interruptible(struct intel_sst_drv
*sst_drv_ctx
,
79 struct sst_block
*block
)
83 if (!wait_event_interruptible(sst_drv_ctx
->wait_queue
,
86 if (block
->ret_code
< 0) {
87 pr_err("sst: stream failed %d\n", block
->ret_code
);
90 pr_debug("sst: event up\n");
94 pr_err("sst: signal interrupted\n");
103 * sst_wait_interruptible_timeout - wait on event interruptable
105 * @sst_drv_ctx: Driver context
106 * @block: Driver block to wait on
107 * @timeout: time for wait on
109 * This function waits with a timeout value (and is interruptible) on a
112 int sst_wait_interruptible_timeout(
113 struct intel_sst_drv
*sst_drv_ctx
,
114 struct sst_block
*block
, int timeout
)
118 pr_debug("sst: sst_wait_interruptible_timeout - waiting....\n");
119 if (wait_event_interruptible_timeout(sst_drv_ctx
->wait_queue
,
121 msecs_to_jiffies(timeout
))) {
122 if (block
->ret_code
< 0)
123 pr_err("sst: stream failed %d\n", block
->ret_code
);
125 pr_debug("sst: event up\n");
126 retval
= block
->ret_code
;
129 pr_err("sst: timeout occured...\n");
130 /*setting firmware state as uninit so that the
131 firmware will get re-downloaded on next request
132 this is because firmare not responding for 5 sec
133 is equalant to some unrecoverable error of FW
134 sst_drv_ctx->sst_state = SST_UN_INIT;*/
143 * sst_wait_timeout - wait on event for timeout
145 * @sst_drv_ctx: Driver context
146 * @block: Driver block to wait on
148 * This function waits with a timeout value (and is not interruptible) on a
151 int sst_wait_timeout(struct intel_sst_drv
*sst_drv_ctx
,
152 struct stream_alloc_block
*block
)
157 Observed that FW processes the alloc msg and replies even
158 before the alloc thread has finished execution */
159 pr_debug("sst: waiting for %x, condition %x\n",
160 block
->sst_id
, block
->ops_block
.condition
);
161 if (wait_event_interruptible_timeout(sst_drv_ctx
->wait_queue
,
162 block
->ops_block
.condition
,
163 msecs_to_jiffies(SST_BLOCK_TIMEOUT
))) {
165 pr_debug("sst: Event wake %x\n", block
->ops_block
.condition
);
166 pr_debug("sst: message ret: %d\n", block
->ops_block
.ret_code
);
167 retval
= block
->ops_block
.ret_code
;
169 block
->ops_block
.on
= false;
170 pr_err("sst: Wait timed-out %x\n", block
->ops_block
.condition
);
171 /* settign firmware state as uninit so that the
172 firmware will get redownloaded on next request
173 this is because firmare not responding for 5 sec
174 is equalant to some unrecoverable error of FW
175 sst_drv_ctx->sst_state = SST_UN_INIT;*/
183 * sst_create_large_msg - create a large IPC message
187 * this function allocates structures to send a large message to the firmware
189 int sst_create_large_msg(struct ipc_post
**arg
)
191 struct ipc_post
*msg
;
193 msg
= kzalloc(sizeof(struct ipc_post
), GFP_ATOMIC
);
195 pr_err("sst: kzalloc msg failed\n");
199 msg
->mailbox_data
= kzalloc(SST_MAILBOX_SIZE
, GFP_ATOMIC
);
200 if (!msg
->mailbox_data
) {
202 pr_err("sst: kzalloc mailbox_data failed");
210 * sst_create_short_msg - create a short IPC message
214 * this function allocates structures to send a short message to the firmware
216 int sst_create_short_msg(struct ipc_post
**arg
)
218 struct ipc_post
*msg
;
220 msg
= kzalloc(sizeof(*msg
), GFP_ATOMIC
);
222 pr_err("sst: kzalloc msg failed\n");
225 msg
->mailbox_data
= NULL
;
231 * sst_clean_stream - clean the stream context
233 * @stream: stream structure
235 * this function resets the stream contexts
236 * should be called in free
238 void sst_clean_stream(struct stream_info
*stream
)
240 struct sst_stream_bufs
*bufs
= NULL
, *_bufs
;
241 stream
->status
= STREAM_UN_INIT
;
242 stream
->prev
= STREAM_UN_INIT
;
243 mutex_lock(&stream
->lock
);
244 list_for_each_entry_safe(bufs
, _bufs
, &stream
->bufs
, node
) {
245 list_del(&bufs
->node
);
248 mutex_unlock(&stream
->lock
);
250 if (stream
->ops
!= STREAM_OPS_PLAYBACK_DRM
)
251 kfree(stream
->decode_ibuf
);
255 * sst_wake_up_alloc_block - wake up waiting block
257 * @sst_drv_ctx: Driver context
259 * @status: status of wakeup
260 * @data: data pointer of wakeup
262 * This function wakes up a sleeping block event based on the response
264 void sst_wake_up_alloc_block(struct intel_sst_drv
*sst_drv_ctx
,
265 u8 sst_id
, int status
, void *data
)
269 /* Unblock with retval code */
270 for (i
= 0; i
< MAX_ACTIVE_STREAM
; i
++) {
271 if (sst_id
== sst_drv_ctx
->alloc_block
[i
].sst_id
) {
272 sst_drv_ctx
->alloc_block
[i
].ops_block
.condition
= true;
273 sst_drv_ctx
->alloc_block
[i
].ops_block
.ret_code
= status
;
274 sst_drv_ctx
->alloc_block
[i
].ops_block
.data
= data
;
275 wake_up(&sst_drv_ctx
->wait_queue
);
282 * sst_enable_rx_timeslot - Send msg to query for stream parameters
283 * @status: rx timeslot to be enabled
285 * This function is called when the RX timeslot is required to be enabled
287 int sst_enable_rx_timeslot(int status
)
290 struct ipc_post
*msg
= NULL
;
292 if (sst_create_short_msg(&msg
)) {
293 pr_err("sst: mem allocation failed\n");
296 pr_debug("sst: ipc message sending: ENABLE_RX_TIME_SLOT\n");
297 sst_fill_header(&msg
->header
, IPC_IA_ENABLE_RX_TIME_SLOT
, 0, 0);
298 msg
->header
.part
.data
= status
;
299 sst_drv_ctx
->hs_info_blk
.condition
= false;
300 sst_drv_ctx
->hs_info_blk
.ret_code
= 0;
301 sst_drv_ctx
->hs_info_blk
.on
= true;
302 spin_lock(&sst_drv_ctx
->list_spin_lock
);
303 list_add_tail(&msg
->node
,
304 &sst_drv_ctx
->ipc_dispatch_list
);
305 spin_unlock(&sst_drv_ctx
->list_spin_lock
);
306 sst_post_message(&sst_drv_ctx
->ipc_post_msg_wq
);
307 retval
= sst_wait_interruptible_timeout(sst_drv_ctx
,
308 &sst_drv_ctx
->hs_info_blk
, SST_BLOCK_TIMEOUT
);