aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/intel/skylake/skl-topology.c169
-rw-r--r--sound/soc/intel/skylake/skl-tplg-interface.h74
-rw-r--r--sound/soc/soc-topology.c7
3 files changed, 248 insertions, 2 deletions
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index 3b1dca419883..9e4c2cb88dea 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -19,6 +19,7 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/types.h> 20#include <linux/types.h>
21#include <linux/firmware.h> 21#include <linux/firmware.h>
22#include <linux/uuid.h>
22#include <sound/soc.h> 23#include <sound/soc.h>
23#include <sound/soc-topology.h> 24#include <sound/soc-topology.h>
24#include <uapi/sound/snd_sst_tokens.h> 25#include <uapi/sound/snd_sst_tokens.h>
@@ -2724,6 +2725,167 @@ static int skl_tplg_get_desc_blocks(struct device *dev,
2724 return -EINVAL; 2725 return -EINVAL;
2725} 2726}
2726 2727
2728/* Functions to parse private data from configuration file format v4 */
2729
2730/*
2731 * Add pipeline from topology binary into driver pipeline list
2732 *
2733 * If already added we return that instance
2734 * Otherwise we create a new instance and add into driver list
2735 */
2736static int skl_tplg_add_pipe_v4(struct device *dev,
2737 struct skl_module_cfg *mconfig, struct skl *skl,
2738 struct skl_dfw_v4_pipe *dfw_pipe)
2739{
2740 struct skl_pipeline *ppl;
2741 struct skl_pipe *pipe;
2742 struct skl_pipe_params *params;
2743
2744 list_for_each_entry(ppl, &skl->ppl_list, node) {
2745 if (ppl->pipe->ppl_id == dfw_pipe->pipe_id) {
2746 mconfig->pipe = ppl->pipe;
2747 return 0;
2748 }
2749 }
2750
2751 ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL);
2752 if (!ppl)
2753 return -ENOMEM;
2754
2755 pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL);
2756 if (!pipe)
2757 return -ENOMEM;
2758
2759 params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL);
2760 if (!params)
2761 return -ENOMEM;
2762
2763 pipe->ppl_id = dfw_pipe->pipe_id;
2764 pipe->memory_pages = dfw_pipe->memory_pages;
2765 pipe->pipe_priority = dfw_pipe->pipe_priority;
2766 pipe->conn_type = dfw_pipe->conn_type;
2767 pipe->state = SKL_PIPE_INVALID;
2768 pipe->p_params = params;
2769 INIT_LIST_HEAD(&pipe->w_list);
2770
2771 ppl->pipe = pipe;
2772 list_add(&ppl->node, &skl->ppl_list);
2773
2774 mconfig->pipe = pipe;
2775
2776 return 0;
2777}
2778
2779static void skl_fill_module_pin_info_v4(struct skl_dfw_v4_module_pin *dfw_pin,
2780 struct skl_module_pin *m_pin,
2781 bool is_dynamic, int max_pin)
2782{
2783 int i;
2784
2785 for (i = 0; i < max_pin; i++) {
2786 m_pin[i].id.module_id = dfw_pin[i].module_id;
2787 m_pin[i].id.instance_id = dfw_pin[i].instance_id;
2788 m_pin[i].in_use = false;
2789 m_pin[i].is_dynamic = is_dynamic;
2790 m_pin[i].pin_state = SKL_PIN_UNBIND;
2791 }
2792}
2793
2794static void skl_tplg_fill_fmt_v4(struct skl_module_pin_fmt *dst_fmt,
2795 struct skl_dfw_v4_module_fmt *src_fmt,
2796 int pins)
2797{
2798 int i;
2799
2800 for (i = 0; i < pins; i++) {
2801 dst_fmt[i].fmt.channels = src_fmt[i].channels;
2802 dst_fmt[i].fmt.s_freq = src_fmt[i].freq;
2803 dst_fmt[i].fmt.bit_depth = src_fmt[i].bit_depth;
2804 dst_fmt[i].fmt.valid_bit_depth = src_fmt[i].valid_bit_depth;
2805 dst_fmt[i].fmt.ch_cfg = src_fmt[i].ch_cfg;
2806 dst_fmt[i].fmt.ch_map = src_fmt[i].ch_map;
2807 dst_fmt[i].fmt.interleaving_style =
2808 src_fmt[i].interleaving_style;
2809 dst_fmt[i].fmt.sample_type = src_fmt[i].sample_type;
2810 }
2811}
2812
2813static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
2814 struct skl *skl, struct device *dev,
2815 struct skl_module_cfg *mconfig)
2816{
2817 struct skl_dfw_v4_module *dfw =
2818 (struct skl_dfw_v4_module *)tplg_w->priv.data;
2819 int ret;
2820
2821 dev_dbg(dev, "Parsing Skylake v4 widget topology data\n");
2822
2823 ret = guid_parse(dfw->uuid, (guid_t *)mconfig->guid);
2824 if (ret)
2825 return ret;
2826 mconfig->id.module_id = -1;
2827 mconfig->id.instance_id = dfw->instance_id;
2828 mconfig->module->resources[0].cps = dfw->max_mcps;
2829 mconfig->module->resources[0].ibs = dfw->ibs;
2830 mconfig->module->resources[0].obs = dfw->obs;
2831 mconfig->core_id = dfw->core_id;
2832 mconfig->module->max_input_pins = dfw->max_in_queue;
2833 mconfig->module->max_output_pins = dfw->max_out_queue;
2834 mconfig->module->loadable = dfw->is_loadable;
2835 skl_tplg_fill_fmt_v4(mconfig->module->formats[0].inputs, dfw->in_fmt,
2836 MAX_IN_QUEUE);
2837 skl_tplg_fill_fmt_v4(mconfig->module->formats[0].outputs, dfw->out_fmt,
2838 MAX_OUT_QUEUE);
2839
2840 mconfig->params_fixup = dfw->params_fixup;
2841 mconfig->converter = dfw->converter;
2842 mconfig->m_type = dfw->module_type;
2843 mconfig->vbus_id = dfw->vbus_id;
2844 mconfig->module->resources[0].is_pages = dfw->mem_pages;
2845
2846 ret = skl_tplg_add_pipe_v4(dev, mconfig, skl, &dfw->pipe);
2847 if (ret)
2848 return ret;
2849
2850 mconfig->dev_type = dfw->dev_type;
2851 mconfig->hw_conn_type = dfw->hw_conn_type;
2852 mconfig->time_slot = dfw->time_slot;
2853 mconfig->formats_config.caps_size = dfw->caps.caps_size;
2854
2855 mconfig->m_in_pin = devm_kzalloc(dev,
2856 MAX_IN_QUEUE * sizeof(*mconfig->m_in_pin),
2857 GFP_KERNEL);
2858 if (!mconfig->m_in_pin)
2859 return -ENOMEM;
2860
2861 mconfig->m_out_pin = devm_kzalloc(dev,
2862 MAX_OUT_QUEUE * sizeof(*mconfig->m_out_pin),
2863 GFP_KERNEL);
2864 if (!mconfig->m_out_pin)
2865 return -ENOMEM;
2866
2867 skl_fill_module_pin_info_v4(dfw->in_pin, mconfig->m_in_pin,
2868 dfw->is_dynamic_in_pin,
2869 mconfig->module->max_input_pins);
2870 skl_fill_module_pin_info_v4(dfw->out_pin, mconfig->m_out_pin,
2871 dfw->is_dynamic_out_pin,
2872 mconfig->module->max_output_pins);
2873
2874 if (mconfig->formats_config.caps_size) {
2875 mconfig->formats_config.set_params = dfw->caps.set_params;
2876 mconfig->formats_config.param_id = dfw->caps.param_id;
2877 mconfig->formats_config.caps =
2878 devm_kzalloc(dev, mconfig->formats_config.caps_size,
2879 GFP_KERNEL);
2880 if (!mconfig->formats_config.caps)
2881 return -ENOMEM;
2882 memcpy(mconfig->formats_config.caps, dfw->caps.caps,
2883 dfw->caps.caps_size);
2884 }
2885
2886 return 0;
2887}
2888
2727/* 2889/*
2728 * Parse the private data for the token and corresponding value. 2890 * Parse the private data for the token and corresponding value.
2729 * The private data can have multiple data blocks. So, a data block 2891 * The private data can have multiple data blocks. So, a data block
@@ -2739,6 +2901,13 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
2739 char *data; 2901 char *data;
2740 int ret; 2902 int ret;
2741 2903
2904 /*
2905 * v4 configuration files have a valid UUID at the start of
2906 * the widget's private data.
2907 */
2908 if (uuid_is_valid((char *)tplg_w->priv.data))
2909 return skl_tplg_get_pvt_data_v4(tplg_w, skl, dev, mconfig);
2910
2742 /* Read the NUM_DATA_BLOCKS descriptor */ 2911 /* Read the NUM_DATA_BLOCKS descriptor */
2743 array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data; 2912 array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data;
2744 ret = skl_tplg_get_desc_blocks(dev, array); 2913 ret = skl_tplg_get_desc_blocks(dev, array);
diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h
index f8d1749a2e0c..b0e3d376594c 100644
--- a/sound/soc/intel/skylake/skl-tplg-interface.h
+++ b/sound/soc/intel/skylake/skl-tplg-interface.h
@@ -169,4 +169,78 @@ enum skl_tuple_type {
169 SKL_TYPE_DATA 169 SKL_TYPE_DATA
170}; 170};
171 171
172/* v4 configuration data */
173
174struct skl_dfw_v4_module_pin {
175 u16 module_id;
176 u16 instance_id;
177} __packed;
178
179struct skl_dfw_v4_module_fmt {
180 u32 channels;
181 u32 freq;
182 u32 bit_depth;
183 u32 valid_bit_depth;
184 u32 ch_cfg;
185 u32 interleaving_style;
186 u32 sample_type;
187 u32 ch_map;
188} __packed;
189
190struct skl_dfw_v4_module_caps {
191 u32 set_params:2;
192 u32 rsvd:30;
193 u32 param_id;
194 u32 caps_size;
195 u32 caps[HDA_SST_CFG_MAX];
196} __packed;
197
198struct skl_dfw_v4_pipe {
199 u8 pipe_id;
200 u8 pipe_priority;
201 u16 conn_type:4;
202 u16 rsvd:4;
203 u16 memory_pages:8;
204} __packed;
205
206struct skl_dfw_v4_module {
207 char uuid[SKL_UUID_STR_SZ];
208
209 u16 module_id;
210 u16 instance_id;
211 u32 max_mcps;
212 u32 mem_pages;
213 u32 obs;
214 u32 ibs;
215 u32 vbus_id;
216
217 u32 max_in_queue:8;
218 u32 max_out_queue:8;
219 u32 time_slot:8;
220 u32 core_id:4;
221 u32 rsvd1:4;
222
223 u32 module_type:8;
224 u32 conn_type:4;
225 u32 dev_type:4;
226 u32 hw_conn_type:4;
227 u32 rsvd2:12;
228
229 u32 params_fixup:8;
230 u32 converter:8;
231 u32 input_pin_type:1;
232 u32 output_pin_type:1;
233 u32 is_dynamic_in_pin:1;
234 u32 is_dynamic_out_pin:1;
235 u32 is_loadable:1;
236 u32 rsvd3:11;
237
238 struct skl_dfw_v4_pipe pipe;
239 struct skl_dfw_v4_module_fmt in_fmt[MAX_IN_QUEUE];
240 struct skl_dfw_v4_module_fmt out_fmt[MAX_OUT_QUEUE];
241 struct skl_dfw_v4_module_pin in_pin[MAX_IN_QUEUE];
242 struct skl_dfw_v4_module_pin out_pin[MAX_OUT_QUEUE];
243 struct skl_dfw_v4_module_caps caps;
244} __packed;
245
172#endif 246#endif
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index f25ea9aab235..3d04fa297677 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -2313,8 +2313,11 @@ static int manifest_new_ver(struct soc_tplg *tplg,
2313 *manifest = NULL; 2313 *manifest = NULL;
2314 2314
2315 if (src->size != sizeof(*src_v4)) { 2315 if (src->size != sizeof(*src_v4)) {
2316 dev_err(tplg->dev, "ASoC: invalid manifest size\n"); 2316 dev_warn(tplg->dev, "ASoC: invalid manifest size %d\n",
2317 return -EINVAL; 2317 src->size);
2318 if (src->size)
2319 return -EINVAL;
2320 src->size = sizeof(*src_v4);
2318 } 2321 }
2319 2322
2320 dev_warn(tplg->dev, "ASoC: old version of manifest\n"); 2323 dev_warn(tplg->dev, "ASoC: old version of manifest\n");