Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelv...
[pandora-kernel.git] / drivers / staging / intel_sst / intel_sst_ipc.c
1 /*
2  *  intel_sst_ipc.c - Intel SST Driver for audio engine
3  *
4  *  Copyright (C) 2008-10 Intel Corporation
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 file defines all ipc functions
27  */
28
29 #include <linux/pci.h>
30 #include <linux/firmware.h>
31 #include <linux/sched.h>
32 #include "intel_sst.h"
33 #include "intel_sst_ioctl.h"
34 #include "intel_sst_fw_ipc.h"
35 #include "intel_sst_common.h"
36
37 /*
38  * sst_send_sound_card_type - send sound card type
39  *
40  * this function sends the sound card type to sst dsp engine
41  */
42 static void sst_send_sound_card_type(void)
43 {
44         struct ipc_post *msg = NULL;
45
46         if (sst_create_short_msg(&msg))
47                 return;
48
49         sst_fill_header(&msg->header, IPC_IA_SET_PMIC_TYPE, 0, 0);
50         msg->header.part.data = sst_drv_ctx->pmic_vendor;
51         spin_lock(&sst_drv_ctx->list_spin_lock);
52         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
53         spin_unlock(&sst_drv_ctx->list_spin_lock);
54         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
55         return;
56 }
57
58 /**
59 * sst_post_message - Posts message to SST
60 *
61 * @work: Pointer to work structure
62 *
63 * This function is called by any component in driver which
64 * wants to send an IPC message. This will post message only if
65 * busy bit is free
66 */
67 void sst_post_message(struct work_struct *work)
68 {
69         struct ipc_post *msg;
70         union ipc_header header;
71         union  interrupt_reg imr;
72         int retval = 0;
73         imr.full = 0;
74
75         /*To check if LPE is in stalled state.*/
76         retval = sst_stalled();
77         if (retval < 0) {
78                 pr_err("sst: in stalled state\n");
79                 return;
80         }
81         pr_debug("sst: post message called\n");
82         spin_lock(&sst_drv_ctx->list_spin_lock);
83
84         /* check list */
85         if (list_empty(&sst_drv_ctx->ipc_dispatch_list)) {
86                 /* list is empty, mask imr */
87                 pr_debug("sst: Empty msg queue... masking\n");
88                 imr.full = readl(sst_drv_ctx->shim + SST_IMRX);
89                 imr.part.done_interrupt = 1;
90                 /* dummy register for shim workaround */
91                 sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
92                 spin_unlock(&sst_drv_ctx->list_spin_lock);
93                 return;
94         }
95
96         /* check busy bit */
97         header.full = sst_shim_read(sst_drv_ctx->shim, SST_IPCX);
98         if (header.part.busy) {
99                 /* busy, unmask */
100                 pr_debug("sst: Busy not free... unmasking\n");
101                 imr.full = readl(sst_drv_ctx->shim + SST_IMRX);
102                 imr.part.done_interrupt = 0;
103                 /* dummy register for shim workaround */
104                 sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
105                 spin_unlock(&sst_drv_ctx->list_spin_lock);
106                 return;
107         }
108         /* copy msg from list */
109         msg = list_entry(sst_drv_ctx->ipc_dispatch_list.next,
110                         struct ipc_post, node);
111         list_del(&msg->node);
112         pr_debug("sst: Post message: header = %x\n", msg->header.full);
113         pr_debug("sst: size: = %x\n", msg->header.part.data);
114         if (msg->header.part.large)
115                 memcpy_toio(sst_drv_ctx->mailbox + SST_MAILBOX_SEND,
116                         msg->mailbox_data, msg->header.part.data);
117         /* dummy register for shim workaround */
118
119         sst_shim_write(sst_drv_ctx->shim, SST_IPCX, msg->header.full);
120         spin_unlock(&sst_drv_ctx->list_spin_lock);
121
122         kfree(msg->mailbox_data);
123         kfree(msg);
124         return;
125 }
126
127 /*
128  * sst_clear_interrupt - clear the SST FW interrupt
129  *
130  * This function clears the interrupt register after the interrupt
131  * bottom half is complete allowing next interrupt to arrive
132  */
133 void sst_clear_interrupt(void)
134 {
135         union interrupt_reg isr;
136         union interrupt_reg imr;
137         union ipc_header clear_ipc;
138
139         imr.full = sst_shim_read(sst_drv_ctx->shim, SST_IMRX);
140         isr.full = sst_shim_read(sst_drv_ctx->shim, SST_ISRX);
141         /*  write 1 to clear  */;
142         isr.part.busy_interrupt = 1;
143         sst_shim_write(sst_drv_ctx->shim, SST_ISRX, isr.full);
144         /* Set IA done bit */
145         clear_ipc.full = sst_shim_read(sst_drv_ctx->shim, SST_IPCD);
146         clear_ipc.part.busy = 0;
147         clear_ipc.part.done = 1;
148         clear_ipc.part.data = IPC_ACK_SUCCESS;
149         sst_shim_write(sst_drv_ctx->shim, SST_IPCD, clear_ipc.full);
150         /* un mask busy interrupt */
151         imr.part.busy_interrupt = 0;
152         sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
153 }
154
155 /*
156  * process_fw_init - process the FW init msg
157  *
158  * @msg: IPC message from FW
159  *
160  * This function processes the FW init msg from FW
161  * marks FW state and prints debug info of loaded FW
162  */
163 int process_fw_init(struct sst_ipc_msg_wq *msg)
164 {
165         struct ipc_header_fw_init *init =
166                 (struct ipc_header_fw_init *)msg->mailbox;
167         int retval = 0;
168
169         pr_debug("sst: *** FW Init msg came***\n");
170         if (init->result) {
171                 mutex_lock(&sst_drv_ctx->sst_lock);
172                 sst_drv_ctx->sst_state = SST_ERROR;
173                 mutex_unlock(&sst_drv_ctx->sst_lock);
174                 pr_debug("sst: FW Init failed, Error %x\n", init->result);
175                 pr_err("sst: FW Init failed, Error %x\n", init->result);
176                 retval = -init->result;
177                 return retval;
178         }
179         if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
180                 sst_send_sound_card_type();
181         mutex_lock(&sst_drv_ctx->sst_lock);
182         sst_drv_ctx->sst_state = SST_FW_RUNNING;
183         mutex_unlock(&sst_drv_ctx->sst_lock);
184         pr_debug("sst: FW Version %x.%x\n",
185                         init->fw_version.major, init->fw_version.minor);
186         pr_debug("sst: Build No %x Type %x\n",
187                         init->fw_version.build, init->fw_version.type);
188         pr_debug("sst:  Build date %s Time %s\n",
189                         init->build_info.date, init->build_info.time);
190         sst_wake_up_alloc_block(sst_drv_ctx, FW_DWNL_ID, retval, NULL);
191         return retval;
192 }
193 /**
194 * sst_process_message - Processes message from SST
195 *
196 * @work:        Pointer to work structure
197 *
198 * This function is scheduled by ISR
199 * It take a msg from process_queue and does action based on msg
200 */
201 void sst_process_message(struct work_struct *work)
202 {
203         struct sst_ipc_msg_wq *msg =
204                         container_of(work, struct sst_ipc_msg_wq, wq);
205         int str_id = msg->header.part.str_id;
206
207         pr_debug("sst: IPC process for %x\n", msg->header.full);
208
209         /* based on msg in list call respective handler */
210         switch (msg->header.part.msg_id) {
211         case IPC_SST_BUF_UNDER_RUN:
212         case IPC_SST_BUF_OVER_RUN:
213                 if (sst_validate_strid(str_id)) {
214                         pr_err("sst:  stream id %d invalid\n", str_id);
215                         break;
216                 }
217                 pr_err("sst: Buffer under/overrun for%d\n",
218                                 msg->header.part.str_id);
219                 pr_err("sst: Got Underrun & not to send data...ignore\n");
220                 break;
221
222         case IPC_SST_GET_PLAY_FRAMES:
223                 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
224                         struct stream_info *stream ;
225
226                         if (sst_validate_strid(str_id)) {
227                                 pr_err("sst: strid %d invalid\n", str_id);
228                                 break;
229                         }
230                         /* call sst_play_frame */
231                         stream = &sst_drv_ctx->streams[str_id];
232                         pr_debug("sst: sst_play_frames for %d\n",
233                                         msg->header.part.str_id);
234                         mutex_lock(&sst_drv_ctx->streams[str_id].lock);
235                         sst_play_frame(msg->header.part.str_id);
236                         mutex_unlock(&sst_drv_ctx->streams[str_id].lock);
237                         break;
238                 } else
239                         pr_err("sst: sst_play_frames for Penwell!!\n");
240
241         case IPC_SST_GET_CAPT_FRAMES:
242                 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
243                         struct stream_info *stream;
244                         /* call sst_capture_frame */
245                         if (sst_validate_strid(str_id)) {
246                                 pr_err("sst: str id %d invalid\n", str_id);
247                                 break;
248                         }
249                         stream = &sst_drv_ctx->streams[str_id];
250                         pr_debug("sst: sst_capture_frames for %d\n",
251                                         msg->header.part.str_id);
252                         mutex_lock(&stream->lock);
253                         if (stream->mmapped == false &&
254                                         stream->src == SST_DRV) {
255                                 pr_debug("sst: waking up block for copy.\n");
256                                 stream->data_blk.ret_code = 0;
257                                 stream->data_blk.condition = true;
258                                 stream->data_blk.on = false;
259                                 wake_up(&sst_drv_ctx->wait_queue);
260                         } else
261                                 sst_capture_frame(msg->header.part.str_id);
262                         mutex_unlock(&stream->lock);
263                 } else
264                         pr_err("sst: sst_play_frames for Penwell!!\n");
265                 break;
266
267         case IPC_IA_PRINT_STRING:
268                 pr_debug("sst: been asked to print something by fw\n");
269                 /* TBD */
270                 break;
271
272         case IPC_IA_FW_INIT_CMPLT: {
273                 /* send next data to FW */
274                 process_fw_init(msg);
275                 break;
276         }
277
278         case IPC_SST_STREAM_PROCESS_FATAL_ERR:
279                 if (sst_validate_strid(str_id)) {
280                         pr_err("sst: stream id %d invalid\n", str_id);
281                         break;
282                 }
283                 pr_err("sst: codec fatal error %x stream %d...\n",
284                                 msg->header.full, msg->header.part.str_id);
285                 pr_err("sst: Dropping the stream\n");
286                 sst_drop_stream(msg->header.part.str_id);
287                 break;
288         case IPC_IA_LPE_GETTING_STALLED:
289                 sst_drv_ctx->lpe_stalled = 1;
290                 break;
291         case IPC_IA_LPE_UNSTALLED:
292                 sst_drv_ctx->lpe_stalled = 0;
293                 break;
294         default:
295                 /* Illegal case */
296                 pr_err("sst: Unhandled msg %x header %x\n",
297                 msg->header.part.msg_id, msg->header.full);
298         }
299         sst_clear_interrupt();
300         return;
301 }
302
303 /**
304 * sst_process_reply - Processes reply message from SST
305 *
306 * @work:        Pointer to work structure
307 *
308 * This function is scheduled by ISR
309 * It take a reply msg from response_queue and
310 * does action based on msg
311 */
312 void sst_process_reply(struct work_struct *work)
313 {
314         struct sst_ipc_msg_wq *msg =
315                         container_of(work, struct sst_ipc_msg_wq, wq);
316
317         int str_id = msg->header.part.str_id;
318         struct stream_info *str_info;
319
320         switch (msg->header.part.msg_id) {
321         case IPC_IA_TARGET_DEV_SELECT:
322                 if (!msg->header.part.data) {
323                         sst_drv_ctx->tgt_dev_blk.ret_code = 0;
324                 } else {
325                         pr_err("sst:  Msg %x reply error %x\n",
326                         msg->header.part.msg_id, msg->header.part.data);
327                         sst_drv_ctx->tgt_dev_blk.ret_code =
328                                         -msg->header.part.data;
329                 }
330
331                 if (sst_drv_ctx->tgt_dev_blk.on == true) {
332                                 sst_drv_ctx->tgt_dev_blk.condition = true;
333                                 wake_up(&sst_drv_ctx->wait_queue);
334                 }
335                 break;
336         case IPC_IA_GET_FW_INFO: {
337                 struct snd_sst_fw_info *fw_info =
338                         (struct snd_sst_fw_info *)msg->mailbox;
339                 if (msg->header.part.large) {
340                         int major = fw_info->fw_version.major;
341                         int minor = fw_info->fw_version.minor;
342                         int build = fw_info->fw_version.build;
343                         pr_debug("sst: Msg succedded %x\n",
344                                        msg->header.part.msg_id);
345                         pr_debug("INFO: ***FW*** = %02d.%02d.%02d\n",
346                                         major, minor, build);
347                         memcpy_fromio(sst_drv_ctx->fw_info_blk.data,
348                                 ((struct snd_sst_fw_info *)(msg->mailbox)),
349                                 sizeof(struct snd_sst_fw_info));
350                         sst_drv_ctx->fw_info_blk.ret_code = 0;
351                 } else {
352                         pr_err("sst:  Msg %x reply error %x\n",
353                         msg->header.part.msg_id, msg->header.part.data);
354                         sst_drv_ctx->fw_info_blk.ret_code =
355                                         -msg->header.part.data;
356                 }
357                 if (sst_drv_ctx->fw_info_blk.on == true) {
358                         pr_debug("sst: Memcopy succedded\n");
359                         sst_drv_ctx->fw_info_blk.on = false;
360                         sst_drv_ctx->fw_info_blk.condition = true;
361                         wake_up(&sst_drv_ctx->wait_queue);
362                 }
363                 break;
364         }
365         case IPC_IA_SET_STREAM_MUTE:
366                 if (!msg->header.part.data) {
367                         pr_debug("sst: Msg succedded %x\n",
368                                        msg->header.part.msg_id);
369                         sst_drv_ctx->mute_info_blk.ret_code = 0;
370                 } else {
371                         pr_err("sst:  Msg %x reply error %x\n",
372                         msg->header.part.msg_id, msg->header.part.data);
373                         sst_drv_ctx->mute_info_blk.ret_code =
374                                         -msg->header.part.data;
375
376                 }
377                 if (sst_drv_ctx->mute_info_blk.on == true) {
378                         sst_drv_ctx->mute_info_blk.on = false;
379                         sst_drv_ctx->mute_info_blk.condition = true;
380                         wake_up(&sst_drv_ctx->wait_queue);
381                 }
382                 break;
383         case IPC_IA_SET_STREAM_VOL:
384                 if (!msg->header.part.data) {
385                         pr_debug("sst: Msg succedded %x\n",
386                                        msg->header.part.msg_id);
387                         sst_drv_ctx->vol_info_blk.ret_code = 0;
388                 } else {
389                         pr_err("sst:  Msg %x reply error %x\n",
390                                         msg->header.part.msg_id,
391                         msg->header.part.data);
392                         sst_drv_ctx->vol_info_blk.ret_code =
393                                         -msg->header.part.data;
394
395                 }
396
397                 if (sst_drv_ctx->vol_info_blk.on == true) {
398                         sst_drv_ctx->vol_info_blk.on = false;
399                         sst_drv_ctx->vol_info_blk.condition = true;
400                         wake_up(&sst_drv_ctx->wait_queue);
401                 }
402                 break;
403         case IPC_IA_GET_STREAM_VOL:
404                 if (msg->header.part.large) {
405                         pr_debug("sst: Large Msg Received Successfully\n");
406                         pr_debug("sst: Msg succedded %x\n",
407                                        msg->header.part.msg_id);
408                         memcpy_fromio(sst_drv_ctx->vol_info_blk.data,
409                                 (void *) msg->mailbox,
410                                 sizeof(struct snd_sst_vol));
411                         sst_drv_ctx->vol_info_blk.ret_code = 0;
412                 } else {
413                         pr_err("sst: Msg %x reply error %x\n",
414                         msg->header.part.msg_id, msg->header.part.data);
415                         sst_drv_ctx->vol_info_blk.ret_code =
416                                         -msg->header.part.data;
417                 }
418                 if (sst_drv_ctx->vol_info_blk.on == true) {
419                         sst_drv_ctx->vol_info_blk.on = false;
420                         sst_drv_ctx->vol_info_blk.condition = true;
421                         wake_up(&sst_drv_ctx->wait_queue);
422                 }
423                 break;
424
425         case IPC_IA_GET_STREAM_PARAMS:
426                 if (sst_validate_strid(str_id)) {
427                         pr_err("sst: stream id %d invalid\n", str_id);
428                         break;
429                 }
430                 str_info = &sst_drv_ctx->streams[str_id];
431                 if (msg->header.part.large) {
432                         pr_debug("sst: Get stream large success\n");
433                         memcpy_fromio(str_info->ctrl_blk.data,
434                                 ((void *)(msg->mailbox)),
435                                 sizeof(struct snd_sst_fw_get_stream_params));
436                         str_info->ctrl_blk.ret_code = 0;
437                 } else {
438                         pr_err("sst: Msg %x reply error %x\n",
439                                 msg->header.part.msg_id, msg->header.part.data);
440                         str_info->ctrl_blk.ret_code = -msg->header.part.data;
441                 }
442                 if (str_info->ctrl_blk.on == true) {
443                         str_info->ctrl_blk.on = false;
444                         str_info->ctrl_blk.condition = true;
445                         wake_up(&sst_drv_ctx->wait_queue);
446                 }
447                 break;
448         case IPC_IA_DECODE_FRAMES:
449                 if (sst_validate_strid(str_id)) {
450                         pr_err("sst: stream id %d invalid\n", str_id);
451                         break;
452                 }
453                 str_info = &sst_drv_ctx->streams[str_id];
454                 if (msg->header.part.large) {
455                         pr_debug("sst: Msg succedded %x\n",
456                                        msg->header.part.msg_id);
457                         memcpy_fromio(str_info->data_blk.data,
458                                         ((void *)(msg->mailbox)),
459                                         sizeof(struct snd_sst_decode_info));
460                         str_info->data_blk.ret_code = 0;
461                 } else {
462                         pr_err("sst: Msg %x reply error %x\n",
463                                 msg->header.part.msg_id, msg->header.part.data);
464                         str_info->data_blk.ret_code = -msg->header.part.data;
465                 }
466                 if (str_info->data_blk.on == true) {
467                         str_info->data_blk.on = false;
468                         str_info->data_blk.condition = true;
469                         wake_up(&sst_drv_ctx->wait_queue);
470                 }
471                 break;
472         case IPC_IA_DRAIN_STREAM:
473                 if (sst_validate_strid(str_id)) {
474                         pr_err("sst: stream id %d invalid\n", str_id);
475                         break;
476                 }
477                 str_info = &sst_drv_ctx->streams[str_id];
478                 if (!msg->header.part.data) {
479                         pr_debug("sst: Msg succedded %x\n",
480                                         msg->header.part.msg_id);
481                         str_info->ctrl_blk.ret_code = 0;
482
483                 } else {
484                         pr_err("sst:  Msg %x reply error %x\n",
485                                 msg->header.part.msg_id, msg->header.part.data);
486                         str_info->ctrl_blk.ret_code = -msg->header.part.data;
487
488                 }
489                 str_info = &sst_drv_ctx->streams[str_id];
490                 if (str_info->data_blk.on == true) {
491                         str_info->data_blk.on = false;
492                         str_info->data_blk.condition = true;
493                         wake_up(&sst_drv_ctx->wait_queue);
494                 }
495                 break;
496
497         case IPC_IA_DROP_STREAM:
498                 if (sst_validate_strid(str_id)) {
499                         pr_err("sst: str id %d invalid\n", str_id);
500                         break;
501                 }
502                 str_info = &sst_drv_ctx->streams[str_id];
503                 if (msg->header.part.large) {
504                         struct snd_sst_drop_response *drop_resp =
505                                 (struct snd_sst_drop_response *)msg->mailbox;
506
507                         pr_debug("sst: Drop ret bytes %x\n", drop_resp->bytes);
508
509                         str_info->curr_bytes = drop_resp->bytes;
510                         str_info->ctrl_blk.ret_code =  0;
511                 } else {
512                         pr_err("sst:  Msg %x reply error %x\n",
513                                 msg->header.part.msg_id, msg->header.part.data);
514                         str_info->ctrl_blk.ret_code = -msg->header.part.data;
515                 }
516                 if (str_info->ctrl_blk.on == true) {
517                         str_info->ctrl_blk.on = false;
518                         str_info->ctrl_blk.condition = true;
519                         wake_up(&sst_drv_ctx->wait_queue);
520                 }
521                 break;
522         case IPC_IA_ENABLE_RX_TIME_SLOT:
523                 if (!msg->header.part.data) {
524                         pr_debug("sst: RX_TIME_SLOT success\n");
525                         sst_drv_ctx->hs_info_blk.ret_code = 0;
526                 } else {
527                         pr_err("sst:  Msg %x reply error %x\n",
528                                 msg->header.part.msg_id,
529                                 msg->header.part.data);
530                         sst_drv_ctx->hs_info_blk.ret_code =
531                                 -msg->header.part.data;
532                 }
533                 if (sst_drv_ctx->hs_info_blk.on == true) {
534                         sst_drv_ctx->hs_info_blk.on = false;
535                         sst_drv_ctx->hs_info_blk.condition = true;
536                         wake_up(&sst_drv_ctx->wait_queue);
537                 }
538                 break;
539         case IPC_IA_PAUSE_STREAM:
540         case IPC_IA_RESUME_STREAM:
541         case IPC_IA_SET_STREAM_PARAMS:
542                 str_info = &sst_drv_ctx->streams[str_id];
543                 if (!msg->header.part.data) {
544                         pr_debug("sst: Msg succedded %x\n",
545                                         msg->header.part.msg_id);
546                         str_info->ctrl_blk.ret_code = 0;
547                 } else {
548                         pr_err("sst:  Msg %x reply error %x\n",
549                                         msg->header.part.msg_id,
550                                         msg->header.part.data);
551                         str_info->ctrl_blk.ret_code = -msg->header.part.data;
552                 }
553                 if (sst_validate_strid(str_id)) {
554                         pr_err("sst:  stream id %d invalid\n", str_id);
555                         break;
556                 }
557
558                 if (str_info->ctrl_blk.on == true) {
559                         str_info->ctrl_blk.on = false;
560                         str_info->ctrl_blk.condition = true;
561                         wake_up(&sst_drv_ctx->wait_queue);
562                 }
563                 break;
564
565         case IPC_IA_FREE_STREAM:
566                 if (!msg->header.part.data) {
567                         pr_debug("sst: Stream %d freed\n", str_id);
568                 } else {
569                         pr_err("sst: Free for %d ret error %x\n",
570                                        str_id, msg->header.part.data);
571                 }
572                 break;
573         case IPC_IA_ALLOC_STREAM: {
574                 /* map to stream, call play */
575                 struct snd_sst_alloc_response *resp =
576                                 (struct snd_sst_alloc_response *)msg->mailbox;
577                 if (resp->str_type.result)
578                         pr_err("sst: error alloc stream = %x\n",
579                                        resp->str_type.result);
580                 sst_alloc_stream_response(str_id, resp);
581                 break;
582         }
583
584         case IPC_IA_PLAY_FRAMES:
585         case IPC_IA_CAPT_FRAMES:
586                 if (sst_validate_strid(str_id)) {
587                         pr_err("sst: stream id %d invalid\n" , str_id);
588                         break;
589                 }
590                 pr_debug("sst: Ack for play/capt frames recived\n");
591                 break;
592
593         case IPC_IA_PREP_LIB_DNLD: {
594                 struct snd_sst_str_type *str_type =
595                         (struct snd_sst_str_type *)msg->mailbox;
596                 pr_debug("sst: Prep Lib download %x\n",
597                                 msg->header.part.msg_id);
598                 if (str_type->result)
599                         pr_err("sst: Prep lib download %x\n", str_type->result);
600                 else
601                         pr_debug("sst: Can download codec now...\n");
602                 sst_wake_up_alloc_block(sst_drv_ctx, str_id,
603                                 str_type->result, NULL);
604                 break;
605         }
606
607         case IPC_IA_LIB_DNLD_CMPLT: {
608                 struct snd_sst_lib_download_info *resp =
609                         (struct snd_sst_lib_download_info *)msg->mailbox;
610                 int retval = resp->result;
611
612                 pr_debug("sst: Lib downloaded %x\n", msg->header.part.msg_id);
613                 if (resp->result) {
614                         pr_err("sst: err in lib dload %x\n", resp->result);
615                 } else {
616                         pr_debug("sst: Codec download complete...\n");
617                         pr_debug("sst: codec Type %d Ver %d Built %s: %s\n",
618                                 resp->dload_lib.lib_info.lib_type,
619                                 resp->dload_lib.lib_info.lib_version,
620                                 resp->dload_lib.lib_info.b_date,
621                                 resp->dload_lib.lib_info.b_time);
622                 }
623                 sst_wake_up_alloc_block(sst_drv_ctx, str_id,
624                                                 retval, NULL);
625                 break;
626         }
627
628         case IPC_IA_GET_FW_VERSION: {
629                 struct ipc_header_fw_init *version =
630                                 (struct ipc_header_fw_init *)msg->mailbox;
631                 int major = version->fw_version.major;
632                 int minor = version->fw_version.minor;
633                 int build = version->fw_version.build;
634                 dev_info(&sst_drv_ctx->pci->dev,
635                         "INFO: ***LOADED SST FW VERSION*** = %02d.%02d.%02d\n",
636                 major, minor, build);
637                 break;
638         }
639         case IPC_IA_GET_FW_BUILD_INF: {
640                 struct sst_fw_build_info *build =
641                         (struct sst_fw_build_info *)msg->mailbox;
642                 pr_debug("sst: Build date:%sTime:%s", build->date, build->time);
643                 break;
644         }
645         case IPC_IA_SET_PMIC_TYPE:
646                 break;
647         case IPC_IA_START_STREAM:
648                 pr_debug("sst: reply for START STREAM %x\n", msg->header.full);
649                 break;
650         default:
651                 /* Illegal case */
652                 pr_err("sst: process reply:default = %x\n", msg->header.full);
653         }
654         sst_clear_interrupt();
655         return;
656 }