Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ef015e6 authored by Ramesh Babu's avatar Ramesh Babu Committed by Mark Brown
Browse files

ASoC: Intel: Skylake: Add library loading support



The library load is added as one of the ops in skl_dsp_fw_ops().

The manifest load gives the files to be loaded which are loaded during
the fw_init()

Signed-off-by: default avatarRamesh Babu <ramesh.babu@intel.com>
Signed-off-by: default avatarKranthi G <gudishax.kranthikumar@intel.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 004d94e5
Loading
Loading
Loading
Loading
+83 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "../common/sst-dsp.h"
#include "../common/sst-dsp-priv.h"
#include "skl-sst-ipc.h"
#include "skl-tplg-interface.h"

#define BXT_BASEFW_TIMEOUT	3000
#define BXT_INIT_TIMEOUT	500
@@ -40,11 +41,73 @@
#define BXT_INSTANCE_ID 0
#define BXT_BASE_FW_MODULE_ID 0

#define BXT_ADSP_FW_BIN_HDR_OFFSET 0x2000

static unsigned int bxt_get_errorcode(struct sst_dsp *ctx)
{
	 return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE);
}

static int
bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo)
{
	struct snd_dma_buffer dmab;
	struct skl_sst *skl = ctx->thread_context;
	const struct firmware *fw = NULL;
	struct firmware stripped_fw;
	int ret = 0, i, dma_id, stream_tag;

	/* library indices start from 1 to N. 0 represents base FW */
	for (i = 1; i < minfo->lib_count; i++) {
		ret = request_firmware(&fw, minfo->lib[i].name, ctx->dev);
		if (ret < 0) {
			dev_err(ctx->dev, "Request lib %s failed:%d\n",
					minfo->lib[i].name, ret);
			return ret;
		}

		if (skl->is_first_boot) {
			ret = snd_skl_parse_uuids(ctx, fw,
					BXT_ADSP_FW_BIN_HDR_OFFSET, i);
			if (ret < 0)
				goto load_library_failed;
		}

		stripped_fw.data = fw->data;
		stripped_fw.size = fw->size;
		skl_dsp_strip_extended_manifest(&stripped_fw);

		stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40,
					stripped_fw.size, &dmab);
		if (stream_tag <= 0) {
			dev_err(ctx->dev, "Lib prepare DMA err: %x\n",
					stream_tag);
			ret = stream_tag;
			goto load_library_failed;
		}

		dma_id = stream_tag - 1;
		memcpy(dmab.area, stripped_fw.data, stripped_fw.size);

		ctx->dsp_ops.trigger(ctx->dev, true, stream_tag);
		ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i);
		if (ret < 0)
			dev_err(ctx->dev, "IPC Load Lib for %s fail: %d\n",
					minfo->lib[i].name, ret);

		ctx->dsp_ops.trigger(ctx->dev, false, stream_tag);
		ctx->dsp_ops.cleanup(ctx->dev, &dmab, stream_tag);
		release_firmware(fw);
		fw = NULL;
	}

	return ret;

load_library_failed:
	release_firmware(fw);
	return ret;
}

/*
 * First boot sequence has some extra steps. Core 0 waits for power
 * status on core 1, so power up core 1 also momentarily, keep it in
@@ -157,8 +220,6 @@ static int sst_transfer_fw_host_dma(struct sst_dsp *ctx)
	return ret;
}

#define BXT_ADSP_FW_BIN_HDR_OFFSET 0x2000

static int bxt_load_base_firmware(struct sst_dsp *ctx)
{
	struct firmware stripped_fw;
@@ -233,15 +294,26 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
	int ret;
	struct skl_ipc_dxstate_info dx;
	unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
	struct skl_dfw_manifest *minfo = &skl->manifest;

	if (skl->fw_loaded == false) {
		skl->boot_complete = false;
		ret = bxt_load_base_firmware(ctx);
		if (ret < 0)
		if (ret < 0) {
			dev_err(ctx->dev, "reload fw failed: %d\n", ret);
			return ret;
		}

		if (minfo->lib_count > 1) {
			ret = bxt_load_library(ctx, minfo);
			if (ret < 0) {
				dev_err(ctx->dev, "reload libs failed: %d\n", ret);
				return ret;
			}
		}
		return ret;
	}

	/* If core 0 is being turned on, turn on core 1 as well */
	if (core_id == SKL_DSP_CORE0_ID)
		ret = skl_dsp_core_power_up(ctx, core_mask |
@@ -344,6 +416,7 @@ static struct skl_dsp_fw_ops bxt_fw_ops = {
	.set_state_D3 = bxt_set_dsp_D3,
	.load_fw = bxt_load_base_firmware,
	.get_fw_errcode = bxt_get_errorcode,
	.load_library = bxt_load_library,
};

static struct sst_ops skl_ops = {
@@ -422,6 +495,13 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx)

	skl_dsp_init_core_state(sst);

	if (ctx->manifest.lib_count > 1) {
		ret = sst->fw_ops.load_library(sst, &ctx->manifest);
		if (ret < 0) {
			dev_err(dev, "Load Library failed : %x", ret);
			return ret;
		}
	}
	ctx->is_first_boot = false;

	return 0;
+2 −0
Original line number Diff line number Diff line
@@ -133,6 +133,8 @@ enum skl_dsp_states {
struct skl_dsp_fw_ops {
	int (*load_fw)(struct sst_dsp  *ctx);
	/* FW module parser/loader */
	int (*load_library)(struct sst_dsp *ctx,
		struct skl_dfw_manifest *minfo);
	int (*parse_fw)(struct sst_dsp *ctx);
	int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id);
	int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id);