ipc3-control.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // This file is provided under a dual BSD/GPLv2 license. When using or
  4. // redistributing this file, you may do so under either license.
  5. //
  6. // Copyright(c) 2021 Intel Corporation. All rights reserved.
  7. //
  8. //
  9. #include "sof-priv.h"
  10. #include "sof-audio.h"
  11. #include "ipc3-priv.h"
  12. /* IPC set()/get() for kcontrols. */
  13. static int sof_ipc3_set_get_kcontrol_data(struct snd_sof_control *scontrol, bool set)
  14. {
  15. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scontrol->scomp);
  16. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  17. const struct sof_ipc_ops *iops = sdev->ipc->ops;
  18. enum sof_ipc_ctrl_type ctrl_type;
  19. struct snd_sof_widget *swidget;
  20. bool widget_found = false;
  21. u32 ipc_cmd, msg_bytes;
  22. list_for_each_entry(swidget, &sdev->widget_list, list) {
  23. if (swidget->comp_id == scontrol->comp_id) {
  24. widget_found = true;
  25. break;
  26. }
  27. }
  28. if (!widget_found) {
  29. dev_err(sdev->dev, "%s: can't find widget with id %d\n", __func__,
  30. scontrol->comp_id);
  31. return -EINVAL;
  32. }
  33. /*
  34. * Volatile controls should always be part of static pipelines and the widget use_count
  35. * would always be > 0 in this case. For the others, just return the cached value if the
  36. * widget is not set up.
  37. */
  38. if (!swidget->use_count)
  39. return 0;
  40. /*
  41. * Select the IPC cmd and the ctrl_type based on the ctrl_cmd and the
  42. * direction
  43. * Note: SOF_CTRL_TYPE_VALUE_COMP_* is not used and supported currently
  44. * for ctrl_type
  45. */
  46. if (cdata->cmd == SOF_CTRL_CMD_BINARY) {
  47. ipc_cmd = set ? SOF_IPC_COMP_SET_DATA : SOF_IPC_COMP_GET_DATA;
  48. ctrl_type = set ? SOF_CTRL_TYPE_DATA_SET : SOF_CTRL_TYPE_DATA_GET;
  49. } else {
  50. ipc_cmd = set ? SOF_IPC_COMP_SET_VALUE : SOF_IPC_COMP_GET_VALUE;
  51. ctrl_type = set ? SOF_CTRL_TYPE_VALUE_CHAN_SET : SOF_CTRL_TYPE_VALUE_CHAN_GET;
  52. }
  53. cdata->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | ipc_cmd;
  54. cdata->type = ctrl_type;
  55. cdata->comp_id = scontrol->comp_id;
  56. cdata->msg_index = 0;
  57. /* calculate header and data size */
  58. switch (cdata->type) {
  59. case SOF_CTRL_TYPE_VALUE_CHAN_GET:
  60. case SOF_CTRL_TYPE_VALUE_CHAN_SET:
  61. cdata->num_elems = scontrol->num_channels;
  62. msg_bytes = scontrol->num_channels *
  63. sizeof(struct sof_ipc_ctrl_value_chan);
  64. msg_bytes += sizeof(struct sof_ipc_ctrl_data);
  65. break;
  66. case SOF_CTRL_TYPE_DATA_GET:
  67. case SOF_CTRL_TYPE_DATA_SET:
  68. cdata->num_elems = cdata->data->size;
  69. msg_bytes = cdata->data->size;
  70. msg_bytes += sizeof(struct sof_ipc_ctrl_data) +
  71. sizeof(struct sof_abi_hdr);
  72. break;
  73. default:
  74. return -EINVAL;
  75. }
  76. cdata->rhdr.hdr.size = msg_bytes;
  77. cdata->elems_remaining = 0;
  78. return iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set);
  79. }
  80. static void snd_sof_refresh_control(struct snd_sof_control *scontrol)
  81. {
  82. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  83. struct snd_soc_component *scomp = scontrol->scomp;
  84. int ret;
  85. if (!scontrol->comp_data_dirty)
  86. return;
  87. if (!pm_runtime_active(scomp->dev))
  88. return;
  89. /* set the ABI header values */
  90. cdata->data->magic = SOF_ABI_MAGIC;
  91. cdata->data->abi = SOF_ABI_VERSION;
  92. /* refresh the component data from DSP */
  93. scontrol->comp_data_dirty = false;
  94. ret = sof_ipc3_set_get_kcontrol_data(scontrol, false);
  95. if (ret < 0) {
  96. dev_err(scomp->dev, "Failed to get control data: %d\n", ret);
  97. /* Set the flag to re-try next time to get the data */
  98. scontrol->comp_data_dirty = true;
  99. }
  100. }
  101. static int sof_ipc3_volume_get(struct snd_sof_control *scontrol,
  102. struct snd_ctl_elem_value *ucontrol)
  103. {
  104. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  105. unsigned int channels = scontrol->num_channels;
  106. unsigned int i;
  107. snd_sof_refresh_control(scontrol);
  108. /* read back each channel */
  109. for (i = 0; i < channels; i++)
  110. ucontrol->value.integer.value[i] = ipc_to_mixer(cdata->chanv[i].value,
  111. scontrol->volume_table,
  112. scontrol->max + 1);
  113. return 0;
  114. }
  115. static bool sof_ipc3_volume_put(struct snd_sof_control *scontrol,
  116. struct snd_ctl_elem_value *ucontrol)
  117. {
  118. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  119. struct snd_soc_component *scomp = scontrol->scomp;
  120. unsigned int channels = scontrol->num_channels;
  121. unsigned int i;
  122. bool change = false;
  123. /* update each channel */
  124. for (i = 0; i < channels; i++) {
  125. u32 value = mixer_to_ipc(ucontrol->value.integer.value[i],
  126. scontrol->volume_table, scontrol->max + 1);
  127. change = change || (value != cdata->chanv[i].value);
  128. cdata->chanv[i].channel = i;
  129. cdata->chanv[i].value = value;
  130. }
  131. /* notify DSP of mixer updates */
  132. if (pm_runtime_active(scomp->dev)) {
  133. int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true);
  134. if (ret < 0) {
  135. dev_err(scomp->dev, "Failed to set mixer updates for %s\n",
  136. scontrol->name);
  137. return false;
  138. }
  139. }
  140. return change;
  141. }
  142. static int sof_ipc3_switch_get(struct snd_sof_control *scontrol,
  143. struct snd_ctl_elem_value *ucontrol)
  144. {
  145. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  146. unsigned int channels = scontrol->num_channels;
  147. unsigned int i;
  148. snd_sof_refresh_control(scontrol);
  149. /* read back each channel */
  150. for (i = 0; i < channels; i++)
  151. ucontrol->value.integer.value[i] = cdata->chanv[i].value;
  152. return 0;
  153. }
  154. static bool sof_ipc3_switch_put(struct snd_sof_control *scontrol,
  155. struct snd_ctl_elem_value *ucontrol)
  156. {
  157. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  158. struct snd_soc_component *scomp = scontrol->scomp;
  159. unsigned int channels = scontrol->num_channels;
  160. unsigned int i;
  161. bool change = false;
  162. u32 value;
  163. /* update each channel */
  164. for (i = 0; i < channels; i++) {
  165. value = ucontrol->value.integer.value[i];
  166. change = change || (value != cdata->chanv[i].value);
  167. cdata->chanv[i].channel = i;
  168. cdata->chanv[i].value = value;
  169. }
  170. /* notify DSP of mixer updates */
  171. if (pm_runtime_active(scomp->dev)) {
  172. int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true);
  173. if (ret < 0) {
  174. dev_err(scomp->dev, "Failed to set mixer updates for %s\n",
  175. scontrol->name);
  176. return false;
  177. }
  178. }
  179. return change;
  180. }
  181. static int sof_ipc3_enum_get(struct snd_sof_control *scontrol,
  182. struct snd_ctl_elem_value *ucontrol)
  183. {
  184. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  185. unsigned int channels = scontrol->num_channels;
  186. unsigned int i;
  187. snd_sof_refresh_control(scontrol);
  188. /* read back each channel */
  189. for (i = 0; i < channels; i++)
  190. ucontrol->value.enumerated.item[i] = cdata->chanv[i].value;
  191. return 0;
  192. }
  193. static bool sof_ipc3_enum_put(struct snd_sof_control *scontrol,
  194. struct snd_ctl_elem_value *ucontrol)
  195. {
  196. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  197. struct snd_soc_component *scomp = scontrol->scomp;
  198. unsigned int channels = scontrol->num_channels;
  199. unsigned int i;
  200. bool change = false;
  201. u32 value;
  202. /* update each channel */
  203. for (i = 0; i < channels; i++) {
  204. value = ucontrol->value.enumerated.item[i];
  205. change = change || (value != cdata->chanv[i].value);
  206. cdata->chanv[i].channel = i;
  207. cdata->chanv[i].value = value;
  208. }
  209. /* notify DSP of enum updates */
  210. if (pm_runtime_active(scomp->dev)) {
  211. int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true);
  212. if (ret < 0) {
  213. dev_err(scomp->dev, "Failed to set enum updates for %s\n",
  214. scontrol->name);
  215. return false;
  216. }
  217. }
  218. return change;
  219. }
  220. static int sof_ipc3_bytes_get(struct snd_sof_control *scontrol,
  221. struct snd_ctl_elem_value *ucontrol)
  222. {
  223. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  224. struct snd_soc_component *scomp = scontrol->scomp;
  225. struct sof_abi_hdr *data = cdata->data;
  226. size_t size;
  227. snd_sof_refresh_control(scontrol);
  228. if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) {
  229. dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n",
  230. scontrol->max_size);
  231. return -EINVAL;
  232. }
  233. /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
  234. if (data->size > scontrol->max_size - sizeof(*data)) {
  235. dev_err_ratelimited(scomp->dev,
  236. "%u bytes of control data is invalid, max is %zu\n",
  237. data->size, scontrol->max_size - sizeof(*data));
  238. return -EINVAL;
  239. }
  240. size = data->size + sizeof(*data);
  241. /* copy back to kcontrol */
  242. memcpy(ucontrol->value.bytes.data, data, size);
  243. return 0;
  244. }
  245. static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol,
  246. struct snd_ctl_elem_value *ucontrol)
  247. {
  248. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  249. struct snd_soc_component *scomp = scontrol->scomp;
  250. struct sof_abi_hdr *data = cdata->data;
  251. size_t size;
  252. if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) {
  253. dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n",
  254. scontrol->max_size);
  255. return -EINVAL;
  256. }
  257. /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */
  258. if (data->size > scontrol->max_size - sizeof(*data)) {
  259. dev_err_ratelimited(scomp->dev, "data size too big %u bytes max is %zu\n",
  260. data->size, scontrol->max_size - sizeof(*data));
  261. return -EINVAL;
  262. }
  263. size = data->size + sizeof(*data);
  264. /* copy from kcontrol */
  265. memcpy(data, ucontrol->value.bytes.data, size);
  266. /* notify DSP of byte control updates */
  267. if (pm_runtime_active(scomp->dev))
  268. return sof_ipc3_set_get_kcontrol_data(scontrol, true);
  269. return 0;
  270. }
  271. static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol,
  272. const unsigned int __user *binary_data, unsigned int size)
  273. {
  274. struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data;
  275. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  276. struct snd_soc_component *scomp = scontrol->scomp;
  277. struct snd_ctl_tlv header;
  278. size_t data_size;
  279. snd_sof_refresh_control(scontrol);
  280. /*
  281. * Decrement the limit by ext bytes header size to
  282. * ensure the user space buffer is not exceeded.
  283. */
  284. if (size < sizeof(struct snd_ctl_tlv))
  285. return -ENOSPC;
  286. size -= sizeof(struct snd_ctl_tlv);
  287. /* set the ABI header values */
  288. cdata->data->magic = SOF_ABI_MAGIC;
  289. cdata->data->abi = SOF_ABI_VERSION;
  290. /* check data size doesn't exceed max coming from topology */
  291. if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) {
  292. dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n",
  293. cdata->data->size,
  294. scontrol->max_size - sizeof(struct sof_abi_hdr));
  295. return -EINVAL;
  296. }
  297. data_size = cdata->data->size + sizeof(struct sof_abi_hdr);
  298. /* make sure we don't exceed size provided by user space for data */
  299. if (data_size > size)
  300. return -ENOSPC;
  301. header.numid = cdata->cmd;
  302. header.length = data_size;
  303. if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv)))
  304. return -EFAULT;
  305. if (copy_to_user(tlvd->tlv, cdata->data, data_size))
  306. return -EFAULT;
  307. return 0;
  308. }
  309. static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol,
  310. const unsigned int __user *binary_data,
  311. unsigned int size)
  312. {
  313. const struct snd_ctl_tlv __user *tlvd = (const struct snd_ctl_tlv __user *)binary_data;
  314. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  315. struct snd_soc_component *scomp = scontrol->scomp;
  316. struct snd_ctl_tlv header;
  317. /*
  318. * The beginning of bytes data contains a header from where
  319. * the length (as bytes) is needed to know the correct copy
  320. * length of data from tlvd->tlv.
  321. */
  322. if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv)))
  323. return -EFAULT;
  324. /* make sure TLV info is consistent */
  325. if (header.length + sizeof(struct snd_ctl_tlv) > size) {
  326. dev_err_ratelimited(scomp->dev, "Inconsistent TLV, data %d + header %zu > %d\n",
  327. header.length, sizeof(struct snd_ctl_tlv), size);
  328. return -EINVAL;
  329. }
  330. /* be->max is coming from topology */
  331. if (header.length > scontrol->max_size) {
  332. dev_err_ratelimited(scomp->dev, "Bytes data size %d exceeds max %zu\n",
  333. header.length, scontrol->max_size);
  334. return -EINVAL;
  335. }
  336. /* Check that header id matches the command */
  337. if (header.numid != cdata->cmd) {
  338. dev_err_ratelimited(scomp->dev, "Incorrect command for bytes put %d\n",
  339. header.numid);
  340. return -EINVAL;
  341. }
  342. if (copy_from_user(cdata->data, tlvd->tlv, header.length))
  343. return -EFAULT;
  344. if (cdata->data->magic != SOF_ABI_MAGIC) {
  345. dev_err_ratelimited(scomp->dev, "Wrong ABI magic 0x%08x\n", cdata->data->magic);
  346. return -EINVAL;
  347. }
  348. if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
  349. dev_err_ratelimited(scomp->dev, "Incompatible ABI version 0x%08x\n",
  350. cdata->data->abi);
  351. return -EINVAL;
  352. }
  353. /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
  354. if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) {
  355. dev_err_ratelimited(scomp->dev, "Mismatch in ABI data size (truncated?)\n");
  356. return -EINVAL;
  357. }
  358. /* notify DSP of byte control updates */
  359. if (pm_runtime_active(scomp->dev))
  360. return sof_ipc3_set_get_kcontrol_data(scontrol, true);
  361. return 0;
  362. }
  363. static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol,
  364. const unsigned int __user *binary_data,
  365. unsigned int size)
  366. {
  367. struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data;
  368. struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
  369. struct snd_soc_component *scomp = scontrol->scomp;
  370. struct snd_ctl_tlv header;
  371. size_t data_size;
  372. int ret;
  373. /*
  374. * Decrement the limit by ext bytes header size to
  375. * ensure the user space buffer is not exceeded.
  376. */
  377. if (size < sizeof(struct snd_ctl_tlv))
  378. return -ENOSPC;
  379. size -= sizeof(struct snd_ctl_tlv);
  380. /* set the ABI header values */
  381. cdata->data->magic = SOF_ABI_MAGIC;
  382. cdata->data->abi = SOF_ABI_VERSION;
  383. /* get all the component data from DSP */
  384. ret = sof_ipc3_set_get_kcontrol_data(scontrol, false);
  385. if (ret < 0)
  386. return ret;
  387. /* check data size doesn't exceed max coming from topology */
  388. if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) {
  389. dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n",
  390. cdata->data->size,
  391. scontrol->max_size - sizeof(struct sof_abi_hdr));
  392. return -EINVAL;
  393. }
  394. data_size = cdata->data->size + sizeof(struct sof_abi_hdr);
  395. /* make sure we don't exceed size provided by user space for data */
  396. if (data_size > size)
  397. return -ENOSPC;
  398. header.numid = cdata->cmd;
  399. header.length = data_size;
  400. if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv)))
  401. return -EFAULT;
  402. if (copy_to_user(tlvd->tlv, cdata->data, data_size))
  403. return -EFAULT;
  404. return ret;
  405. }
  406. static void snd_sof_update_control(struct snd_sof_control *scontrol,
  407. struct sof_ipc_ctrl_data *cdata)
  408. {
  409. struct snd_soc_component *scomp = scontrol->scomp;
  410. struct sof_ipc_ctrl_data *local_cdata;
  411. int i;
  412. local_cdata = scontrol->ipc_control_data;
  413. if (cdata->cmd == SOF_CTRL_CMD_BINARY) {
  414. if (cdata->num_elems != local_cdata->data->size) {
  415. dev_err(scomp->dev, "cdata binary size mismatch %u - %u\n",
  416. cdata->num_elems, local_cdata->data->size);
  417. return;
  418. }
  419. /* copy the new binary data */
  420. memcpy(local_cdata->data, cdata->data, cdata->num_elems);
  421. } else if (cdata->num_elems != scontrol->num_channels) {
  422. dev_err(scomp->dev, "cdata channel count mismatch %u - %d\n",
  423. cdata->num_elems, scontrol->num_channels);
  424. } else {
  425. /* copy the new values */
  426. for (i = 0; i < cdata->num_elems; i++)
  427. local_cdata->chanv[i].value = cdata->chanv[i].value;
  428. }
  429. }
  430. static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_message)
  431. {
  432. struct sof_ipc_ctrl_data *cdata = ipc_control_message;
  433. struct snd_soc_dapm_widget *widget;
  434. struct snd_sof_control *scontrol;
  435. struct snd_sof_widget *swidget;
  436. struct snd_kcontrol *kc = NULL;
  437. struct soc_mixer_control *sm;
  438. struct soc_bytes_ext *be;
  439. size_t expected_size;
  440. struct soc_enum *se;
  441. bool found = false;
  442. int i, type;
  443. if (cdata->type == SOF_CTRL_TYPE_VALUE_COMP_GET ||
  444. cdata->type == SOF_CTRL_TYPE_VALUE_COMP_SET) {
  445. dev_err(sdev->dev, "Component data is not supported in control notification\n");
  446. return;
  447. }
  448. /* Find the swidget first */
  449. list_for_each_entry(swidget, &sdev->widget_list, list) {
  450. if (swidget->comp_id == cdata->comp_id) {
  451. found = true;
  452. break;
  453. }
  454. }
  455. if (!found)
  456. return;
  457. /* Translate SOF cmd to TPLG type */
  458. switch (cdata->cmd) {
  459. case SOF_CTRL_CMD_VOLUME:
  460. case SOF_CTRL_CMD_SWITCH:
  461. type = SND_SOC_TPLG_TYPE_MIXER;
  462. break;
  463. case SOF_CTRL_CMD_BINARY:
  464. type = SND_SOC_TPLG_TYPE_BYTES;
  465. break;
  466. case SOF_CTRL_CMD_ENUM:
  467. type = SND_SOC_TPLG_TYPE_ENUM;
  468. break;
  469. default:
  470. dev_err(sdev->dev, "Unknown cmd %u in %s\n", cdata->cmd, __func__);
  471. return;
  472. }
  473. widget = swidget->widget;
  474. for (i = 0; i < widget->num_kcontrols; i++) {
  475. /* skip non matching types or non matching indexes within type */
  476. if (widget->dobj.widget.kcontrol_type[i] == type &&
  477. widget->kcontrol_news[i].index == cdata->index) {
  478. kc = widget->kcontrols[i];
  479. break;
  480. }
  481. }
  482. if (!kc)
  483. return;
  484. switch (cdata->cmd) {
  485. case SOF_CTRL_CMD_VOLUME:
  486. case SOF_CTRL_CMD_SWITCH:
  487. sm = (struct soc_mixer_control *)kc->private_value;
  488. scontrol = sm->dobj.private;
  489. break;
  490. case SOF_CTRL_CMD_BINARY:
  491. be = (struct soc_bytes_ext *)kc->private_value;
  492. scontrol = be->dobj.private;
  493. break;
  494. case SOF_CTRL_CMD_ENUM:
  495. se = (struct soc_enum *)kc->private_value;
  496. scontrol = se->dobj.private;
  497. break;
  498. default:
  499. return;
  500. }
  501. expected_size = sizeof(struct sof_ipc_ctrl_data);
  502. switch (cdata->type) {
  503. case SOF_CTRL_TYPE_VALUE_CHAN_GET:
  504. case SOF_CTRL_TYPE_VALUE_CHAN_SET:
  505. expected_size += cdata->num_elems *
  506. sizeof(struct sof_ipc_ctrl_value_chan);
  507. break;
  508. case SOF_CTRL_TYPE_DATA_GET:
  509. case SOF_CTRL_TYPE_DATA_SET:
  510. expected_size += cdata->num_elems + sizeof(struct sof_abi_hdr);
  511. break;
  512. default:
  513. return;
  514. }
  515. if (cdata->rhdr.hdr.size != expected_size) {
  516. dev_err(sdev->dev, "Component notification size mismatch\n");
  517. return;
  518. }
  519. if (cdata->num_elems)
  520. /*
  521. * The message includes the updated value/data, update the
  522. * control's local cache using the received notification
  523. */
  524. snd_sof_update_control(scontrol, cdata);
  525. else
  526. /* Mark the scontrol that the value/data is changed in SOF */
  527. scontrol->comp_data_dirty = true;
  528. snd_ctl_notify_one(swidget->scomp->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, kc, 0);
  529. }
  530. static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev,
  531. struct snd_sof_widget *swidget)
  532. {
  533. struct snd_sof_control *scontrol;
  534. int ret;
  535. /* set up all controls for the widget */
  536. list_for_each_entry(scontrol, &sdev->kcontrol_list, list)
  537. if (scontrol->comp_id == swidget->comp_id) {
  538. /* set kcontrol data in DSP */
  539. ret = sof_ipc3_set_get_kcontrol_data(scontrol, true);
  540. if (ret < 0) {
  541. dev_err(sdev->dev,
  542. "kcontrol %d set up failed for widget %s\n",
  543. scontrol->comp_id, swidget->widget->name);
  544. return ret;
  545. }
  546. /*
  547. * Read back the data from the DSP for static widgets.
  548. * This is particularly useful for binary kcontrols
  549. * associated with static pipeline widgets to initialize
  550. * the data size to match that in the DSP.
  551. */
  552. if (swidget->dynamic_pipeline_widget)
  553. continue;
  554. ret = sof_ipc3_set_get_kcontrol_data(scontrol, false);
  555. if (ret < 0)
  556. dev_warn(sdev->dev,
  557. "kcontrol %d read failed for widget %s\n",
  558. scontrol->comp_id, swidget->widget->name);
  559. }
  560. return 0;
  561. }
  562. static int
  563. sof_ipc3_set_up_volume_table(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS], int size)
  564. {
  565. int i;
  566. /* init the volume table */
  567. scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL);
  568. if (!scontrol->volume_table)
  569. return -ENOMEM;
  570. /* populate the volume table */
  571. for (i = 0; i < size ; i++)
  572. scontrol->volume_table[i] = vol_compute_gain(i, tlv);
  573. return 0;
  574. }
  575. const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = {
  576. .volume_put = sof_ipc3_volume_put,
  577. .volume_get = sof_ipc3_volume_get,
  578. .switch_put = sof_ipc3_switch_put,
  579. .switch_get = sof_ipc3_switch_get,
  580. .enum_put = sof_ipc3_enum_put,
  581. .enum_get = sof_ipc3_enum_get,
  582. .bytes_put = sof_ipc3_bytes_put,
  583. .bytes_get = sof_ipc3_bytes_get,
  584. .bytes_ext_put = sof_ipc3_bytes_ext_put,
  585. .bytes_ext_get = sof_ipc3_bytes_ext_get,
  586. .bytes_ext_volatile_get = sof_ipc3_bytes_ext_volatile_get,
  587. .update = sof_ipc3_control_update,
  588. .widget_kcontrol_setup = sof_ipc3_widget_kcontrol_setup,
  589. .set_up_volume_table = sof_ipc3_set_up_volume_table,
  590. };