diff options
-rw-r--r-- | sound/soc/intel/skylake/skl-topology.c | 121 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-tplg-interface.h | 7 |
2 files changed, 123 insertions, 5 deletions
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index bfc138df56bc..622f7430e100 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c | |||
@@ -875,6 +875,60 @@ static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, | |||
875 | return 0; | 875 | return 0; |
876 | } | 876 | } |
877 | 877 | ||
878 | static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, | ||
879 | unsigned int __user *data, unsigned int size) | ||
880 | { | ||
881 | struct soc_bytes_ext *sb = | ||
882 | (struct soc_bytes_ext *)kcontrol->private_value; | ||
883 | struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; | ||
884 | |||
885 | if (bc->params) { | ||
886 | if (copy_to_user(data, &bc->param_id, sizeof(u32))) | ||
887 | return -EFAULT; | ||
888 | if (copy_to_user(data + sizeof(u32), &size, sizeof(u32))) | ||
889 | return -EFAULT; | ||
890 | if (copy_to_user(data + 2 * sizeof(u32), bc->params, size)) | ||
891 | return -EFAULT; | ||
892 | } | ||
893 | |||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | #define SKL_PARAM_VENDOR_ID 0xff | ||
898 | |||
899 | static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, | ||
900 | const unsigned int __user *data, unsigned int size) | ||
901 | { | ||
902 | struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); | ||
903 | struct skl_module_cfg *mconfig = w->priv; | ||
904 | struct soc_bytes_ext *sb = | ||
905 | (struct soc_bytes_ext *)kcontrol->private_value; | ||
906 | struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private; | ||
907 | struct skl *skl = get_skl_ctx(w->dapm->dev); | ||
908 | |||
909 | if (ac->params) { | ||
910 | /* | ||
911 | * if the param_is is of type Vendor, firmware expects actual | ||
912 | * parameter id and size from the control. | ||
913 | */ | ||
914 | if (ac->param_id == SKL_PARAM_VENDOR_ID) { | ||
915 | if (copy_from_user(ac->params, data, size)) | ||
916 | return -EFAULT; | ||
917 | } else { | ||
918 | if (copy_from_user(ac->params, | ||
919 | data + 2 * sizeof(u32), size)) | ||
920 | return -EFAULT; | ||
921 | } | ||
922 | |||
923 | if (w->power) | ||
924 | return skl_set_module_params(skl->skl_sst, | ||
925 | (u32 *)ac->params, ac->max, | ||
926 | ac->param_id, mconfig); | ||
927 | } | ||
928 | |||
929 | return 0; | ||
930 | } | ||
931 | |||
878 | /* | 932 | /* |
879 | * The FE params are passed by hw_params of the DAI. | 933 | * The FE params are passed by hw_params of the DAI. |
880 | * On hw_params, the params are stored in Gateway module of the FE and we | 934 | * On hw_params, the params are stored in Gateway module of the FE and we |
@@ -1125,6 +1179,11 @@ static const struct snd_soc_tplg_widget_events skl_tplg_widget_ops[] = { | |||
1125 | {SKL_PGA_EVENT, skl_tplg_pga_event}, | 1179 | {SKL_PGA_EVENT, skl_tplg_pga_event}, |
1126 | }; | 1180 | }; |
1127 | 1181 | ||
1182 | static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { | ||
1183 | {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get, | ||
1184 | skl_tplg_tlv_control_set}, | ||
1185 | }; | ||
1186 | |||
1128 | /* | 1187 | /* |
1129 | * The topology binary passes the pin info for a module so initialize the pin | 1188 | * The topology binary passes the pin info for a module so initialize the pin |
1130 | * info passed into module instance | 1189 | * info passed into module instance |
@@ -1321,8 +1380,70 @@ bind_event: | |||
1321 | return 0; | 1380 | return 0; |
1322 | } | 1381 | } |
1323 | 1382 | ||
1383 | static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, | ||
1384 | struct snd_soc_tplg_bytes_control *bc) | ||
1385 | { | ||
1386 | struct skl_algo_data *ac; | ||
1387 | struct skl_dfw_algo_data *dfw_ac = | ||
1388 | (struct skl_dfw_algo_data *)bc->priv.data; | ||
1389 | |||
1390 | ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL); | ||
1391 | if (!ac) | ||
1392 | return -ENOMEM; | ||
1393 | |||
1394 | /* Fill private data */ | ||
1395 | ac->max = dfw_ac->max; | ||
1396 | ac->param_id = dfw_ac->param_id; | ||
1397 | ac->set_params = dfw_ac->set_params; | ||
1398 | |||
1399 | if (ac->max) { | ||
1400 | ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL); | ||
1401 | if (!ac->params) | ||
1402 | return -ENOMEM; | ||
1403 | |||
1404 | if (dfw_ac->params) | ||
1405 | memcpy(ac->params, dfw_ac->params, ac->max); | ||
1406 | } | ||
1407 | |||
1408 | be->dobj.private = ac; | ||
1409 | return 0; | ||
1410 | } | ||
1411 | |||
1412 | static int skl_tplg_control_load(struct snd_soc_component *cmpnt, | ||
1413 | struct snd_kcontrol_new *kctl, | ||
1414 | struct snd_soc_tplg_ctl_hdr *hdr) | ||
1415 | { | ||
1416 | struct soc_bytes_ext *sb; | ||
1417 | struct snd_soc_tplg_bytes_control *tplg_bc; | ||
1418 | struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); | ||
1419 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
1420 | |||
1421 | switch (hdr->ops.info) { | ||
1422 | case SND_SOC_TPLG_CTL_BYTES: | ||
1423 | tplg_bc = container_of(hdr, | ||
1424 | struct snd_soc_tplg_bytes_control, hdr); | ||
1425 | if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { | ||
1426 | sb = (struct soc_bytes_ext *)kctl->private_value; | ||
1427 | if (tplg_bc->priv.size) | ||
1428 | return skl_init_algo_data( | ||
1429 | bus->dev, sb, tplg_bc); | ||
1430 | } | ||
1431 | break; | ||
1432 | |||
1433 | default: | ||
1434 | dev_warn(bus->dev, "Control load not supported %d:%d:%d\n", | ||
1435 | hdr->ops.get, hdr->ops.put, hdr->ops.info); | ||
1436 | break; | ||
1437 | } | ||
1438 | |||
1439 | return 0; | ||
1440 | } | ||
1441 | |||
1324 | static struct snd_soc_tplg_ops skl_tplg_ops = { | 1442 | static struct snd_soc_tplg_ops skl_tplg_ops = { |
1325 | .widget_load = skl_tplg_widget_load, | 1443 | .widget_load = skl_tplg_widget_load, |
1444 | .control_load = skl_tplg_control_load, | ||
1445 | .bytes_ext_ops = skl_tlv_ops, | ||
1446 | .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), | ||
1326 | }; | 1447 | }; |
1327 | 1448 | ||
1328 | /* This will be read from topology manifest, currently defined here */ | 1449 | /* This will be read from topology manifest, currently defined here */ |
diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index 63c83a3eeb7e..3f1908e3ae80 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h | |||
@@ -23,10 +23,7 @@ | |||
23 | * Default types range from 0~12. type can range from 0 to 0xff | 23 | * Default types range from 0~12. type can range from 0 to 0xff |
24 | * SST types start at higher to avoid any overlapping in future | 24 | * SST types start at higher to avoid any overlapping in future |
25 | */ | 25 | */ |
26 | #define SOC_CONTROL_TYPE_HDA_SST_ALGO_PARAMS 0x100 | 26 | #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 |
27 | #define SOC_CONTROL_TYPE_HDA_SST_MUX 0x101 | ||
28 | #define SOC_CONTROL_TYPE_HDA_SST_MIX 0x101 | ||
29 | #define SOC_CONTROL_TYPE_HDA_SST_BYTE 0x103 | ||
30 | 27 | ||
31 | #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ | 28 | #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ |
32 | #define MAX_IN_QUEUE 8 | 29 | #define MAX_IN_QUEUE 8 |
@@ -218,8 +215,8 @@ struct skl_dfw_module { | |||
218 | struct skl_dfw_algo_data { | 215 | struct skl_dfw_algo_data { |
219 | u32 set_params:1; | 216 | u32 set_params:1; |
220 | u32 rsvd:31; | 217 | u32 rsvd:31; |
221 | u32 param_id; | ||
222 | u32 max; | 218 | u32 max; |
219 | u32 param_id; | ||
223 | char params[0]; | 220 | char params[0]; |
224 | } __packed; | 221 | } __packed; |
225 | 222 | ||