diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h index e05cb21023e557..7abc4f0bd3ade1 100644 --- a/include/sound/sof/ext_manifest.h +++ b/include/sound/sof/ext_manifest.h @@ -62,6 +62,7 @@ enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO, SOF_EXT_MAN_ELEM_DBG_ABI = SOF_IPC_EXT_USER_ABI_INFO, SOF_EXT_MAN_ELEM_CONFIG_DATA = 5, /**< ABI3.17 */ + SOF_EXT_MAN_ELEM_PLATFORM_CONFIG_DATA = 6, }; /* extended manifest element header */ diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 4eeade2e77f7f7..fc29b91b8932bd 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -92,6 +92,9 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .pre_fw_run = hda_dsp_pre_fw_run, .post_fw_run = hda_dsp_post_fw_run, + /* parse platform specific extended manifest */ + .parse_platform_ext_manifest = hda_dsp_ext_man_get_cavs_config_data, + /* dsp core power up/down */ .core_power_up = hda_dsp_enable_core, .core_power_down = hda_dsp_core_reset_power_down, diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index a5d3258104c08d..158c38743731ed 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -294,6 +294,9 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .pre_fw_run = hda_dsp_pre_fw_run, .post_fw_run = hda_dsp_post_fw_run, + /* parse platform specific extended manifest */ + .parse_platform_ext_manifest = hda_dsp_ext_man_get_cavs_config_data, + /* dsp core power up/down */ .core_power_up = hda_dsp_enable_core, .core_power_down = hda_dsp_core_reset_power_down, diff --git a/sound/soc/sof/intel/ext_manifest.h b/sound/soc/sof/intel/ext_manifest.h new file mode 100644 index 00000000000000..091d39a8570e80 --- /dev/null +++ b/sound/soc/sof/intel/ext_manifest.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + */ + +/* + * Intel extended manifest is a extra place to store Intel cavs specific + * metadata about firmware, for example LPRO/HPRO configuration is + * Intel cavs specific. This part of output binary is not signed. + */ + +#ifndef __INTEL_CAVS_EXT_MANIFEST_H__ +#define __INTEL_CAVS_EXT_MANIFEST_H__ + +#include + +/* EXT_MAN_ELEM_PLATFORM_CONFIG_DATA elements identificators */ +enum sof_cavs_config_elem_type { + SOF_EXT_MAN_CAVS_CONFIG_EMPTY = 0, + SOF_EXT_MAN_CAVS_CONFIG_CAVS_LPRO = 1, + SOF_EXT_MAN_CAVS_CONFIG_OUTBOX_SIZE = 2, + SOF_EXT_MAN_CAVS_CONFIG_INBOX_SIZE = 3, + SOF_EXT_MAN_CAVS_CONFIG_LAST_ELEM, /**< keep it at the end of enum list */ +}; + +/* EXT_MAN_ELEM_PLATFORM_CONFIG_DATA elements */ +struct sof_ext_man_cavs_config_data { + struct sof_ext_man_elem_header hdr; + + struct sof_config_elem elems[SOF_EXT_MAN_CAVS_CONFIG_LAST_ELEM]; +} __packed; + +#endif /* __INTEL_CAVS_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 2707a16c6a4d3d..0ee8928396d733 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -19,6 +19,7 @@ #include #include #include +#include "ext_manifest.h" #include "../ops.h" #include "hda.h" @@ -470,3 +471,39 @@ int hda_dsp_post_fw_run(struct snd_sof_dev *sdev) /* re-enable clock gating and power gating */ return hda_dsp_ctrl_clock_power_gating(sdev, true); } + +int hda_dsp_ext_man_get_cavs_config_data(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_cavs_config_data *config_data = + container_of(hdr, struct sof_ext_man_cavs_config_data, hdr); + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + int i, elem_num; + + /* calculate total number of config data elements */ + elem_num = (hdr->size - sizeof(struct sof_ext_man_elem_header)) / sizeof(struct sof_config_elem); + if (elem_num <= 0) { + dev_err(sdev->dev, "cavs config data is inconsistent: %d\n", elem_num); + return -EINVAL; + } + + for (i = 0; i < elem_num; i++) + switch (config_data->elems[i].token) { + case SOF_EXT_MAN_CAVS_CONFIG_EMPTY: + /* skip empty token */ + break; + case SOF_EXT_MAN_CAVS_CONFIG_CAVS_LPRO: + hda->clk_config_lpro = config_data->elems[i].value; + dev_dbg(sdev->dev, "FW clock config: %s\n", hda->clk_config_lpro ? "LPRO" : "HPRO"); + break; + case SOF_EXT_MAN_CAVS_CONFIG_OUTBOX_SIZE: + case SOF_EXT_MAN_CAVS_CONFIG_INBOX_SIZE: + /* This elem is supported but config data is not being used yet */ + break; + default: + dev_warn(sdev->dev, "unsupported token type: %d\n", + config_data->elems[i].token); + } + + return 0; +} diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 1bc4dabdd39450..3d1674bb5e7c09 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -447,6 +447,9 @@ struct sof_intel_hda_dev { /* sdw context allocated by SoundWire driver */ struct sdw_intel_ctx *sdw; + + /* FW clock config, 0:HPRO, 1:LPRO */ + bool clk_config_lpro; }; static inline struct hdac_bus *sof_to_bus(struct snd_sof_dev *s) @@ -618,6 +621,10 @@ int hda_dsp_cl_boot_firmware_skl(struct snd_sof_dev *sdev); int hda_dsp_pre_fw_run(struct snd_sof_dev *sdev); int hda_dsp_post_fw_run(struct snd_sof_dev *sdev); +/* parse platform specific ext manifest ops */ +int hda_dsp_ext_man_get_cavs_config_data(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr); + /* * HDA Controller Operations. */ diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 0278b67de1ecb6..6caf55871e743c 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -84,6 +84,9 @@ const struct snd_sof_dsp_ops sof_tgl_ops = { .pre_fw_run = hda_dsp_pre_fw_run, .post_fw_run = hda_dsp_post_fw_run, + /* parse platform specific extended manifest */ + .parse_platform_ext_manifest = hda_dsp_ext_man_get_cavs_config_data, + /* dsp core power up/down */ .core_power_up = hda_dsp_enable_core, .core_power_down = hda_dsp_core_reset_power_down, diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 2a8c9bff99639e..cbce484b64690e 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -330,6 +330,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, case SOF_EXT_MAN_ELEM_CONFIG_DATA: ret = ext_man_get_config_data(sdev, elem_hdr); break; + case SOF_EXT_MAN_ELEM_PLATFORM_CONFIG_DATA: + ret = snd_sof_dsp_parse_platform_ext_manifest(sdev, elem_hdr); + break; default: dev_info(sdev->dev, "unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index b21632f5511a10..77a6ac157d3774 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -100,6 +100,16 @@ static inline int snd_sof_dsp_post_fw_run(struct snd_sof_dev *sdev) return 0; } +/* parse platform specific extended manifest */ +static inline int snd_sof_dsp_parse_platform_ext_manifest(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + if (sof_ops(sdev)->parse_platform_ext_manifest) + return sof_ops(sdev)->parse_platform_ext_manifest(sdev, hdr); + + return 0; +} + /* misc */ /** diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index d8bc0178dc89d0..124cdeb0efdec2 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -18,6 +18,7 @@ #include #include #include +#include /* debug flags */ #define SOF_DBG_ENABLE_TRACE BIT(0) @@ -208,6 +209,10 @@ struct snd_sof_dsp_ops { int (*pre_fw_run)(struct snd_sof_dev *sof_dev); /* optional */ int (*post_fw_run)(struct snd_sof_dev *sof_dev); /* optional */ + /* parse platform specific extended manifest */ + int (*parse_platform_ext_manifest)(struct snd_sof_dev *sof_dev, + const struct sof_ext_man_elem_header *hdr); /* optional */ + /* DSP PM */ int (*suspend)(struct snd_sof_dev *sof_dev, u32 target_state); /* optional */