Unverified Commit cbe37a4d authored by Amadeusz Sławiński's avatar Amadeusz Sławiński Committed by Mark Brown
Browse files

ASoC: Intel: avs: Configure basefw on TGL-based platforms



The AudioDSP firmware requires additional information about the
configuration on selected devices. That information is unaccessible from
the DSP side and shall be sent before any streaming starts.

To achieve the goal, introduce FW_CONFIG_SET request. FW_CONFIG_SET
message allows driver to modify firmware's configuration. Multiple
parameters can be modified at once, thanks to payload being an array of
TLVs.

Signed-off-by: default avatarAmadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Signed-off-by: default avatarCezary Rojewski <cezary.rojewski@intel.com>
Link: https://patch.msgid.link/20250203141051.2361323-8-cezary.rojewski@intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent e995c519
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -510,6 +510,44 @@ int avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg)
	return ret;
}

int avs_ipc_set_fw_config(struct avs_dev *adev, size_t num_tlvs, ...)
{
	struct avs_tlv *tlv;
	void *payload;
	size_t offset;
	va_list args;
	int ret, i;

	payload = kzalloc(AVS_MAILBOX_SIZE, GFP_KERNEL);
	if (!payload)
		return -ENOMEM;

	va_start(args, num_tlvs);
	for (offset = i = 0; i < num_tlvs && offset < AVS_MAILBOX_SIZE - sizeof(*tlv); i++) {
		tlv = (struct avs_tlv *)(payload + offset);
		tlv->type = va_arg(args, u32);
		tlv->length = va_arg(args, u32);

		offset += sizeof(*tlv) + tlv->length;
		if (offset > AVS_MAILBOX_SIZE)
			break;

		memcpy(tlv->value, va_arg(args, u8*), tlv->length);
	}

	if (i == num_tlvs)
		ret = avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID,
					       AVS_BASEFW_FIRMWARE_CONFIG, payload, offset);
	else
		ret = -ERANGE;

	va_end(args);
	kfree(payload);
	if (ret)
		dev_err(adev->dev, "set fw cfg failed: %d\n", ret);
	return ret;
}

int avs_ipc_get_hw_config(struct avs_dev *adev, struct avs_hw_cfg *cfg)
{
	struct avs_tlv *tlv;
+9 −0
Original line number Diff line number Diff line
@@ -451,6 +451,8 @@ enum avs_fw_cfg_params {
	AVS_FW_CFG_RESERVED,
	AVS_FW_CFG_POWER_GATING_POLICY,
	AVS_FW_CFG_ASSERT_MODE,
	AVS_FW_CFG_RESERVED2,
	AVS_FW_CFG_BUS_HARDWARE_ID,
};

struct avs_fw_cfg {
@@ -475,7 +477,14 @@ struct avs_fw_cfg {
	u32 power_gating_policy;
};

struct avs_bus_hwid {
	u32 device;
	u32 subsystem;
	u8 revision;
};

int avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg);
int avs_ipc_set_fw_config(struct avs_dev *adev, size_t num_tlvs, ...);

enum avs_hw_cfg_params {
	AVS_HW_CFG_AVS_VER,
+33 −0
Original line number Diff line number Diff line
@@ -6,7 +6,11 @@
//          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
//

#include <linux/pci.h>
#include "avs.h"
#include "messages.h"

#define CPUID_TSC_LEAF 0x15

static int avs_tgl_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power)
{
@@ -35,6 +39,34 @@ static int avs_tgl_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stal
	return avs_dsp_core_stall(adev, core_mask, stall);
}

static int avs_tgl_config_basefw(struct avs_dev *adev)
{
	struct pci_dev *pci = adev->base.pci;
	struct avs_bus_hwid hwid;
	int ret;
#ifdef CONFIG_X86
	unsigned int ecx;

#include <asm/cpuid.h>
	ecx = cpuid_ecx(CPUID_TSC_LEAF);
	if (ecx) {
		ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_XTAL_FREQ_HZ, sizeof(ecx), &ecx);
		if (ret)
			return AVS_IPC_RET(ret);
	}
#endif

	hwid.device = pci->device;
	hwid.subsystem = pci->subsystem_vendor | (pci->subsystem_device << 16);
	hwid.revision = pci->revision;

	ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_BUS_HARDWARE_ID, sizeof(hwid), &hwid);
	if (ret)
		return AVS_IPC_RET(ret);

	return 0;
}

const struct avs_dsp_ops avs_tgl_dsp_ops = {
	.power = avs_tgl_dsp_core_power,
	.reset = avs_tgl_dsp_core_reset,
@@ -44,6 +76,7 @@ const struct avs_dsp_ops avs_tgl_dsp_ops = {
	.load_basefw = avs_icl_load_basefw,
	.load_lib = avs_hda_load_library,
	.transfer_mods = avs_hda_transfer_modules,
	.config_basefw = avs_tgl_config_basefw,
	.log_buffer_offset = avs_icl_log_buffer_offset,
	.log_buffer_status = avs_apl_log_buffer_status,
	.coredump = avs_apl_coredump,