aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/sst-baytrail-ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel/sst-baytrail-ipc.c')
-rw-r--r--sound/soc/intel/sst-baytrail-ipc.c132
1 files changed, 112 insertions, 20 deletions
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c
index d0eaeee21be4..7c1ec003d55d 100644
--- a/sound/soc/intel/sst-baytrail-ipc.c
+++ b/sound/soc/intel/sst-baytrail-ipc.c
@@ -173,6 +173,7 @@ struct sst_byt {
173 /* boot */ 173 /* boot */
174 wait_queue_head_t boot_wait; 174 wait_queue_head_t boot_wait;
175 bool boot_complete; 175 bool boot_complete;
176 struct sst_fw *fw;
176 177
177 /* IPC messaging */ 178 /* IPC messaging */
178 struct list_head tx_list; 179 struct list_head tx_list;
@@ -299,6 +300,24 @@ static inline void sst_byt_tx_msg_reply_complete(struct sst_byt *byt,
299 wake_up(&msg->waitq); 300 wake_up(&msg->waitq);
300} 301}
301 302
303static void sst_byt_drop_all(struct sst_byt *byt)
304{
305 struct ipc_message *msg, *tmp;
306 unsigned long flags;
307
308 /* drop all TX and Rx messages before we stall + reset DSP */
309 spin_lock_irqsave(&byt->dsp->spinlock, flags);
310 list_for_each_entry_safe(msg, tmp, &byt->tx_list, list) {
311 list_move(&msg->list, &byt->empty_list);
312 }
313
314 list_for_each_entry_safe(msg, tmp, &byt->rx_list, list) {
315 list_move(&msg->list, &byt->empty_list);
316 }
317
318 spin_unlock_irqrestore(&byt->dsp->spinlock, flags);
319}
320
302static int sst_byt_tx_wait_done(struct sst_byt *byt, struct ipc_message *msg, 321static int sst_byt_tx_wait_done(struct sst_byt *byt, struct ipc_message *msg,
303 void *rx_data) 322 void *rx_data)
304{ 323{
@@ -542,16 +561,20 @@ struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id,
542 void *data) 561 void *data)
543{ 562{
544 struct sst_byt_stream *stream; 563 struct sst_byt_stream *stream;
564 struct sst_dsp *sst = byt->dsp;
565 unsigned long flags;
545 566
546 stream = kzalloc(sizeof(*stream), GFP_KERNEL); 567 stream = kzalloc(sizeof(*stream), GFP_KERNEL);
547 if (stream == NULL) 568 if (stream == NULL)
548 return NULL; 569 return NULL;
549 570
571 spin_lock_irqsave(&sst->spinlock, flags);
550 list_add(&stream->node, &byt->stream_list); 572 list_add(&stream->node, &byt->stream_list);
551 stream->notify_position = notify_position; 573 stream->notify_position = notify_position;
552 stream->pdata = data; 574 stream->pdata = data;
553 stream->byt = byt; 575 stream->byt = byt;
554 stream->str_id = id; 576 stream->str_id = id;
577 spin_unlock_irqrestore(&sst->spinlock, flags);
555 578
556 return stream; 579 return stream;
557} 580}
@@ -630,6 +653,8 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream)
630{ 653{
631 u64 header; 654 u64 header;
632 int ret = 0; 655 int ret = 0;
656 struct sst_dsp *sst = byt->dsp;
657 unsigned long flags;
633 658
634 if (!stream->commited) 659 if (!stream->commited)
635 goto out; 660 goto out;
@@ -644,8 +669,10 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream)
644 669
645 stream->commited = false; 670 stream->commited = false;
646out: 671out:
672 spin_lock_irqsave(&sst->spinlock, flags);
647 list_del(&stream->node); 673 list_del(&stream->node);
648 kfree(stream); 674 kfree(stream);
675 spin_unlock_irqrestore(&sst->spinlock, flags);
649 676
650 return ret; 677 return ret;
651} 678}
@@ -653,36 +680,33 @@ out:
653static int sst_byt_stream_operations(struct sst_byt *byt, int type, 680static int sst_byt_stream_operations(struct sst_byt *byt, int type,
654 int stream_id, int wait) 681 int stream_id, int wait)
655{ 682{
656 struct sst_byt_start_stream_params start_stream;
657 u64 header; 683 u64 header;
658 void *tx_msg = NULL;
659 size_t size = 0;
660
661 if (type != IPC_IA_START_STREAM) {
662 header = sst_byt_header(type, 0, false, stream_id);
663 } else {
664 start_stream.byte_offset = 0;
665 header = sst_byt_header(IPC_IA_START_STREAM,
666 sizeof(start_stream) + sizeof(u32),
667 true, stream_id);
668 tx_msg = &start_stream;
669 size = sizeof(start_stream);
670 }
671 684
685 header = sst_byt_header(type, 0, false, stream_id);
672 if (wait) 686 if (wait)
673 return sst_byt_ipc_tx_msg_wait(byt, header, 687 return sst_byt_ipc_tx_msg_wait(byt, header, NULL, 0, NULL, 0);
674 tx_msg, size, NULL, 0);
675 else 688 else
676 return sst_byt_ipc_tx_msg_nowait(byt, header, tx_msg, size); 689 return sst_byt_ipc_tx_msg_nowait(byt, header, NULL, 0);
677} 690}
678 691
679/* stream ALSA trigger operations */ 692/* stream ALSA trigger operations */
680int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream) 693int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream,
694 u32 start_offset)
681{ 695{
696 struct sst_byt_start_stream_params start_stream;
697 void *tx_msg;
698 size_t size;
699 u64 header;
682 int ret; 700 int ret;
683 701
684 ret = sst_byt_stream_operations(byt, IPC_IA_START_STREAM, 702 start_stream.byte_offset = start_offset;
685 stream->str_id, 0); 703 header = sst_byt_header(IPC_IA_START_STREAM,
704 sizeof(start_stream) + sizeof(u32),
705 true, stream->str_id);
706 tx_msg = &start_stream;
707 size = sizeof(start_stream);
708
709 ret = sst_byt_ipc_tx_msg_nowait(byt, header, tx_msg, size);
686 if (ret < 0) 710 if (ret < 0)
687 dev_err(byt->dev, "ipc: error failed to start stream %d\n", 711 dev_err(byt->dev, "ipc: error failed to start stream %d\n",
688 stream->str_id); 712 stream->str_id);
@@ -774,6 +798,73 @@ static struct sst_dsp_device byt_dev = {
774 .ops = &sst_byt_ops, 798 .ops = &sst_byt_ops,
775}; 799};
776 800
801int sst_byt_dsp_suspend_noirq(struct device *dev, struct sst_pdata *pdata)
802{
803 struct sst_byt *byt = pdata->dsp;
804
805 dev_dbg(byt->dev, "dsp reset\n");
806 sst_dsp_reset(byt->dsp);
807 sst_byt_drop_all(byt);
808 dev_dbg(byt->dev, "dsp in reset\n");
809
810 return 0;
811}
812EXPORT_SYMBOL_GPL(sst_byt_dsp_suspend_noirq);
813
814int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata)
815{
816 struct sst_byt *byt = pdata->dsp;
817
818 dev_dbg(byt->dev, "free all blocks and unload fw\n");
819 sst_fw_unload(byt->fw);
820
821 return 0;
822}
823EXPORT_SYMBOL_GPL(sst_byt_dsp_suspend_late);
824
825int sst_byt_dsp_boot(struct device *dev, struct sst_pdata *pdata)
826{
827 struct sst_byt *byt = pdata->dsp;
828 int ret;
829
830 dev_dbg(byt->dev, "reload dsp fw\n");
831
832 sst_dsp_reset(byt->dsp);
833
834 ret = sst_fw_reload(byt->fw);
835 if (ret < 0) {
836 dev_err(dev, "error: failed to reload firmware\n");
837 return ret;
838 }
839
840 /* wait for DSP boot completion */
841 byt->boot_complete = false;
842 sst_dsp_boot(byt->dsp);
843 dev_dbg(byt->dev, "dsp booting...\n");
844
845 return 0;
846}
847EXPORT_SYMBOL_GPL(sst_byt_dsp_boot);
848
849int sst_byt_dsp_wait_for_ready(struct device *dev, struct sst_pdata *pdata)
850{
851 struct sst_byt *byt = pdata->dsp;
852 int err;
853
854 dev_dbg(byt->dev, "wait for dsp reboot\n");
855
856 err = wait_event_timeout(byt->boot_wait, byt->boot_complete,
857 msecs_to_jiffies(IPC_BOOT_MSECS));
858 if (err == 0) {
859 dev_err(byt->dev, "ipc: error DSP boot timeout\n");
860 return -EIO;
861 }
862
863 dev_dbg(byt->dev, "dsp rebooted\n");
864 return 0;
865}
866EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready);
867
777int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) 868int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
778{ 869{
779 struct sst_byt *byt; 870 struct sst_byt *byt;
@@ -840,6 +931,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
840 } 931 }
841 932
842 pdata->dsp = byt; 933 pdata->dsp = byt;
934 byt->fw = byt_sst_fw;
843 935
844 return 0; 936 return 0;
845 937