162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * skl-sst-cldma.c - Code Loader DMA handler 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2015, Intel Corporation. 662306a36Sopenharmony_ci * Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com> 762306a36Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/device.h> 1162306a36Sopenharmony_ci#include <linux/io.h> 1262306a36Sopenharmony_ci#include <linux/mm.h> 1362306a36Sopenharmony_ci#include <linux/delay.h> 1462306a36Sopenharmony_ci#include <sound/hda_register.h> 1562306a36Sopenharmony_ci#include "../common/sst-dsp.h" 1662306a36Sopenharmony_ci#include "../common/sst-dsp-priv.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic void skl_cldma_int_enable(struct sst_dsp *ctx) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC, 2162306a36Sopenharmony_ci SKL_ADSPIC_CL_DMA, SKL_ADSPIC_CL_DMA); 2262306a36Sopenharmony_ci} 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_civoid skl_cldma_int_disable(struct sst_dsp *ctx) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, 2762306a36Sopenharmony_ci SKL_ADSP_REG_ADSPIC, SKL_ADSPIC_CL_DMA, 0); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic void skl_cldma_stream_run(struct sst_dsp *ctx, bool enable) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci unsigned char val; 3362306a36Sopenharmony_ci int timeout; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, 3662306a36Sopenharmony_ci SKL_ADSP_REG_CL_SD_CTL, 3762306a36Sopenharmony_ci CL_SD_CTL_RUN_MASK, CL_SD_CTL_RUN(enable)); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci udelay(3); 4062306a36Sopenharmony_ci timeout = 300; 4162306a36Sopenharmony_ci do { 4262306a36Sopenharmony_ci /* waiting for hardware to report that the stream Run bit set */ 4362306a36Sopenharmony_ci val = sst_dsp_shim_read(ctx, SKL_ADSP_REG_CL_SD_CTL) & 4462306a36Sopenharmony_ci CL_SD_CTL_RUN_MASK; 4562306a36Sopenharmony_ci if (enable && val) 4662306a36Sopenharmony_ci break; 4762306a36Sopenharmony_ci else if (!enable && !val) 4862306a36Sopenharmony_ci break; 4962306a36Sopenharmony_ci udelay(3); 5062306a36Sopenharmony_ci } while (--timeout); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci if (timeout == 0) 5362306a36Sopenharmony_ci dev_err(ctx->dev, "Failed to set Run bit=%d enable=%d\n", val, enable); 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic void skl_cldma_stream_clear(struct sst_dsp *ctx) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci /* make sure Run bit is cleared before setting stream register */ 5962306a36Sopenharmony_ci skl_cldma_stream_run(ctx, 0); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 6262306a36Sopenharmony_ci CL_SD_CTL_IOCE_MASK, CL_SD_CTL_IOCE(0)); 6362306a36Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 6462306a36Sopenharmony_ci CL_SD_CTL_FEIE_MASK, CL_SD_CTL_FEIE(0)); 6562306a36Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 6662306a36Sopenharmony_ci CL_SD_CTL_DEIE_MASK, CL_SD_CTL_DEIE(0)); 6762306a36Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 6862306a36Sopenharmony_ci CL_SD_CTL_STRM_MASK, CL_SD_CTL_STRM(0)); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL, CL_SD_BDLPLBA(0)); 7162306a36Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU, 0); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_CBL, 0); 7462306a36Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_LVI, 0); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* Code loader helper APIs */ 7862306a36Sopenharmony_cistatic void skl_cldma_setup_bdle(struct sst_dsp *ctx, 7962306a36Sopenharmony_ci struct snd_dma_buffer *dmab_data, 8062306a36Sopenharmony_ci __le32 **bdlp, int size, int with_ioc) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci __le32 *bdl = *bdlp; 8362306a36Sopenharmony_ci int remaining = ctx->cl_dev.bufsize; 8462306a36Sopenharmony_ci int offset = 0; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci ctx->cl_dev.frags = 0; 8762306a36Sopenharmony_ci while (remaining > 0) { 8862306a36Sopenharmony_ci phys_addr_t addr; 8962306a36Sopenharmony_ci int chunk; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci addr = snd_sgbuf_get_addr(dmab_data, offset); 9262306a36Sopenharmony_ci bdl[0] = cpu_to_le32(lower_32_bits(addr)); 9362306a36Sopenharmony_ci bdl[1] = cpu_to_le32(upper_32_bits(addr)); 9462306a36Sopenharmony_ci chunk = snd_sgbuf_get_chunk_size(dmab_data, offset, size); 9562306a36Sopenharmony_ci bdl[2] = cpu_to_le32(chunk); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci remaining -= chunk; 9862306a36Sopenharmony_ci bdl[3] = (remaining > 0) ? 0 : cpu_to_le32(0x01); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci bdl += 4; 10162306a36Sopenharmony_ci offset += chunk; 10262306a36Sopenharmony_ci ctx->cl_dev.frags++; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/* 10762306a36Sopenharmony_ci * Setup controller 10862306a36Sopenharmony_ci * Configure the registers to update the dma buffer address and 10962306a36Sopenharmony_ci * enable interrupts. 11062306a36Sopenharmony_ci * Note: Using the channel 1 for transfer 11162306a36Sopenharmony_ci */ 11262306a36Sopenharmony_cistatic void skl_cldma_setup_controller(struct sst_dsp *ctx, 11362306a36Sopenharmony_ci struct snd_dma_buffer *dmab_bdl, unsigned int max_size, 11462306a36Sopenharmony_ci u32 count) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci skl_cldma_stream_clear(ctx); 11762306a36Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL, 11862306a36Sopenharmony_ci CL_SD_BDLPLBA(dmab_bdl->addr)); 11962306a36Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU, 12062306a36Sopenharmony_ci CL_SD_BDLPUBA(dmab_bdl->addr)); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_CBL, max_size); 12362306a36Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_LVI, count - 1); 12462306a36Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 12562306a36Sopenharmony_ci CL_SD_CTL_IOCE_MASK, CL_SD_CTL_IOCE(1)); 12662306a36Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 12762306a36Sopenharmony_ci CL_SD_CTL_FEIE_MASK, CL_SD_CTL_FEIE(1)); 12862306a36Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 12962306a36Sopenharmony_ci CL_SD_CTL_DEIE_MASK, CL_SD_CTL_DEIE(1)); 13062306a36Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 13162306a36Sopenharmony_ci CL_SD_CTL_STRM_MASK, CL_SD_CTL_STRM(FW_CL_STREAM_NUMBER)); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic void skl_cldma_setup_spb(struct sst_dsp *ctx, 13562306a36Sopenharmony_ci unsigned int size, bool enable) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci if (enable) 13862306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, 13962306a36Sopenharmony_ci SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL, 14062306a36Sopenharmony_ci CL_SPBFIFO_SPBFCCTL_SPIBE_MASK, 14162306a36Sopenharmony_ci CL_SPBFIFO_SPBFCCTL_SPIBE(1)); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_CL_SPBFIFO_SPIB, size); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic void skl_cldma_cleanup_spb(struct sst_dsp *ctx) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, 14962306a36Sopenharmony_ci SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL, 15062306a36Sopenharmony_ci CL_SPBFIFO_SPBFCCTL_SPIBE_MASK, 15162306a36Sopenharmony_ci CL_SPBFIFO_SPBFCCTL_SPIBE(0)); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_CL_SPBFIFO_SPIB, 0); 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic void skl_cldma_cleanup(struct sst_dsp *ctx) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci skl_cldma_cleanup_spb(ctx); 15962306a36Sopenharmony_ci skl_cldma_stream_clear(ctx); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data); 16262306a36Sopenharmony_ci ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_bdl); 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ciint skl_cldma_wait_interruptible(struct sst_dsp *ctx) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci int ret = 0; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci if (!wait_event_timeout(ctx->cl_dev.wait_queue, 17062306a36Sopenharmony_ci ctx->cl_dev.wait_condition, 17162306a36Sopenharmony_ci msecs_to_jiffies(SKL_WAIT_TIMEOUT))) { 17262306a36Sopenharmony_ci dev_err(ctx->dev, "%s: Wait timeout\n", __func__); 17362306a36Sopenharmony_ci ret = -EIO; 17462306a36Sopenharmony_ci goto cleanup; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci dev_dbg(ctx->dev, "%s: Event wake\n", __func__); 17862306a36Sopenharmony_ci if (ctx->cl_dev.wake_status != SKL_CL_DMA_BUF_COMPLETE) { 17962306a36Sopenharmony_ci dev_err(ctx->dev, "%s: DMA Error\n", __func__); 18062306a36Sopenharmony_ci ret = -EIO; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cicleanup: 18462306a36Sopenharmony_ci ctx->cl_dev.wake_status = SKL_CL_DMA_STATUS_NONE; 18562306a36Sopenharmony_ci return ret; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic void skl_cldma_stop(struct sst_dsp *ctx) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci skl_cldma_stream_run(ctx, false); 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistatic void skl_cldma_fill_buffer(struct sst_dsp *ctx, unsigned int size, 19462306a36Sopenharmony_ci const void *curr_pos, bool intr_enable, bool trigger) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci dev_dbg(ctx->dev, "Size: %x, intr_enable: %d\n", size, intr_enable); 19762306a36Sopenharmony_ci dev_dbg(ctx->dev, "buf_pos_index:%d, trigger:%d\n", 19862306a36Sopenharmony_ci ctx->cl_dev.dma_buffer_offset, trigger); 19962306a36Sopenharmony_ci dev_dbg(ctx->dev, "spib position: %d\n", ctx->cl_dev.curr_spib_pos); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* 20262306a36Sopenharmony_ci * Check if the size exceeds buffer boundary. If it exceeds 20362306a36Sopenharmony_ci * max_buffer size, then copy till buffer size and then copy 20462306a36Sopenharmony_ci * remaining buffer from the start of ring buffer. 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_ci if (ctx->cl_dev.dma_buffer_offset + size > ctx->cl_dev.bufsize) { 20762306a36Sopenharmony_ci unsigned int size_b = ctx->cl_dev.bufsize - 20862306a36Sopenharmony_ci ctx->cl_dev.dma_buffer_offset; 20962306a36Sopenharmony_ci memcpy(ctx->cl_dev.dmab_data.area + ctx->cl_dev.dma_buffer_offset, 21062306a36Sopenharmony_ci curr_pos, size_b); 21162306a36Sopenharmony_ci size -= size_b; 21262306a36Sopenharmony_ci curr_pos += size_b; 21362306a36Sopenharmony_ci ctx->cl_dev.dma_buffer_offset = 0; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci memcpy(ctx->cl_dev.dmab_data.area + ctx->cl_dev.dma_buffer_offset, 21762306a36Sopenharmony_ci curr_pos, size); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (ctx->cl_dev.curr_spib_pos == ctx->cl_dev.bufsize) 22062306a36Sopenharmony_ci ctx->cl_dev.dma_buffer_offset = 0; 22162306a36Sopenharmony_ci else 22262306a36Sopenharmony_ci ctx->cl_dev.dma_buffer_offset = ctx->cl_dev.curr_spib_pos; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci ctx->cl_dev.wait_condition = false; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (intr_enable) 22762306a36Sopenharmony_ci skl_cldma_int_enable(ctx); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci ctx->cl_dev.ops.cl_setup_spb(ctx, ctx->cl_dev.curr_spib_pos, trigger); 23062306a36Sopenharmony_ci if (trigger) 23162306a36Sopenharmony_ci ctx->cl_dev.ops.cl_trigger(ctx, true); 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci/* 23562306a36Sopenharmony_ci * The CL dma doesn't have any way to update the transfer status until a BDL 23662306a36Sopenharmony_ci * buffer is fully transferred 23762306a36Sopenharmony_ci * 23862306a36Sopenharmony_ci * So Copying is divided in two parts. 23962306a36Sopenharmony_ci * 1. Interrupt on buffer done where the size to be transferred is more than 24062306a36Sopenharmony_ci * ring buffer size. 24162306a36Sopenharmony_ci * 2. Polling on fw register to identify if data left to transferred doesn't 24262306a36Sopenharmony_ci * fill the ring buffer. Caller takes care of polling the required status 24362306a36Sopenharmony_ci * register to identify the transfer status. 24462306a36Sopenharmony_ci * 3. if wait flag is set, waits for DBL interrupt to copy the next chunk till 24562306a36Sopenharmony_ci * bytes_left is 0. 24662306a36Sopenharmony_ci * if wait flag is not set, doesn't wait for BDL interrupt. after ccopying 24762306a36Sopenharmony_ci * the first chunk return the no of bytes_left to be copied. 24862306a36Sopenharmony_ci */ 24962306a36Sopenharmony_cistatic int 25062306a36Sopenharmony_ciskl_cldma_copy_to_buf(struct sst_dsp *ctx, const void *bin, 25162306a36Sopenharmony_ci u32 total_size, bool wait) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci int ret; 25462306a36Sopenharmony_ci bool start = true; 25562306a36Sopenharmony_ci unsigned int excess_bytes; 25662306a36Sopenharmony_ci u32 size; 25762306a36Sopenharmony_ci unsigned int bytes_left = total_size; 25862306a36Sopenharmony_ci const void *curr_pos = bin; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci if (total_size <= 0) 26162306a36Sopenharmony_ci return -EINVAL; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci dev_dbg(ctx->dev, "%s: Total binary size: %u\n", __func__, bytes_left); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci while (bytes_left) { 26662306a36Sopenharmony_ci if (bytes_left > ctx->cl_dev.bufsize) { 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* 26962306a36Sopenharmony_ci * dma transfers only till the write pointer as 27062306a36Sopenharmony_ci * updated in spib 27162306a36Sopenharmony_ci */ 27262306a36Sopenharmony_ci if (ctx->cl_dev.curr_spib_pos == 0) 27362306a36Sopenharmony_ci ctx->cl_dev.curr_spib_pos = ctx->cl_dev.bufsize; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci size = ctx->cl_dev.bufsize; 27662306a36Sopenharmony_ci skl_cldma_fill_buffer(ctx, size, curr_pos, true, start); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (wait) { 27962306a36Sopenharmony_ci start = false; 28062306a36Sopenharmony_ci ret = skl_cldma_wait_interruptible(ctx); 28162306a36Sopenharmony_ci if (ret < 0) { 28262306a36Sopenharmony_ci skl_cldma_stop(ctx); 28362306a36Sopenharmony_ci return ret; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci } else { 28762306a36Sopenharmony_ci skl_cldma_int_disable(ctx); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci if ((ctx->cl_dev.curr_spib_pos + bytes_left) 29062306a36Sopenharmony_ci <= ctx->cl_dev.bufsize) { 29162306a36Sopenharmony_ci ctx->cl_dev.curr_spib_pos += bytes_left; 29262306a36Sopenharmony_ci } else { 29362306a36Sopenharmony_ci excess_bytes = bytes_left - 29462306a36Sopenharmony_ci (ctx->cl_dev.bufsize - 29562306a36Sopenharmony_ci ctx->cl_dev.curr_spib_pos); 29662306a36Sopenharmony_ci ctx->cl_dev.curr_spib_pos = excess_bytes; 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci size = bytes_left; 30062306a36Sopenharmony_ci skl_cldma_fill_buffer(ctx, size, 30162306a36Sopenharmony_ci curr_pos, false, start); 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci bytes_left -= size; 30462306a36Sopenharmony_ci curr_pos = curr_pos + size; 30562306a36Sopenharmony_ci if (!wait) 30662306a36Sopenharmony_ci return bytes_left; 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci return bytes_left; 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_civoid skl_cldma_process_intr(struct sst_dsp *ctx) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci u8 cl_dma_intr_status; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci cl_dma_intr_status = 31762306a36Sopenharmony_ci sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_CL_SD_STS); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (!(cl_dma_intr_status & SKL_CL_DMA_SD_INT_COMPLETE)) 32062306a36Sopenharmony_ci ctx->cl_dev.wake_status = SKL_CL_DMA_ERR; 32162306a36Sopenharmony_ci else 32262306a36Sopenharmony_ci ctx->cl_dev.wake_status = SKL_CL_DMA_BUF_COMPLETE; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci ctx->cl_dev.wait_condition = true; 32562306a36Sopenharmony_ci wake_up(&ctx->cl_dev.wait_queue); 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ciint skl_cldma_prepare(struct sst_dsp *ctx) 32962306a36Sopenharmony_ci{ 33062306a36Sopenharmony_ci int ret; 33162306a36Sopenharmony_ci __le32 *bdl; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci ctx->cl_dev.bufsize = SKL_MAX_BUFFER_SIZE; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* Allocate cl ops */ 33662306a36Sopenharmony_ci ctx->cl_dev.ops.cl_setup_bdle = skl_cldma_setup_bdle; 33762306a36Sopenharmony_ci ctx->cl_dev.ops.cl_setup_controller = skl_cldma_setup_controller; 33862306a36Sopenharmony_ci ctx->cl_dev.ops.cl_setup_spb = skl_cldma_setup_spb; 33962306a36Sopenharmony_ci ctx->cl_dev.ops.cl_cleanup_spb = skl_cldma_cleanup_spb; 34062306a36Sopenharmony_ci ctx->cl_dev.ops.cl_trigger = skl_cldma_stream_run; 34162306a36Sopenharmony_ci ctx->cl_dev.ops.cl_cleanup_controller = skl_cldma_cleanup; 34262306a36Sopenharmony_ci ctx->cl_dev.ops.cl_copy_to_dmabuf = skl_cldma_copy_to_buf; 34362306a36Sopenharmony_ci ctx->cl_dev.ops.cl_stop_dma = skl_cldma_stop; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* Allocate buffer*/ 34662306a36Sopenharmony_ci ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, ctx->dev, ctx->cl_dev.bufsize, 34762306a36Sopenharmony_ci &ctx->cl_dev.dmab_data); 34862306a36Sopenharmony_ci if (ret < 0) { 34962306a36Sopenharmony_ci dev_err(ctx->dev, "Alloc buffer for base fw failed: %x\n", ret); 35062306a36Sopenharmony_ci return ret; 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci /* Setup Code loader BDL */ 35462306a36Sopenharmony_ci ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, ctx->dev, BDL_SIZE, &ctx->cl_dev.dmab_bdl); 35562306a36Sopenharmony_ci if (ret < 0) { 35662306a36Sopenharmony_ci dev_err(ctx->dev, "Alloc buffer for blde failed: %x\n", ret); 35762306a36Sopenharmony_ci ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data); 35862306a36Sopenharmony_ci return ret; 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci bdl = (__le32 *)ctx->cl_dev.dmab_bdl.area; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci /* Allocate BDLs */ 36362306a36Sopenharmony_ci ctx->cl_dev.ops.cl_setup_bdle(ctx, &ctx->cl_dev.dmab_data, 36462306a36Sopenharmony_ci &bdl, ctx->cl_dev.bufsize, 1); 36562306a36Sopenharmony_ci ctx->cl_dev.ops.cl_setup_controller(ctx, &ctx->cl_dev.dmab_bdl, 36662306a36Sopenharmony_ci ctx->cl_dev.bufsize, ctx->cl_dev.frags); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci ctx->cl_dev.curr_spib_pos = 0; 36962306a36Sopenharmony_ci ctx->cl_dev.dma_buffer_offset = 0; 37062306a36Sopenharmony_ci init_waitqueue_head(&ctx->cl_dev.wait_queue); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci return ret; 37362306a36Sopenharmony_ci} 374