2 * sst_dsp.c - Intel SST Driver for audio engine
4 * Copyright (C) 2008-14 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 * This file contains all dsp controlling functions like firmware download,
23 * setting/resetting dsp cores, etc
25 #include <linux/pci.h>
26 #include <linux/delay.h>
28 #include <linux/sched.h>
29 #include <linux/firmware.h>
30 #include <linux/dmaengine.h>
31 #include <linux/pm_runtime.h>
32 #include <linux/pm_qos.h>
33 #include <sound/core.h>
34 #include <sound/pcm.h>
35 #include <sound/soc.h>
36 #include <sound/compress_driver.h>
37 #include <asm/platform_sst_audio.h>
38 #include "../sst-mfld-platform.h"
40 #include "../sst-dsp.h"
42 static inline void memcpy32_toio(void __iomem
*dst
, const void *src
, int count
)
44 /* __iowrite32_copy uses 32-bit count values so divide by 4 for
45 * right count in words
47 __iowrite32_copy(dst
, src
, count
/4);
51 * intel_sst_reset_dsp_mrfld - Resetting SST DSP
53 * This resets DSP in case of MRFLD platfroms
55 int intel_sst_reset_dsp_mrfld(struct intel_sst_drv
*sst_drv_ctx
)
57 union config_status_reg_mrfld csr
;
59 dev_dbg(sst_drv_ctx
->dev
, "sst: Resetting the DSP in mrfld\n");
60 csr
.full
= sst_shim_read64(sst_drv_ctx
->shim
, SST_CSR
);
62 dev_dbg(sst_drv_ctx
->dev
, "value:0x%llx\n", csr
.full
);
65 sst_shim_write64(sst_drv_ctx
->shim
, SST_CSR
, csr
.full
);
66 csr
.full
= sst_shim_read64(sst_drv_ctx
->shim
, SST_CSR
);
68 dev_dbg(sst_drv_ctx
->dev
, "value:0x%llx\n", csr
.full
);
71 sst_shim_write64(sst_drv_ctx
->shim
, SST_CSR
, csr
.full
);
73 csr
.full
= sst_shim_read64(sst_drv_ctx
->shim
, SST_CSR
);
74 dev_dbg(sst_drv_ctx
->dev
, "value:0x%llx\n", csr
.full
);
79 * sst_start_merrifield - Start the SST DSP processor
81 * This starts the DSP in MERRIFIELD platfroms
83 int sst_start_mrfld(struct intel_sst_drv
*sst_drv_ctx
)
85 union config_status_reg_mrfld csr
;
87 dev_dbg(sst_drv_ctx
->dev
, "sst: Starting the DSP in mrfld LALALALA\n");
88 csr
.full
= sst_shim_read64(sst_drv_ctx
->shim
, SST_CSR
);
89 dev_dbg(sst_drv_ctx
->dev
, "value:0x%llx\n", csr
.full
);
92 sst_shim_write64(sst_drv_ctx
->shim
, SST_CSR
, csr
.full
);
94 csr
.full
= sst_shim_read64(sst_drv_ctx
->shim
, SST_CSR
);
95 dev_dbg(sst_drv_ctx
->dev
, "value:0x%llx\n", csr
.full
);
97 csr
.part
.xt_snoop
= 1;
99 sst_shim_write64(sst_drv_ctx
->shim
, SST_CSR
, csr
.full
);
101 csr
.full
= sst_shim_read64(sst_drv_ctx
->shim
, SST_CSR
);
102 dev_dbg(sst_drv_ctx
->dev
, "sst: Starting the DSP_merrifield:%llx\n",
107 static int sst_validate_fw_image(struct intel_sst_drv
*ctx
, unsigned long size
,
108 struct fw_module_header
**module
, u32
*num_modules
)
110 struct sst_fw_header
*header
;
111 const void *sst_fw_in_mem
= ctx
->fw_in_mem
;
113 dev_dbg(ctx
->dev
, "Enter\n");
115 /* Read the header information from the data pointer */
116 header
= (struct sst_fw_header
*)sst_fw_in_mem
;
118 "header sign=%s size=%x modules=%x fmt=%x size=%zx\n",
119 header
->signature
, header
->file_size
, header
->modules
,
120 header
->file_format
, sizeof(*header
));
123 if ((strncmp(header
->signature
, SST_FW_SIGN
, 4) != 0) ||
124 (size
!= header
->file_size
+ sizeof(*header
))) {
125 /* Invalid FW signature */
126 dev_err(ctx
->dev
, "InvalidFW sign/filesize mismatch\n");
129 *num_modules
= header
->modules
;
130 *module
= (void *)sst_fw_in_mem
+ sizeof(*header
);
136 * sst_fill_memcpy_list - Fill the memcpy list
138 * @memcpy_list: List to be filled
139 * @destn: Destination addr to be filled in the list
140 * @src: Source addr to be filled in the list
141 * @size: Size to be filled in the list
143 * Adds the node to the list after required fields
144 * are populated in the node
146 static int sst_fill_memcpy_list(struct list_head
*memcpy_list
,
147 void *destn
, const void *src
, u32 size
, bool is_io
)
149 struct sst_memcpy_list
*listnode
;
151 listnode
= kzalloc(sizeof(*listnode
), GFP_KERNEL
);
152 if (listnode
== NULL
)
154 listnode
->dstn
= destn
;
156 listnode
->size
= size
;
157 listnode
->is_io
= is_io
;
158 list_add_tail(&listnode
->memcpylist
, memcpy_list
);
164 * sst_parse_module_memcpy - Parse audio FW modules and populate the memcpy list
166 * @sst_drv_ctx : driver context
167 * @module : FW module header
168 * @memcpy_list : Pointer to the list to be populated
169 * Create the memcpy list as the number of block to be copied
170 * returns error or 0 if module sizes are proper
172 static int sst_parse_module_memcpy(struct intel_sst_drv
*sst_drv_ctx
,
173 struct fw_module_header
*module
, struct list_head
*memcpy_list
)
175 struct fw_block_info
*block
;
178 void __iomem
*ram_iomem
;
180 dev_dbg(sst_drv_ctx
->dev
, "module sign %s size %x blocks %x type %x\n",
181 module
->signature
, module
->mod_size
,
182 module
->blocks
, module
->type
);
183 dev_dbg(sst_drv_ctx
->dev
, "module entrypoint 0x%x\n", module
->entry_point
);
185 block
= (void *)module
+ sizeof(*module
);
187 for (count
= 0; count
< module
->blocks
; count
++) {
188 if (block
->size
<= 0) {
189 dev_err(sst_drv_ctx
->dev
, "block size invalid\n");
192 switch (block
->type
) {
194 ram_iomem
= sst_drv_ctx
->iram
;
197 ram_iomem
= sst_drv_ctx
->dram
;
200 ram_iomem
= sst_drv_ctx
->ddr
;
202 case SST_CUSTOM_INFO
:
203 block
= (void *)block
+ sizeof(*block
) + block
->size
;
206 dev_err(sst_drv_ctx
->dev
, "wrong ram type0x%x in block0x%x\n",
211 ret_val
= sst_fill_memcpy_list(memcpy_list
,
212 ram_iomem
+ block
->ram_offset
,
213 (void *)block
+ sizeof(*block
), block
->size
, 1);
217 block
= (void *)block
+ sizeof(*block
) + block
->size
;
223 * sst_parse_fw_memcpy - parse the firmware image & populate the list for memcpy
225 * @ctx : pointer to drv context
226 * @size : size of the firmware
227 * @fw_list : pointer to list_head to be populated
228 * This function parses the FW image and saves the parsed image in the list
231 static int sst_parse_fw_memcpy(struct intel_sst_drv
*ctx
, unsigned long size
,
232 struct list_head
*fw_list
)
234 struct fw_module_header
*module
;
235 u32 count
, num_modules
;
238 ret_val
= sst_validate_fw_image(ctx
, size
, &module
, &num_modules
);
242 for (count
= 0; count
< num_modules
; count
++) {
243 ret_val
= sst_parse_module_memcpy(ctx
, module
, fw_list
);
246 module
= (void *)module
+ sizeof(*module
) + module
->mod_size
;
253 * sst_do_memcpy - function initiates the memcpy
255 * @memcpy_list: Pter to memcpy list on which the memcpy needs to be initiated
257 * Triggers the memcpy
259 static void sst_do_memcpy(struct list_head
*memcpy_list
)
261 struct sst_memcpy_list
*listnode
;
263 list_for_each_entry(listnode
, memcpy_list
, memcpylist
) {
264 if (listnode
->is_io
== true)
265 memcpy32_toio((void __iomem
*)listnode
->dstn
,
266 listnode
->src
, listnode
->size
);
268 memcpy(listnode
->dstn
, listnode
->src
, listnode
->size
);
272 void sst_memcpy_free_resources(struct intel_sst_drv
*sst_drv_ctx
)
274 struct sst_memcpy_list
*listnode
, *tmplistnode
;
277 if (!list_empty(&sst_drv_ctx
->memcpy_list
)) {
278 list_for_each_entry_safe(listnode
, tmplistnode
,
279 &sst_drv_ctx
->memcpy_list
, memcpylist
) {
280 list_del(&listnode
->memcpylist
);
286 static int sst_cache_and_parse_fw(struct intel_sst_drv
*sst
,
287 const struct firmware
*fw
)
291 sst
->fw_in_mem
= kzalloc(fw
->size
, GFP_KERNEL
);
292 if (!sst
->fw_in_mem
) {
296 dev_dbg(sst
->dev
, "copied fw to %p", sst
->fw_in_mem
);
297 dev_dbg(sst
->dev
, "phys: %lx", (unsigned long)virt_to_phys(sst
->fw_in_mem
));
298 memcpy(sst
->fw_in_mem
, fw
->data
, fw
->size
);
299 retval
= sst_parse_fw_memcpy(sst
, fw
->size
, &sst
->memcpy_list
);
301 dev_err(sst
->dev
, "Failed to parse fw\n");
302 kfree(sst
->fw_in_mem
);
303 sst
->fw_in_mem
= NULL
;
307 release_firmware(fw
);
312 void sst_firmware_load_cb(const struct firmware
*fw
, void *context
)
314 struct intel_sst_drv
*ctx
= context
;
316 dev_dbg(ctx
->dev
, "Enter\n");
319 dev_err(ctx
->dev
, "request fw failed\n");
323 mutex_lock(&ctx
->sst_lock
);
325 if (ctx
->sst_state
!= SST_RESET
||
326 ctx
->fw_in_mem
!= NULL
) {
328 release_firmware(fw
);
329 mutex_unlock(&ctx
->sst_lock
);
333 dev_dbg(ctx
->dev
, "Request Fw completed\n");
334 sst_cache_and_parse_fw(ctx
, fw
);
335 mutex_unlock(&ctx
->sst_lock
);
339 * sst_request_fw - requests audio fw from kernel and saves a copy
341 * This function requests the SST FW from the kernel, parses it and
342 * saves a copy in the driver context
344 static int sst_request_fw(struct intel_sst_drv
*sst
)
347 const struct firmware
*fw
;
349 retval
= request_firmware(&fw
, sst
->firmware_name
, sst
->dev
);
351 dev_err(sst
->dev
, "fw is returning as null\n");
355 dev_err(sst
->dev
, "request fw failed %d\n", retval
);
358 mutex_lock(&sst
->sst_lock
);
359 retval
= sst_cache_and_parse_fw(sst
, fw
);
360 mutex_unlock(&sst
->sst_lock
);
366 * Writing the DDR physical base to DCCM offset
367 * so that FW can use it to setup TLB
369 static void sst_dccm_config_write(void __iomem
*dram_base
,
370 unsigned int ddr_base
)
375 addr
= (void __iomem
*)(dram_base
+ MRFLD_FW_DDR_BASE_OFFSET
);
376 memcpy32_toio(addr
, (void *)&ddr_base
, sizeof(u32
));
377 bss_reset
|= (1 << MRFLD_FW_BSS_RESET_BIT
);
378 addr
= (void __iomem
*)(dram_base
+ MRFLD_FW_FEATURE_BASE_OFFSET
);
379 memcpy32_toio(addr
, &bss_reset
, sizeof(u32
));
383 void sst_post_download_mrfld(struct intel_sst_drv
*ctx
)
385 sst_dccm_config_write(ctx
->dram
, ctx
->ddr_base
);
386 dev_dbg(ctx
->dev
, "config written to DCCM\n");
390 * sst_load_fw - function to load FW into DSP
391 * Transfers the FW to DSP using dma/memcpy
393 int sst_load_fw(struct intel_sst_drv
*sst_drv_ctx
)
396 struct sst_block
*block
;
398 dev_dbg(sst_drv_ctx
->dev
, "sst_load_fw\n");
400 if (sst_drv_ctx
->sst_state
!= SST_RESET
||
401 sst_drv_ctx
->sst_state
== SST_SHUTDOWN
)
404 if (!sst_drv_ctx
->fw_in_mem
) {
405 dev_dbg(sst_drv_ctx
->dev
, "sst: FW not in memory retry to download\n");
406 ret_val
= sst_request_fw(sst_drv_ctx
);
411 BUG_ON(!sst_drv_ctx
->fw_in_mem
);
412 block
= sst_create_block(sst_drv_ctx
, 0, FW_DWNL_ID
);
416 /* Prevent C-states beyond C6 */
417 pm_qos_update_request(sst_drv_ctx
->qos
, 0);
419 sst_drv_ctx
->sst_state
= SST_FW_LOADING
;
421 ret_val
= sst_drv_ctx
->ops
->reset(sst_drv_ctx
);
425 sst_do_memcpy(&sst_drv_ctx
->memcpy_list
);
427 /* Write the DRAM/DCCM config before enabling FW */
428 if (sst_drv_ctx
->ops
->post_download
)
429 sst_drv_ctx
->ops
->post_download(sst_drv_ctx
);
431 /* bring sst out of reset */
432 ret_val
= sst_drv_ctx
->ops
->start(sst_drv_ctx
);
436 ret_val
= sst_wait_timeout(sst_drv_ctx
, block
);
438 dev_err(sst_drv_ctx
->dev
, "fw download failed %d\n" , ret_val
);
439 /* FW download failed due to timeout */
446 /* Re-enable Deeper C-states beyond C6 */
447 pm_qos_update_request(sst_drv_ctx
->qos
, PM_QOS_DEFAULT_VALUE
);
448 sst_free_block(sst_drv_ctx
, block
);
449 dev_dbg(sst_drv_ctx
->dev
, "fw load successful!!!\n");
451 if (sst_drv_ctx
->ops
->restore_dsp_context
)
452 sst_drv_ctx
->ops
->restore_dsp_context();
453 sst_drv_ctx
->sst_state
= SST_FW_RUNNING
;