Skip to content

Cave Audio support, via CrOS topology compatibility #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: v4.16.18-galliumos
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions galliumos/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
linux-4.16.18-galliumos (4.16.18-galliumos5) bismuth; urgency=medium

cherry pick ac9391daac00:
"ASoC: topology: Improve backwards compatibility with v4 topology files"

linux-4.16.18-galliumos (4.16.18-galliumos4) bismuth; urgency=medium

* Add config for Apollo Lake chipset and audio
Expand Down
169 changes: 169 additions & 0 deletions sound/soc/intel/skylake/skl-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/firmware.h>
#include <linux/uuid.h>
#include <sound/soc.h>
#include <sound/soc-topology.h>
#include <uapi/sound/snd_sst_tokens.h>
Expand Down Expand Up @@ -2639,6 +2640,167 @@ static int skl_tplg_get_desc_blocks(struct device *dev,
return -EINVAL;
}

/* Functions to parse private data from configuration file format v4 */

/*
* Add pipeline from topology binary into driver pipeline list
*
* If already added we return that instance
* Otherwise we create a new instance and add into driver list
*/
static int skl_tplg_add_pipe_v4(struct device *dev,
struct skl_module_cfg *mconfig, struct skl *skl,
struct skl_dfw_v4_pipe *dfw_pipe)
{
struct skl_pipeline *ppl;
struct skl_pipe *pipe;
struct skl_pipe_params *params;

list_for_each_entry(ppl, &skl->ppl_list, node) {
if (ppl->pipe->ppl_id == dfw_pipe->pipe_id) {
mconfig->pipe = ppl->pipe;
return 0;
}
}

ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL);
if (!ppl)
return -ENOMEM;

pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL);
if (!pipe)
return -ENOMEM;

params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;

pipe->ppl_id = dfw_pipe->pipe_id;
pipe->memory_pages = dfw_pipe->memory_pages;
pipe->pipe_priority = dfw_pipe->pipe_priority;
pipe->conn_type = dfw_pipe->conn_type;
pipe->state = SKL_PIPE_INVALID;
pipe->p_params = params;
INIT_LIST_HEAD(&pipe->w_list);

ppl->pipe = pipe;
list_add(&ppl->node, &skl->ppl_list);

mconfig->pipe = pipe;

return 0;
}

static void skl_fill_module_pin_info_v4(struct skl_dfw_v4_module_pin *dfw_pin,
struct skl_module_pin *m_pin,
bool is_dynamic, int max_pin)
{
int i;

for (i = 0; i < max_pin; i++) {
m_pin[i].id.module_id = dfw_pin[i].module_id;
m_pin[i].id.instance_id = dfw_pin[i].instance_id;
m_pin[i].in_use = false;
m_pin[i].is_dynamic = is_dynamic;
m_pin[i].pin_state = SKL_PIN_UNBIND;
}
}

static void skl_tplg_fill_fmt_v4(struct skl_module_pin_fmt *dst_fmt,
struct skl_dfw_v4_module_fmt *src_fmt,
int pins)
{
int i;

for (i = 0; i < pins; i++) {
dst_fmt[i].fmt.channels = src_fmt[i].channels;
dst_fmt[i].fmt.s_freq = src_fmt[i].freq;
dst_fmt[i].fmt.bit_depth = src_fmt[i].bit_depth;
dst_fmt[i].fmt.valid_bit_depth = src_fmt[i].valid_bit_depth;
dst_fmt[i].fmt.ch_cfg = src_fmt[i].ch_cfg;
dst_fmt[i].fmt.ch_map = src_fmt[i].ch_map;
dst_fmt[i].fmt.interleaving_style =
src_fmt[i].interleaving_style;
dst_fmt[i].fmt.sample_type = src_fmt[i].sample_type;
}
}

