diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-04 09:08:25 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-04 09:08:25 -0700 |
commit | b77279bc2e81545b20824da701b349272a78e4e7 (patch) | |
tree | d8f3a8ddf544cf201f8bdcb587cf360571487e5c /sound/soc/intel/sst-baytrail-ipc.c | |
parent | 15b588303155b22edd559672905db8e59a44ef9a (diff) | |
parent | 16088cb6c02d0b766b9b8d7edff98da7f1c93205 (diff) |
Merge tag 'sound-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound into next
Pull sound updates from Takashi Iwai:
"At this time, majority of changes come from ASoC world while we got a
few new drivers in other places for FireWire and USB. There have been
lots of ASoC core cleanups / refactoring, but very little visible to
external users.
ASoC:
- Support for specifying aux CODECs in DT
- Removal of the deprecated mux and enum macros
- More moves towards full componentisation
- Removal of some unused I/O code
- Lots of cleanups, fixes and enhancements to the davinci, Freescale,
Haswell and Realtek drivers
- Several drivers exposed directly in Kconfig for use with
simple-card
- GPIO descriptor support for jacks
- More updates and fixes to the Freescale SSI, Intel and rsnd drivers
- New drivers for Cirrus CS42L56, Realtek RT5639, RT5642 and RT5651
and ST STA350, Analog Devices ADAU1361, ADAU1381, ADAU1761 and
ADAU1781, and Realtek RT5677
HD-audio:
- Clean up Dell headset quirks
- Noise fixes for Dell and Sony laptops
- Thinkpad T440 dock fix
- Realtek codec updates (ALC293,ALC233,ALC3235)
- Tegra HD-audio HDMI support
FireWire-audio:
- FireWire audio stack enhancement (AMDTP, MIDI), support for
incoming isochronous stream and duplex streams with timestamp
synchronization
- BeBoB-based devices support
- Fireworks-based device support
USB-audio:
- Behringer BCD2000 USB device support
Misc:
- Clean up of a few old drivers, atmel, fm801, etc"
* tag 'sound-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (480 commits)
ASoC: Fix wrong argument for card remove callbacks
ASoC: free jack GPIOs before the sound card is freed
ALSA: firewire-lib: Remove a comment about restriction of asynchronous operation
ASoC: cache: Fix error code when not using ASoC level cache
ALSA: hda/realtek - Fix COEF widget NID for ALC260 replacer fixup
ALSA: hda/realtek - Correction of fixup codes for PB V7900 laptop
ALSA: firewire-lib: Use IEC 61883-6 compliant labels for Raw Audio data
ASoC: add RT5677 CODEC driver
ASoC: intel: The Baytrail/MAX98090 driver depends on I2C
ASoC: rt5640: Add the function "get_clk_info" to RL6231 shared support
ASoC: rt5640: Add the function of the PLL clock calculation to RL6231 shared support
ASoC: rt5640: Add RL6231 class device shared support for RT5640, RT5645 and RT5651
ASoC: cache: Fix possible ZERO_SIZE_PTR pointer dereferencing error.
ASoC: Add helper functions to cast from DAPM context to CODEC/platform
ALSA: bebob: sizeof() vs ARRAY_SIZE() typo
ASoC: wm9713: correct mono out PGA sources
ALSA: synth: emux: soundfont.c: Cleaning up memory leak
ASoC: fsl: Remove dependencies of boards for SND_SOC_EUKREA_TLV320
ASoC: fsl-ssi: Use regmap
ASoC: fsl-ssi: reorder and document fsl_ssi_private
...
Diffstat (limited to 'sound/soc/intel/sst-baytrail-ipc.c')
-rw-r--r-- | sound/soc/intel/sst-baytrail-ipc.c | 132 |
1 files changed, 109 insertions, 23 deletions
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c index 0d31dbbf480..d207b22ea33 100644 --- a/sound/soc/intel/sst-baytrail-ipc.c +++ b/sound/soc/intel/sst-baytrail-ipc.c @@ -22,7 +22,6 @@ #include <linux/export.h> #include <linux/slab.h> #include <linux/delay.h> -#include <linux/list.h> #include <linux/platform_device.h> #include <linux/kthread.h> #include <linux/firmware.h> @@ -173,6 +172,7 @@ struct sst_byt { /* boot */ wait_queue_head_t boot_wait; bool boot_complete; + struct sst_fw *fw; /* IPC messaging */ struct list_head tx_list; @@ -299,6 +299,24 @@ static inline void sst_byt_tx_msg_reply_complete(struct sst_byt *byt, wake_up(&msg->waitq); } +static void sst_byt_drop_all(struct sst_byt *byt) +{ + struct ipc_message *msg, *tmp; + unsigned long flags; + + /* drop all TX and Rx messages before we stall + reset DSP */ + spin_lock_irqsave(&byt->dsp->spinlock, flags); + list_for_each_entry_safe(msg, tmp, &byt->tx_list, list) { + list_move(&msg->list, &byt->empty_list); + } + + list_for_each_entry_safe(msg, tmp, &byt->rx_list, list) { + list_move(&msg->list, &byt->empty_list); + } + + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); +} + static int sst_byt_tx_wait_done(struct sst_byt *byt, struct ipc_message *msg, void *rx_data) { @@ -661,36 +679,33 @@ out: static int sst_byt_stream_operations(struct sst_byt *byt, int type, int stream_id, int wait) { - struct sst_byt_start_stream_params start_stream; u64 header; - void *tx_msg = NULL; - size_t size = 0; - - if (type != IPC_IA_START_STREAM) { - header = sst_byt_header(type, 0, false, stream_id); - } else { - start_stream.byte_offset = 0; - header = sst_byt_header(IPC_IA_START_STREAM, - sizeof(start_stream) + sizeof(u32), - true, stream_id); - tx_msg = &start_stream; - size = sizeof(start_stream); - } + header = sst_byt_header(type, 0, false, stream_id); if (wait) - return sst_byt_ipc_tx_msg_wait(byt, header, - tx_msg, size, NULL, 0); + return sst_byt_ipc_tx_msg_wait(byt, header, NULL, 0, NULL, 0); else - return sst_byt_ipc_tx_msg_nowait(byt, header, tx_msg, size); + return sst_byt_ipc_tx_msg_nowait(byt, header, NULL, 0); } /* stream ALSA trigger operations */ -int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream) +int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream, + u32 start_offset) { + struct sst_byt_start_stream_params start_stream; + void *tx_msg; + size_t size; + u64 header; int ret; - ret = sst_byt_stream_operations(byt, IPC_IA_START_STREAM, - stream->str_id, 0); + start_stream.byte_offset = start_offset; + header = sst_byt_header(IPC_IA_START_STREAM, + sizeof(start_stream) + sizeof(u32), + true, stream->str_id); + tx_msg = &start_stream; + size = sizeof(start_stream); + + ret = sst_byt_ipc_tx_msg_nowait(byt, header, tx_msg, size); if (ret < 0) dev_err(byt->dev, "ipc: error failed to start stream %d\n", stream->str_id); @@ -782,6 +797,73 @@ static struct sst_dsp_device byt_dev = { .ops = &sst_byt_ops, }; +int sst_byt_dsp_suspend_noirq(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_byt *byt = pdata->dsp; + + dev_dbg(byt->dev, "dsp reset\n"); + sst_dsp_reset(byt->dsp); + sst_byt_drop_all(byt); + dev_dbg(byt->dev, "dsp in reset\n"); + + return 0; +} +EXPORT_SYMBOL_GPL(sst_byt_dsp_suspend_noirq); + +int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_byt *byt = pdata->dsp; + + dev_dbg(byt->dev, "free all blocks and unload fw\n"); + sst_fw_unload(byt->fw); + + return 0; +} +EXPORT_SYMBOL_GPL(sst_byt_dsp_suspend_late); + +int sst_byt_dsp_boot(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_byt *byt = pdata->dsp; + int ret; + + dev_dbg(byt->dev, "reload dsp fw\n"); + + sst_dsp_reset(byt->dsp); + + ret = sst_fw_reload(byt->fw); + if (ret < 0) { + dev_err(dev, "error: failed to reload firmware\n"); + return ret; + } + + /* wait for DSP boot completion */ + byt->boot_complete = false; + sst_dsp_boot(byt->dsp); + dev_dbg(byt->dev, "dsp booting...\n"); + + return 0; +} +EXPORT_SYMBOL_GPL(sst_byt_dsp_boot); + +int sst_byt_dsp_wait_for_ready(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_byt *byt = pdata->dsp; + int err; + + dev_dbg(byt->dev, "wait for dsp reboot\n"); + + err = wait_event_timeout(byt->boot_wait, byt->boot_complete, + msecs_to_jiffies(IPC_BOOT_MSECS)); + if (err == 0) { + dev_err(byt->dev, "ipc: error DSP boot timeout\n"); + return -EIO; + } + + dev_dbg(byt->dev, "dsp rebooted\n"); + return 0; +} +EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready); + int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) { struct sst_byt *byt; @@ -809,7 +891,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) /* start the IPC message thread */ init_kthread_worker(&byt->kworker); byt->tx_thread = kthread_run(kthread_worker_fn, - &byt->kworker, + &byt->kworker, "%s", dev_name(byt->dev)); if (IS_ERR(byt->tx_thread)) { err = PTR_ERR(byt->tx_thread); @@ -824,7 +906,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) byt->dsp = sst_dsp_new(dev, &byt_dev, pdata); if (byt->dsp == NULL) { err = -ENODEV; - goto err_free_msg; + goto dsp_err; } /* keep the DSP in reset state for base FW loading */ @@ -848,6 +930,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) } pdata->dsp = byt; + byt->fw = byt_sst_fw; return 0; @@ -856,6 +939,8 @@ boot_err: sst_fw_free(byt_sst_fw); fw_err: sst_dsp_free(byt->dsp); +dsp_err: + kthread_stop(byt->tx_thread); err_free_msg: kfree(byt->msg); @@ -870,6 +955,7 @@ void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata) sst_dsp_reset(byt->dsp); sst_fw_free_all(byt->dsp); sst_dsp_free(byt->dsp); + kthread_stop(byt->tx_thread); kfree(byt->msg); } EXPORT_SYMBOL_GPL(sst_byt_dsp_free); |