diff options
author | Jin Yao <yao.jin@linux.intel.com> | 2015-04-06 21:33:31 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-04-10 14:00:45 -0400 |
commit | 48cec59b6f383c63b2b828b93656ee2030abecc0 (patch) | |
tree | 1cc8159082087d69f06a8b4b73fa5b5f56a3936f | |
parent | a33c1ec5cf82efb76f0e7339b13f11cfb53a2a2f (diff) |
ASoC: Intel: Use the generic IPC/mailbox APIs in Baytrail
Use the generic IPC/mailbox APIs to replace the original processing
code for Baytrail platform.
Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Acked-by: Jie Yang <yang.jie@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/intel/baytrail/sst-baytrail-ipc.c | 360 |
1 files changed, 77 insertions, 283 deletions
diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c index aabb9b0f48b8..1efb33b36303 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c +++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "sst-baytrail-ipc.h" | 31 | #include "sst-baytrail-ipc.h" |
32 | #include "../common/sst-dsp.h" | 32 | #include "../common/sst-dsp.h" |
33 | #include "../common/sst-dsp-priv.h" | 33 | #include "../common/sst-dsp-priv.h" |
34 | #include "../common/sst-ipc.h" | ||
34 | 35 | ||
35 | /* IPC message timeout */ | 36 | /* IPC message timeout */ |
36 | #define IPC_TIMEOUT_MSECS 300 | 37 | #define IPC_TIMEOUT_MSECS 300 |
@@ -142,23 +143,6 @@ struct sst_byt_fw_init { | |||
142 | u8 debug_info; | 143 | u8 debug_info; |
143 | } __packed; | 144 | } __packed; |
144 | 145 | ||
145 | /* driver internal IPC message structure */ | ||
146 | struct ipc_message { | ||
147 | struct list_head list; | ||
148 | u64 header; | ||
149 | |||
150 | /* direction wrt host CPU */ | ||
151 | char tx_data[SST_BYT_IPC_MAX_PAYLOAD_SIZE]; | ||
152 | size_t tx_size; | ||
153 | char rx_data[SST_BYT_IPC_MAX_PAYLOAD_SIZE]; | ||
154 | size_t rx_size; | ||
155 | |||
156 | wait_queue_head_t waitq; | ||
157 | bool complete; | ||
158 | bool wait; | ||
159 | int errno; | ||
160 | }; | ||
161 | |||
162 | struct sst_byt_stream; | 146 | struct sst_byt_stream; |
163 | struct sst_byt; | 147 | struct sst_byt; |
164 | 148 | ||
@@ -195,14 +179,7 @@ struct sst_byt { | |||
195 | struct sst_fw *fw; | 179 | struct sst_fw *fw; |
196 | 180 | ||
197 | /* IPC messaging */ | 181 | /* IPC messaging */ |
198 | struct list_head tx_list; | 182 | struct sst_generic_ipc ipc; |
199 | struct list_head rx_list; | ||
200 | struct list_head empty_list; | ||
201 | wait_queue_head_t wait_txq; | ||
202 | struct task_struct *tx_thread; | ||
203 | struct kthread_worker kworker; | ||
204 | struct kthread_work kwork; | ||
205 | struct ipc_message *msg; | ||
206 | }; | 183 | }; |
207 | 184 | ||
208 | static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id) | 185 | static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id) |
@@ -246,209 +223,6 @@ static struct sst_byt_stream *sst_byt_get_stream(struct sst_byt *byt, | |||
246 | return NULL; | 223 | return NULL; |
247 | } | 224 | } |
248 | 225 | ||
249 | static void sst_byt_ipc_shim_dbg(struct sst_byt *byt, const char *text) | ||
250 | { | ||
251 | struct sst_dsp *sst = byt->dsp; | ||
252 | u64 isr, ipcd, imrx, ipcx; | ||
253 | |||
254 | ipcx = sst_dsp_shim_read64_unlocked(sst, SST_IPCX); | ||
255 | isr = sst_dsp_shim_read64_unlocked(sst, SST_ISRX); | ||
256 | ipcd = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); | ||
257 | imrx = sst_dsp_shim_read64_unlocked(sst, SST_IMRX); | ||
258 | |||
259 | dev_err(byt->dev, | ||
260 | "ipc: --%s-- ipcx 0x%llx isr 0x%llx ipcd 0x%llx imrx 0x%llx\n", | ||
261 | text, ipcx, isr, ipcd, imrx); | ||
262 | } | ||
263 | |||
264 | /* locks held by caller */ | ||
265 | static struct ipc_message *sst_byt_msg_get_empty(struct sst_byt *byt) | ||
266 | { | ||
267 | struct ipc_message *msg = NULL; | ||
268 | |||
269 | if (!list_empty(&byt->empty_list)) { | ||
270 | msg = list_first_entry(&byt->empty_list, | ||
271 | struct ipc_message, list); | ||
272 | list_del(&msg->list); | ||
273 | } | ||
274 | |||
275 | return msg; | ||
276 | } | ||
277 | |||
278 | static void sst_byt_ipc_tx_msgs(struct kthread_work *work) | ||
279 | { | ||
280 | struct sst_byt *byt = | ||
281 | container_of(work, struct sst_byt, kwork); | ||
282 | struct ipc_message *msg; | ||
283 | u64 ipcx; | ||
284 | unsigned long flags; | ||
285 | |||
286 | spin_lock_irqsave(&byt->dsp->spinlock, flags); | ||
287 | if (list_empty(&byt->tx_list)) { | ||
288 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
289 | return; | ||
290 | } | ||
291 | |||
292 | /* if the DSP is busy we will TX messages after IRQ */ | ||
293 | ipcx = sst_dsp_shim_read64_unlocked(byt->dsp, SST_IPCX); | ||
294 | if (ipcx & SST_BYT_IPCX_BUSY) { | ||
295 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
296 | return; | ||
297 | } | ||
298 | |||
299 | msg = list_first_entry(&byt->tx_list, struct ipc_message, list); | ||
300 | |||
301 | list_move(&msg->list, &byt->rx_list); | ||
302 | |||
303 | /* send the message */ | ||
304 | if (msg->header & IPC_HEADER_LARGE(true)) | ||
305 | sst_dsp_outbox_write(byt->dsp, msg->tx_data, msg->tx_size); | ||
306 | sst_dsp_shim_write64_unlocked(byt->dsp, SST_IPCX, msg->header); | ||
307 | |||
308 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
309 | } | ||
310 | |||
311 | static inline void sst_byt_tx_msg_reply_complete(struct sst_byt *byt, | ||
312 | struct ipc_message *msg) | ||
313 | { | ||
314 | msg->complete = true; | ||
315 | |||
316 | if (!msg->wait) | ||
317 | list_add_tail(&msg->list, &byt->empty_list); | ||
318 | else | ||
319 | wake_up(&msg->waitq); | ||
320 | } | ||
321 | |||
322 | static void sst_byt_drop_all(struct sst_byt *byt) | ||
323 | { | ||
324 | struct ipc_message *msg, *tmp; | ||
325 | unsigned long flags; | ||
326 | |||
327 | /* drop all TX and Rx messages before we stall + reset DSP */ | ||
328 | spin_lock_irqsave(&byt->dsp->spinlock, flags); | ||
329 | list_for_each_entry_safe(msg, tmp, &byt->tx_list, list) { | ||
330 | list_move(&msg->list, &byt->empty_list); | ||
331 | } | ||
332 | |||
333 | list_for_each_entry_safe(msg, tmp, &byt->rx_list, list) { | ||
334 | list_move(&msg->list, &byt->empty_list); | ||
335 | } | ||
336 | |||
337 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
338 | } | ||
339 | |||
340 | static int sst_byt_tx_wait_done(struct sst_byt *byt, struct ipc_message *msg, | ||
341 | void *rx_data) | ||
342 | { | ||
343 | unsigned long flags; | ||
344 | int ret; | ||
345 | |||
346 | /* wait for DSP completion */ | ||
347 | ret = wait_event_timeout(msg->waitq, msg->complete, | ||
348 | msecs_to_jiffies(IPC_TIMEOUT_MSECS)); | ||
349 | |||
350 | spin_lock_irqsave(&byt->dsp->spinlock, flags); | ||
351 | if (ret == 0) { | ||
352 | list_del(&msg->list); | ||
353 | sst_byt_ipc_shim_dbg(byt, "message timeout"); | ||
354 | |||
355 | ret = -ETIMEDOUT; | ||
356 | } else { | ||
357 | |||
358 | /* copy the data returned from DSP */ | ||
359 | if (msg->rx_size) | ||
360 | memcpy(rx_data, msg->rx_data, msg->rx_size); | ||
361 | ret = msg->errno; | ||
362 | } | ||
363 | |||
364 | list_add_tail(&msg->list, &byt->empty_list); | ||
365 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | static int sst_byt_ipc_tx_message(struct sst_byt *byt, u64 header, | ||
370 | void *tx_data, size_t tx_bytes, | ||
371 | void *rx_data, size_t rx_bytes, int wait) | ||
372 | { | ||
373 | unsigned long flags; | ||
374 | struct ipc_message *msg; | ||
375 | |||
376 | spin_lock_irqsave(&byt->dsp->spinlock, flags); | ||
377 | |||
378 | msg = sst_byt_msg_get_empty(byt); | ||
379 | if (msg == NULL) { | ||
380 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
381 | return -EBUSY; | ||
382 | } | ||
383 | |||
384 | msg->header = header; | ||
385 | msg->tx_size = tx_bytes; | ||
386 | msg->rx_size = rx_bytes; | ||
387 | msg->wait = wait; | ||
388 | msg->errno = 0; | ||
389 | msg->complete = false; | ||
390 | |||
391 | if (tx_bytes) { | ||
392 | /* msg content = lower 32-bit of the header + data */ | ||
393 | *(u32 *)msg->tx_data = (u32)(header & (u32)-1); | ||
394 | memcpy(msg->tx_data + sizeof(u32), tx_data, tx_bytes); | ||
395 | msg->tx_size += sizeof(u32); | ||
396 | } | ||
397 | |||
398 | list_add_tail(&msg->list, &byt->tx_list); | ||
399 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
400 | |||
401 | queue_kthread_work(&byt->kworker, &byt->kwork); | ||
402 | |||
403 | if (wait) | ||
404 | return sst_byt_tx_wait_done(byt, msg, rx_data); | ||
405 | else | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | static inline int sst_byt_ipc_tx_msg_wait(struct sst_byt *byt, u64 header, | ||
410 | void *tx_data, size_t tx_bytes, | ||
411 | void *rx_data, size_t rx_bytes) | ||
412 | { | ||
413 | return sst_byt_ipc_tx_message(byt, header, tx_data, tx_bytes, | ||
414 | rx_data, rx_bytes, 1); | ||
415 | } | ||
416 | |||
417 | static inline int sst_byt_ipc_tx_msg_nowait(struct sst_byt *byt, u64 header, | ||
418 | void *tx_data, size_t tx_bytes) | ||
419 | { | ||
420 | return sst_byt_ipc_tx_message(byt, header, tx_data, tx_bytes, | ||
421 | NULL, 0, 0); | ||
422 | } | ||
423 | |||
424 | static struct ipc_message *sst_byt_reply_find_msg(struct sst_byt *byt, | ||
425 | u64 header) | ||
426 | { | ||
427 | struct ipc_message *msg = NULL, *_msg; | ||
428 | u64 mask; | ||
429 | |||
430 | /* match reply to message sent based on msg and stream IDs */ | ||
431 | mask = IPC_HEADER_MSG_ID_MASK | | ||
432 | IPC_HEADER_STR_ID_MASK << IPC_HEADER_STR_ID_SHIFT; | ||
433 | header &= mask; | ||
434 | |||
435 | if (list_empty(&byt->rx_list)) { | ||
436 | dev_err(byt->dev, | ||
437 | "ipc: rx list is empty but received 0x%llx\n", header); | ||
438 | goto out; | ||
439 | } | ||
440 | |||
441 | list_for_each_entry(_msg, &byt->rx_list, list) { | ||
442 | if ((_msg->header & mask) == header) { | ||
443 | msg = _msg; | ||
444 | break; | ||
445 | } | ||
446 | } | ||
447 | |||
448 | out: | ||
449 | return msg; | ||
450 | } | ||
451 | |||
452 | static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg) | 226 | static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg) |
453 | { | 227 | { |
454 | struct sst_byt_stream *stream; | 228 | struct sst_byt_stream *stream; |
@@ -477,7 +251,7 @@ static int sst_byt_process_reply(struct sst_byt *byt, u64 header) | |||
477 | { | 251 | { |
478 | struct ipc_message *msg; | 252 | struct ipc_message *msg; |
479 | 253 | ||
480 | msg = sst_byt_reply_find_msg(byt, header); | 254 | msg = sst_ipc_reply_find_msg(&byt->ipc, header); |
481 | if (msg == NULL) | 255 | if (msg == NULL) |
482 | return 1; | 256 | return 1; |
483 | 257 | ||
@@ -491,7 +265,7 @@ static int sst_byt_process_reply(struct sst_byt *byt, u64 header) | |||
491 | 265 | ||
492 | list_del(&msg->list); | 266 | list_del(&msg->list); |
493 | /* wake up */ | 267 | /* wake up */ |
494 | sst_byt_tx_msg_reply_complete(byt, msg); | 268 | sst_ipc_tx_msg_reply_complete(&byt->ipc, msg); |
495 | 269 | ||
496 | return 1; | 270 | return 1; |
497 | } | 271 | } |
@@ -538,6 +312,7 @@ static irqreturn_t sst_byt_irq_thread(int irq, void *context) | |||
538 | { | 312 | { |
539 | struct sst_dsp *sst = (struct sst_dsp *) context; | 313 | struct sst_dsp *sst = (struct sst_dsp *) context; |
540 | struct sst_byt *byt = sst_dsp_get_thread_context(sst); | 314 | struct sst_byt *byt = sst_dsp_get_thread_context(sst); |
315 | struct sst_generic_ipc *ipc = &byt->ipc; | ||
541 | u64 header; | 316 | u64 header; |
542 | unsigned long flags; | 317 | unsigned long flags; |
543 | 318 | ||
@@ -569,7 +344,7 @@ static irqreturn_t sst_byt_irq_thread(int irq, void *context) | |||
569 | spin_unlock_irqrestore(&sst->spinlock, flags); | 344 | spin_unlock_irqrestore(&sst->spinlock, flags); |
570 | 345 | ||
571 | /* continue to send any remaining messages... */ | 346 | /* continue to send any remaining messages... */ |
572 | queue_kthread_work(&byt->kworker, &byt->kwork); | 347 | queue_kthread_work(&ipc->kworker, &ipc->kwork); |
573 | 348 | ||
574 | return IRQ_HANDLED; | 349 | return IRQ_HANDLED; |
575 | } | 350 | } |
@@ -656,7 +431,8 @@ int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream) | |||
656 | header = sst_byt_header(IPC_IA_ALLOC_STREAM, | 431 | header = sst_byt_header(IPC_IA_ALLOC_STREAM, |
657 | sizeof(*str_req) + sizeof(u32), | 432 | sizeof(*str_req) + sizeof(u32), |
658 | true, stream->str_id); | 433 | true, stream->str_id); |
659 | ret = sst_byt_ipc_tx_msg_wait(byt, header, str_req, sizeof(*str_req), | 434 | ret = sst_ipc_tx_message_wait(&byt->ipc, header, str_req, |
435 | sizeof(*str_req), | ||
660 | reply, sizeof(*reply)); | 436 | reply, sizeof(*reply)); |
661 | if (ret < 0) { | 437 | if (ret < 0) { |
662 | dev_err(byt->dev, "ipc: error stream commit failed\n"); | 438 | dev_err(byt->dev, "ipc: error stream commit failed\n"); |
@@ -679,7 +455,7 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) | |||
679 | goto out; | 455 | goto out; |
680 | 456 | ||
681 | header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id); | 457 | header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id); |
682 | ret = sst_byt_ipc_tx_msg_wait(byt, header, NULL, 0, NULL, 0); | 458 | ret = sst_ipc_tx_message_wait(&byt->ipc, header, NULL, 0, NULL, 0); |
683 | if (ret < 0) { | 459 | if (ret < 0) { |
684 | dev_err(byt->dev, "ipc: free stream %d failed\n", | 460 | dev_err(byt->dev, "ipc: free stream %d failed\n", |
685 | stream->str_id); | 461 | stream->str_id); |
@@ -703,9 +479,11 @@ static int sst_byt_stream_operations(struct sst_byt *byt, int type, | |||
703 | 479 | ||
704 | header = sst_byt_header(type, 0, false, stream_id); | 480 | header = sst_byt_header(type, 0, false, stream_id); |
705 | if (wait) | 481 | if (wait) |
706 | return sst_byt_ipc_tx_msg_wait(byt, header, NULL, 0, NULL, 0); | 482 | return sst_ipc_tx_message_wait(&byt->ipc, header, NULL, |
483 | 0, NULL, 0); | ||
707 | else | 484 | else |
708 | return sst_byt_ipc_tx_msg_nowait(byt, header, NULL, 0); | 485 | return sst_ipc_tx_message_nowait(&byt->ipc, header, |
486 | NULL, 0); | ||
709 | } | 487 | } |
710 | 488 | ||
711 | /* stream ALSA trigger operations */ | 489 | /* stream ALSA trigger operations */ |
@@ -725,7 +503,7 @@ int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream, | |||
725 | tx_msg = &start_stream; | 503 | tx_msg = &start_stream; |
726 | size = sizeof(start_stream); | 504 | size = sizeof(start_stream); |
727 | 505 | ||
728 | ret = sst_byt_ipc_tx_msg_nowait(byt, header, tx_msg, size); | 506 | ret = sst_ipc_tx_message_nowait(&byt->ipc, header, tx_msg, size); |
729 | if (ret < 0) | 507 | if (ret < 0) |
730 | dev_err(byt->dev, "ipc: error failed to start stream %d\n", | 508 | dev_err(byt->dev, "ipc: error failed to start stream %d\n", |
731 | stream->str_id); | 509 | stream->str_id); |
@@ -790,23 +568,6 @@ int sst_byt_get_dsp_position(struct sst_byt *byt, | |||
790 | return do_div(fw_tstamp.ring_buffer_counter, buffer_size); | 568 | return do_div(fw_tstamp.ring_buffer_counter, buffer_size); |
791 | } | 569 | } |
792 | 570 | ||
793 | static int msg_empty_list_init(struct sst_byt *byt) | ||
794 | { | ||
795 | struct ipc_message *msg; | ||
796 | int i; | ||
797 | |||
798 | byt->msg = kzalloc(sizeof(*msg) * IPC_EMPTY_LIST_SIZE, GFP_KERNEL); | ||
799 | if (byt->msg == NULL) | ||
800 | return -ENOMEM; | ||
801 | |||
802 | for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { | ||
803 | init_waitqueue_head(&byt->msg[i].waitq); | ||
804 | list_add(&byt->msg[i].list, &byt->empty_list); | ||
805 | } | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt) | 571 | struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt) |
811 | { | 572 | { |
812 | return byt->dsp; | 573 | return byt->dsp; |
@@ -823,7 +584,7 @@ int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata) | |||
823 | 584 | ||
824 | dev_dbg(byt->dev, "dsp reset\n"); | 585 | dev_dbg(byt->dev, "dsp reset\n"); |
825 | sst_dsp_reset(byt->dsp); | 586 | sst_dsp_reset(byt->dsp); |
826 | sst_byt_drop_all(byt); | 587 | sst_ipc_drop_all(&byt->ipc); |
827 | dev_dbg(byt->dev, "dsp in reset\n"); | 588 | dev_dbg(byt->dev, "dsp in reset\n"); |
828 | 589 | ||
829 | dev_dbg(byt->dev, "free all blocks and unload fw\n"); | 590 | dev_dbg(byt->dev, "free all blocks and unload fw\n"); |
@@ -876,9 +637,52 @@ int sst_byt_dsp_wait_for_ready(struct device *dev, struct sst_pdata *pdata) | |||
876 | } | 637 | } |
877 | EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready); | 638 | EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready); |
878 | 639 | ||
640 | static void byt_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) | ||
641 | { | ||
642 | if (msg->header & IPC_HEADER_LARGE(true)) | ||
643 | sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); | ||
644 | |||
645 | sst_dsp_shim_write64_unlocked(ipc->dsp, SST_IPCX, msg->header); | ||
646 | } | ||
647 | |||
648 | static void byt_shim_dbg(struct sst_generic_ipc *ipc, const char *text) | ||
649 | { | ||
650 | struct sst_dsp *sst = ipc->dsp; | ||
651 | u64 isr, ipcd, imrx, ipcx; | ||
652 | |||
653 | ipcx = sst_dsp_shim_read64_unlocked(sst, SST_IPCX); | ||
654 | isr = sst_dsp_shim_read64_unlocked(sst, SST_ISRX); | ||
655 | ipcd = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); | ||
656 | imrx = sst_dsp_shim_read64_unlocked(sst, SST_IMRX); | ||
657 | |||
658 | dev_err(ipc->dev, | ||
659 | "ipc: --%s-- ipcx 0x%llx isr 0x%llx ipcd 0x%llx imrx 0x%llx\n", | ||
660 | text, ipcx, isr, ipcd, imrx); | ||
661 | } | ||
662 | |||
663 | static void byt_tx_data_copy(struct ipc_message *msg, char *tx_data, | ||
664 | size_t tx_size) | ||
665 | { | ||
666 | /* msg content = lower 32-bit of the header + data */ | ||
667 | *(u32 *)msg->tx_data = (u32)(msg->header & (u32)-1); | ||
668 | memcpy(msg->tx_data + sizeof(u32), tx_data, tx_size); | ||
669 | msg->tx_size += sizeof(u32); | ||
670 | } | ||
671 | |||
672 | static u64 byt_reply_msg_match(u64 header, u64 *mask) | ||
673 | { | ||
674 | /* match reply to message sent based on msg and stream IDs */ | ||
675 | *mask = IPC_HEADER_MSG_ID_MASK | | ||
676 | IPC_HEADER_STR_ID_MASK << IPC_HEADER_STR_ID_SHIFT; | ||
677 | header &= *mask; | ||
678 | |||
679 | return header; | ||
680 | } | ||
681 | |||
879 | int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | 682 | int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) |
880 | { | 683 | { |
881 | struct sst_byt *byt; | 684 | struct sst_byt *byt; |
685 | struct sst_generic_ipc *ipc; | ||
882 | struct sst_fw *byt_sst_fw; | 686 | struct sst_fw *byt_sst_fw; |
883 | struct sst_byt_fw_init init; | 687 | struct sst_byt_fw_init init; |
884 | int err; | 688 | int err; |
@@ -889,39 +693,30 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
889 | if (byt == NULL) | 693 | if (byt == NULL) |
890 | return -ENOMEM; | 694 | return -ENOMEM; |
891 | 695 | ||
892 | byt->dev = dev; | 696 | ipc = &byt->ipc; |
893 | INIT_LIST_HEAD(&byt->stream_list); | 697 | ipc->dev = dev; |
894 | INIT_LIST_HEAD(&byt->tx_list); | 698 | ipc->ops.tx_msg = byt_tx_msg; |
895 | INIT_LIST_HEAD(&byt->rx_list); | 699 | ipc->ops.shim_dbg = byt_shim_dbg; |
896 | INIT_LIST_HEAD(&byt->empty_list); | 700 | ipc->ops.tx_data_copy = byt_tx_data_copy; |
897 | init_waitqueue_head(&byt->boot_wait); | 701 | ipc->ops.reply_msg_match = byt_reply_msg_match; |
898 | init_waitqueue_head(&byt->wait_txq); | ||
899 | 702 | ||
900 | err = msg_empty_list_init(byt); | 703 | err = sst_ipc_init(ipc); |
901 | if (err < 0) | 704 | if (err != 0) |
902 | return -ENOMEM; | 705 | goto ipc_init_err; |
903 | |||
904 | /* start the IPC message thread */ | ||
905 | init_kthread_worker(&byt->kworker); | ||
906 | byt->tx_thread = kthread_run(kthread_worker_fn, | ||
907 | &byt->kworker, "%s", | ||
908 | dev_name(byt->dev)); | ||
909 | if (IS_ERR(byt->tx_thread)) { | ||
910 | err = PTR_ERR(byt->tx_thread); | ||
911 | dev_err(byt->dev, "error failed to create message TX task\n"); | ||
912 | goto err_free_msg; | ||
913 | } | ||
914 | init_kthread_work(&byt->kwork, sst_byt_ipc_tx_msgs); | ||
915 | 706 | ||
707 | INIT_LIST_HEAD(&byt->stream_list); | ||
708 | init_waitqueue_head(&byt->boot_wait); | ||
916 | byt_dev.thread_context = byt; | 709 | byt_dev.thread_context = byt; |
917 | 710 | ||
918 | /* init SST shim */ | 711 | /* init SST shim */ |
919 | byt->dsp = sst_dsp_new(dev, &byt_dev, pdata); | 712 | byt->dsp = sst_dsp_new(dev, &byt_dev, pdata); |
920 | if (byt->dsp == NULL) { | 713 | if (byt->dsp == NULL) { |
921 | err = -ENODEV; | 714 | err = -ENODEV; |
922 | goto dsp_err; | 715 | goto dsp_new_err; |
923 | } | 716 | } |
924 | 717 | ||
718 | ipc->dsp = byt->dsp; | ||
719 | |||
925 | /* keep the DSP in reset state for base FW loading */ | 720 | /* keep the DSP in reset state for base FW loading */ |
926 | sst_dsp_reset(byt->dsp); | 721 | sst_dsp_reset(byt->dsp); |
927 | 722 | ||
@@ -961,10 +756,10 @@ boot_err: | |||
961 | sst_fw_free(byt_sst_fw); | 756 | sst_fw_free(byt_sst_fw); |
962 | fw_err: | 757 | fw_err: |
963 | sst_dsp_free(byt->dsp); | 758 | sst_dsp_free(byt->dsp); |
964 | dsp_err: | 759 | dsp_new_err: |
965 | kthread_stop(byt->tx_thread); | 760 | sst_ipc_fini(ipc); |
966 | err_free_msg: | 761 | ipc_init_err: |
967 | kfree(byt->msg); | 762 | kfree(byt); |
968 | 763 | ||
969 | return err; | 764 | return err; |
970 | } | 765 | } |
@@ -977,7 +772,6 @@ void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata) | |||
977 | sst_dsp_reset(byt->dsp); | 772 | sst_dsp_reset(byt->dsp); |
978 | sst_fw_free_all(byt->dsp); | 773 | sst_fw_free_all(byt->dsp); |
979 | sst_dsp_free(byt->dsp); | 774 | sst_dsp_free(byt->dsp); |
980 | kthread_stop(byt->tx_thread); | 775 | sst_ipc_fini(&byt->ipc); |
981 | kfree(byt->msg); | ||
982 | } | 776 | } |
983 | EXPORT_SYMBOL_GPL(sst_byt_dsp_free); | 777 | EXPORT_SYMBOL_GPL(sst_byt_dsp_free); |