static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
struct skl *skl, struct device *dev,
struct skl_module_cfg *mconfig)
{
struct skl_dfw_v4_module *dfw =
(struct skl_dfw_v4_module *)tplg_w->priv.data;
int ret;

dev_dbg(dev, "Parsing Skylake v4 widget topology data\n");

ret = guid_parse(dfw->uuid, (guid_t *)mconfig->guid);
if (ret)
return ret;
mconfig->id.module_id = -1;
mconfig->id.instance_id = dfw->instance_id;
mconfig->module->resources[0].cps = dfw->max_mcps;
mconfig->module->resources[0].ibs = dfw->ibs;
mconfig->module->resources[0].obs = dfw->obs;
mconfig->core_id = dfw->core_id;
mconfig->module->max_input_pins = dfw->max_in_queue;
mconfig->module->max_output_pins = dfw->max_out_queue;
mconfig->module->loadable = dfw->is_loadable;
skl_tplg_fill_fmt_v4(mconfig->module->formats[0].inputs, dfw->in_fmt,
MAX_IN_QUEUE);
skl_tplg_fill_fmt_v4(mconfig->module->formats[0].outputs, dfw->out_fmt,
MAX_OUT_QUEUE);

mconfig->params_fixup = dfw->params_fixup;
mconfig->converter = dfw->converter;
mconfig->m_type = dfw->module_type;
mconfig->vbus_id = dfw->vbus_id;
mconfig->module->resources[0].is_pages = dfw->mem_pages;

ret = skl_tplg_add_pipe_v4(dev, mconfig, skl, &dfw->pipe);
if (ret)
return ret;

mconfig->dev_type = dfw->dev_type;
mconfig->hw_conn_type = dfw->hw_conn_type;
mconfig->time_slot = dfw->time_slot;
mconfig->formats_config.caps_size = dfw->caps.caps_size;

mconfig->m_in_pin = devm_kzalloc(dev,
MAX_IN_QUEUE * sizeof(*mconfig->m_in_pin),
GFP_KERNEL);
if (!mconfig->m_in_pin)
return -ENOMEM;

mconfig->m_out_pin = devm_kzalloc(dev,
MAX_OUT_QUEUE * sizeof(*mconfig->m_out_pin),
GFP_KERNEL);
if (!mconfig->m_out_pin)
return -ENOMEM;

skl_fill_module_pin_info_v4(dfw->in_pin, mconfig->m_in_pin,
dfw->is_dynamic_in_pin,
mconfig->module->max_input_pins);
skl_fill_module_pin_info_v4(dfw->out_pin, mconfig->m_out_pin,
dfw->is_dynamic_out_pin,
mconfig->module->max_output_pins);

if (mconfig->formats_config.caps_size) {
mconfig->formats_config.set_params = dfw->caps.set_params;
mconfig->formats_config.param_id = dfw->caps.param_id;
mconfig->formats_config.caps =
devm_kzalloc(dev, mconfig->formats_config.caps_size,
GFP_KERNEL);
if (!mconfig->formats_config.caps)
return -ENOMEM;
memcpy(mconfig->formats_config.caps, dfw->caps.caps,
dfw->caps.caps_size);
}

return 0;
}

/*
* Parse the private data for the token and corresponding value.
* The private data can have multiple data blocks. So, a data block
Expand All @@ -2654,6 +2816,13 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
char *data;
int ret;

/*
* v4 configuration files have a valid UUID at the start of
* the widget's private data.
*/
if (uuid_is_valid((char *)tplg_w->priv.data))
return skl_tplg_get_pvt_data_v4(tplg_w, skl, dev, mconfig);

/* Read the NUM_DATA_BLOCKS descriptor */
array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data;
ret = skl_tplg_get_desc_blocks(dev, array);
Expand Down
74 changes: 74 additions & 0 deletions sound/soc/intel/skylake/skl-tplg-interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,78 @@ enum skl_tuple_type {
SKL_TYPE_DATA
};

/* v4 configuration data */

struct skl_dfw_v4_module_pin {
u16 module_id;
u16 instance_id;
} __packed;

struct skl_dfw_v4_module_fmt {
u32 channels;
u32 freq;
u32 bit_depth;
u32 valid_bit_depth;
u32 ch_cfg;
u32 interleaving_style;
u32 sample_type;
u32 ch_map;
} __packed;

struct skl_dfw_v4_module_caps {
u32 set_params:2;
u32 rsvd:30;
u32 param_id;
u32 caps_size;
u32 caps[HDA_SST_CFG_MAX];
} __packed;

struct skl_dfw_v4_pipe {
u8 pipe_id;
u8 pipe_priority;
u16 conn_type:4;
u16 rsvd:4;
u16 memory_pages:8;
} __packed;

struct skl_dfw_v4_module {
char uuid[SKL_UUID_STR_SZ];

u16 module_id;
u16 instance_id;
u32 max_mcps;
u32 mem_pages;
u32 obs;
u32 ibs;
u32 vbus_id;

u32 max_in_queue:8;
u32 max_out_queue:8;
u32 time_slot:8;
u32 core_id:4;
u32 rsvd1:4;

u32 module_type:8;
u32 conn_type:4;
u32 dev_type:4;
u32 hw_conn_type:4;
u32 rsvd2:12;

u32 params_fixup:8;
u32 converter:8;
u32 input_pin_type:1;
u32 output_pin_type:1;
u32 is_dynamic_in_pin:1;
u32 is_dynamic_out_pin:1;
u32 is_loadable:1;
u32 rsvd3:11;

struct skl_dfw_v4_pipe pipe;
struct skl_dfw_v4_module_fmt in_fmt[MAX_IN_QUEUE];
struct skl_dfw_v4_module_fmt out_fmt[MAX_OUT_QUEUE];
struct skl_dfw_v4_module_pin in_pin[MAX_IN_QUEUE];
struct skl_dfw_v4_module_pin out_pin[MAX_OUT_QUEUE];
struct skl_dfw_v4_module_caps caps;
} __packed;

#endif
7 changes: 5 additions & 2 deletions sound/soc/soc-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -2284,8 +2284,11 @@ static int manifest_new_ver(struct soc_tplg *tplg,
*manifest = NULL;

if (src->size != sizeof(*src_v4)) {
dev_err(tplg->dev, "ASoC: invalid manifest size\n");
return -EINVAL;
dev_warn(tplg->dev, "ASoC: invalid manifest size %d\n",
src->size);
if (src->size)
return -EINVAL;
src->size = sizeof(*src_v4);
}

dev_warn(tplg->dev, "ASoC: old version of manifest\n");
Expand Down