|
@@ -2201,6 +2201,197 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int skl_tplg_fill_str_mfest_tkn(struct device *dev,
|
|
|
+ struct snd_soc_tplg_vendor_string_elem *str_elem,
|
|
|
+ struct skl_dfw_manifest *minfo)
|
|
|
+{
|
|
|
+ int tkn_count = 0;
|
|
|
+ static int ref_count;
|
|
|
+
|
|
|
+ switch (str_elem->token) {
|
|
|
+ case SKL_TKN_STR_LIB_NAME:
|
|
|
+ if (ref_count > minfo->lib_count - 1) {
|
|
|
+ ref_count = 0;
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ strncpy(minfo->lib[ref_count].name, str_elem->string,
|
|
|
+ ARRAY_SIZE(minfo->lib[ref_count].name));
|
|
|
+ ref_count++;
|
|
|
+ tkn_count++;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ dev_err(dev, "Not a string token %d", str_elem->token);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return tkn_count;
|
|
|
+}
|
|
|
+
|
|
|
+static int skl_tplg_get_str_tkn(struct device *dev,
|
|
|
+ struct snd_soc_tplg_vendor_array *array,
|
|
|
+ struct skl_dfw_manifest *minfo)
|
|
|
+{
|
|
|
+ int tkn_count = 0, ret;
|
|
|
+ struct snd_soc_tplg_vendor_string_elem *str_elem;
|
|
|
+
|
|
|
+ str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value;
|
|
|
+ while (tkn_count < array->num_elems) {
|
|
|
+ ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, minfo);
|
|
|
+ str_elem++;
|
|
|
+
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ tkn_count = tkn_count + ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ return tkn_count;
|
|
|
+}
|
|
|
+
|
|
|
+static int skl_tplg_get_int_tkn(struct device *dev,
|
|
|
+ struct snd_soc_tplg_vendor_value_elem *tkn_elem,
|
|
|
+ struct skl_dfw_manifest *minfo)
|
|
|
+{
|
|
|
+ int tkn_count = 0;
|
|
|
+
|
|
|
+ switch (tkn_elem->token) {
|
|
|
+ case SKL_TKN_U32_LIB_COUNT:
|
|
|
+ minfo->lib_count = tkn_elem->value;
|
|
|
+ tkn_count++;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ dev_err(dev, "Not a manifest token %d", tkn_elem->token);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return tkn_count;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Fill the manifest structure by parsing the tokens based on the
|
|
|
+ * type.
|
|
|
+ */
|
|
|
+static int skl_tplg_get_manifest_tkn(struct device *dev,
|
|
|
+ char *pvt_data, struct skl_dfw_manifest *minfo,
|
|
|
+ int block_size)
|
|
|
+{
|
|
|
+ int tkn_count = 0, ret;
|
|
|
+ int off = 0, tuple_size = 0;
|
|
|
+ struct snd_soc_tplg_vendor_array *array;
|
|
|
+ struct snd_soc_tplg_vendor_value_elem *tkn_elem;
|
|
|
+
|
|
|
+ if (block_size <= 0)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ while (tuple_size < block_size) {
|
|
|
+ array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off);
|
|
|
+ off += array->size;
|
|
|
+ switch (array->type) {
|
|
|
+ case SND_SOC_TPLG_TUPLE_TYPE_STRING:
|
|
|
+ ret = skl_tplg_get_str_tkn(dev, array, minfo);
|
|
|
+
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+ tkn_count += ret;
|
|
|
+
|
|
|
+ tuple_size += tkn_count *
|
|
|
+ sizeof(struct snd_soc_tplg_vendor_string_elem);
|
|
|
+ continue;
|
|
|
+
|
|
|
+ case SND_SOC_TPLG_TUPLE_TYPE_UUID:
|
|
|
+ dev_warn(dev, "no uuid tokens for skl tplf manifest");
|
|
|
+ continue;
|
|
|
+
|
|
|
+ default:
|
|
|
+ tkn_elem = array->value;
|
|
|
+ tkn_count = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ while (tkn_count <= array->num_elems - 1) {
|
|
|
+ ret = skl_tplg_get_int_tkn(dev,
|
|
|
+ tkn_elem, minfo);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ tkn_count = tkn_count + ret;
|
|
|
+ tkn_elem++;
|
|
|
+ tuple_size += tkn_count *
|
|
|
+ sizeof(struct snd_soc_tplg_vendor_value_elem);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ tkn_count = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Parse manifest private data for tokens. The private data block is
|
|
|
+ * preceded by descriptors for type and size of data block.
|
|
|
+ */
|
|
|
+static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest,
|
|
|
+ struct device *dev, struct skl_dfw_manifest *minfo)
|
|
|
+{
|
|
|
+ struct snd_soc_tplg_vendor_array *array;
|
|
|
+ int num_blocks, block_size = 0, block_type, off = 0;
|
|
|
+ char *data;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /* Read the NUM_DATA_BLOCKS descriptor */
|
|
|
+ array = (struct snd_soc_tplg_vendor_array *)manifest->priv.data;
|
|
|
+ ret = skl_tplg_get_desc_blocks(dev, array);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+ num_blocks = ret;
|
|
|
+
|
|
|
+ off += array->size;
|
|
|
+ array = (struct snd_soc_tplg_vendor_array *)
|
|
|
+ (manifest->priv.data + off);
|
|
|
+
|
|
|
+ /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
|
|
|
+ while (num_blocks > 0) {
|
|
|
+ ret = skl_tplg_get_desc_blocks(dev, array);
|
|
|
+
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+ block_type = ret;
|
|
|
+ off += array->size;
|
|
|
+
|
|
|
+ array = (struct snd_soc_tplg_vendor_array *)
|
|
|
+ (manifest->priv.data + off);
|
|
|
+
|
|
|
+ ret = skl_tplg_get_desc_blocks(dev, array);
|
|
|
+
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+ block_size = ret;
|
|
|
+ off += array->size;
|
|
|
+
|
|
|
+ array = (struct snd_soc_tplg_vendor_array *)
|
|
|
+ (manifest->priv.data + off);
|
|
|
+
|
|
|
+ data = (manifest->priv.data + off);
|
|
|
+
|
|
|
+ if (block_type == SKL_TYPE_TUPLE) {
|
|
|
+ ret = skl_tplg_get_manifest_tkn(dev, data, minfo,
|
|
|
+ block_size);
|
|
|
+
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ --num_blocks;
|
|
|
+ } else {
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int skl_manifest_load(struct snd_soc_component *cmpnt,
|
|
|
struct snd_soc_tplg_manifest *manifest)
|
|
|
{
|
|
@@ -2211,7 +2402,8 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt,
|
|
|
int ret = 0;
|
|
|
|
|
|
minfo = &skl->skl_sst->manifest;
|
|
|
- memcpy(minfo, manifest->priv.data, sizeof(struct skl_dfw_manifest));
|
|
|
+
|
|
|
+ skl_tplg_get_manifest_data(manifest, bus->dev, minfo);
|
|
|
|
|
|
if (minfo->lib_count > HDA_MAX_LIB) {
|
|
|
dev_err(bus->dev, "Exceeding max Library count. Got:%d\n",
|