diff options
Diffstat (limited to 'sound/soc/intel/common')
-rw-r--r-- | sound/soc/intel/common/sst-dsp-priv.h | 23 | ||||
-rw-r--r-- | sound/soc/intel/common/sst-dsp.c | 71 | ||||
-rw-r--r-- | sound/soc/intel/common/sst-dsp.h | 6 |
3 files changed, 96 insertions, 4 deletions
diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h index 396d54510..cbd568eac 100644 --- a/sound/soc/intel/common/sst-dsp-priv.h +++ b/sound/soc/intel/common/sst-dsp-priv.h @@ -22,6 +22,8 @@ #include <linux/interrupt.h> #include <linux/firmware.h> +#include "../skylake/skl-sst-dsp.h" + struct sst_mem_block; struct sst_module; struct sst_fw; @@ -258,6 +260,8 @@ struct sst_mem_block { */ struct sst_dsp { + /* Shared for all platforms */ + /* runtime */ struct sst_dsp_device *sst_dev; spinlock_t spinlock; /* IPC locking */ @@ -268,10 +272,6 @@ struct sst_dsp { int irq; u32 id; - /* list of free and used ADSP memory blocks */ - struct list_head used_block_list; - struct list_head free_block_list; - /* operations */ struct sst_ops *ops; @@ -284,6 +284,12 @@ struct sst_dsp { /* mailbox */ struct sst_mailbox mailbox; + /* HSW/Byt data */ + + /* list of free and used ADSP memory blocks */ + struct list_head used_block_list; + struct list_head free_block_list; + /* SST FW files loaded and their modules */ struct list_head module_list; struct list_head fw_list; @@ -299,6 +305,15 @@ struct sst_dsp { /* DMA FW loading */ struct sst_dma *dma; bool fw_use_dma; + + /* SKL data */ + + /* To allocate CL dma buffers */ + struct skl_dsp_loader_ops dsp_ops; + struct skl_dsp_fw_ops fw_ops; + int sst_state; + struct skl_cl_dev cl_dev; + u32 intr_status; }; /* Size optimised DRAM/IRAM memcpy */ diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c index 64e94212d..a627236dd 100644 --- a/sound/soc/intel/common/sst-dsp.c +++ b/sound/soc/intel/common/sst-dsp.c @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/delay.h> #include "sst-dsp.h" #include "sst-dsp-priv.h" @@ -196,6 +197,22 @@ int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, } EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64_unlocked); +/* This is for registers bits with attribute RWC */ +void sst_dsp_shim_update_bits_forced_unlocked(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value) +{ + unsigned int old, new; + u32 ret; + + ret = sst_dsp_shim_read_unlocked(sst, offset); + + old = ret; + new = (old & (~mask)) | (value & mask); + + sst_dsp_shim_write_unlocked(sst, offset, new); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced_unlocked); + int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset, u32 mask, u32 value) { @@ -222,6 +239,60 @@ int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, } EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); +/* This is for registers bits with attribute RWC */ +void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value) +{ + unsigned long flags; + + spin_lock_irqsave(&sst->spinlock, flags); + sst_dsp_shim_update_bits_forced_unlocked(sst, offset, mask, value); + spin_unlock_irqrestore(&sst->spinlock, flags); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced); + +int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask, + u32 target, u32 timeout, char *operation) +{ + int time, ret; + u32 reg; + bool done = false; + + /* + * we will poll for couple of ms using mdelay, if not successful + * then go to longer sleep using usleep_range + */ + + /* check if set state successful */ + for (time = 0; time < 5; time++) { + if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) { + done = true; + break; + } + mdelay(1); + } + + if (done == false) { + /* sleeping in 10ms steps so adjust timeout value */ + timeout /= 10; + + for (time = 0; time < timeout; time++) { + if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) + break; + + usleep_range(5000, 10000); + } + } + + reg = sst_dsp_shim_read_unlocked(ctx, offset); + dev_info(ctx->dev, "FW Poll Status: reg=%#x %s %s\n", reg, operation, + (time < timeout) ? "successful" : "timedout"); + ret = time < timeout ? 0 : -ETIME; + + return ret; +} +EXPORT_SYMBOL_GPL(sst_dsp_register_poll); + void sst_dsp_dump(struct sst_dsp *sst) { if (sst->ops->dump) diff --git a/sound/soc/intel/common/sst-dsp.h b/sound/soc/intel/common/sst-dsp.h index 96aeb2556..1f45f1871 100644 --- a/sound/soc/intel/common/sst-dsp.h +++ b/sound/soc/intel/common/sst-dsp.h @@ -230,6 +230,8 @@ void sst_dsp_shim_write64(struct sst_dsp *sst, u32 offset, u64 value); u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset); int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, u64 mask, u64 value); +void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value); /* SHIM Read / Write Unlocked for callers already holding sst lock */ void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value); @@ -240,6 +242,8 @@ void sst_dsp_shim_write64_unlocked(struct sst_dsp *sst, u32 offset, u64 value); u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset); int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, u64 mask, u64 value); +void sst_dsp_shim_update_bits_forced_unlocked(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value); /* Internal generic low-level SST IO functions - can be overidden */ void sst_shim32_write(void __iomem *addr, u32 offset, u32 value); @@ -278,6 +282,8 @@ void sst_dsp_inbox_read(struct sst_dsp *dsp, void *message, size_t bytes); void sst_dsp_outbox_write(struct sst_dsp *dsp, void *message, size_t bytes); void sst_dsp_outbox_read(struct sst_dsp *dsp, void *message, size_t bytes); void sst_dsp_mailbox_dump(struct sst_dsp *dsp, size_t bytes); +int sst_dsp_register_poll(struct sst_dsp *dsp, u32 offset, u32 mask, + u32 expected_value, u32 timeout, char *operation); /* Debug */ void sst_dsp_dump(struct sst_dsp *sst); |