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