sdw-mockup.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // sdw-mockup.c -- a mockup SoundWire codec for tests where only the host
  4. // drives the bus.
  5. //
  6. // Copyright(c) 2021 Intel Corporation
  7. //
  8. //
  9. #include <linux/device.h>
  10. #include <linux/mod_devicetable.h>
  11. #include <linux/module.h>
  12. #include <linux/soundwire/sdw.h>
  13. #include <linux/soundwire/sdw_type.h>
  14. #include <linux/soundwire/sdw_registers.h>
  15. #include <sound/core.h>
  16. #include <sound/pcm.h>
  17. #include <sound/pcm_params.h>
  18. #include <sound/soc.h>
  19. struct sdw_mockup_priv {
  20. struct sdw_slave *slave;
  21. };
  22. struct sdw_stream_data {
  23. struct sdw_stream_runtime *sdw_stream;
  24. };
  25. static int sdw_mockup_component_probe(struct snd_soc_component *component)
  26. {
  27. return 0;
  28. }
  29. static void sdw_mockup_component_remove(struct snd_soc_component *component)
  30. {
  31. }
  32. static const struct snd_soc_component_driver snd_soc_sdw_mockup_component = {
  33. .probe = sdw_mockup_component_probe,
  34. .remove = sdw_mockup_component_remove,
  35. .endianness = 1,
  36. };
  37. static int sdw_mockup_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
  38. int direction)
  39. {
  40. struct sdw_stream_data *stream;
  41. if (!sdw_stream)
  42. return 0;
  43. stream = kzalloc(sizeof(*stream), GFP_KERNEL);
  44. if (!stream)
  45. return -ENOMEM;
  46. stream->sdw_stream = sdw_stream;
  47. /* Use tx_mask or rx_mask to configure stream tag and set dma_data */
  48. if (direction == SNDRV_PCM_STREAM_PLAYBACK)
  49. dai->playback_dma_data = stream;
  50. else
  51. dai->capture_dma_data = stream;
  52. return 0;
  53. }
  54. static void sdw_mockup_shutdown(struct snd_pcm_substream *substream,
  55. struct snd_soc_dai *dai)
  56. {
  57. struct sdw_stream_data *stream;
  58. stream = snd_soc_dai_get_dma_data(dai, substream);
  59. snd_soc_dai_set_dma_data(dai, substream, NULL);
  60. kfree(stream);
  61. }
  62. static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream,
  63. struct snd_pcm_hw_params *params,
  64. struct snd_soc_dai *dai)
  65. {
  66. struct snd_soc_component *component = dai->component;
  67. struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component);
  68. struct sdw_stream_config stream_config;
  69. struct sdw_port_config port_config;
  70. enum sdw_data_direction direction;
  71. struct sdw_stream_data *stream;
  72. int num_channels;
  73. int port;
  74. int ret;
  75. stream = snd_soc_dai_get_dma_data(dai, substream);
  76. if (!stream)
  77. return -EINVAL;
  78. if (!sdw_mockup->slave)
  79. return -EINVAL;
  80. /* SoundWire specific configuration */
  81. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  82. direction = SDW_DATA_DIR_RX;
  83. port = 1;
  84. } else {
  85. direction = SDW_DATA_DIR_TX;
  86. port = 8;
  87. }
  88. stream_config.frame_rate = params_rate(params);
  89. stream_config.ch_count = params_channels(params);
  90. stream_config.bps = snd_pcm_format_width(params_format(params));
  91. stream_config.direction = direction;
  92. num_channels = params_channels(params);
  93. port_config.ch_mask = (1 << num_channels) - 1;
  94. port_config.num = port;
  95. ret = sdw_stream_add_slave(sdw_mockup->slave, &stream_config,
  96. &port_config, 1, stream->sdw_stream);
  97. if (ret)
  98. dev_err(dai->dev, "Unable to configure port\n");
  99. return ret;
  100. }
  101. static int sdw_mockup_pcm_hw_free(struct snd_pcm_substream *substream,
  102. struct snd_soc_dai *dai)
  103. {
  104. struct snd_soc_component *component = dai->component;
  105. struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component);
  106. struct sdw_stream_data *stream =
  107. snd_soc_dai_get_dma_data(dai, substream);
  108. if (!sdw_mockup->slave)
  109. return -EINVAL;
  110. sdw_stream_remove_slave(sdw_mockup->slave, stream->sdw_stream);
  111. return 0;
  112. }
  113. static const struct snd_soc_dai_ops sdw_mockup_ops = {
  114. .hw_params = sdw_mockup_pcm_hw_params,
  115. .hw_free = sdw_mockup_pcm_hw_free,
  116. .set_stream = sdw_mockup_set_sdw_stream,
  117. .shutdown = sdw_mockup_shutdown,
  118. };
  119. static struct snd_soc_dai_driver sdw_mockup_dai[] = {
  120. {
  121. .name = "sdw-mockup-aif1",
  122. .id = 1,
  123. .playback = {
  124. .stream_name = "DP1 Playback",
  125. .channels_min = 1,
  126. .channels_max = 2,
  127. },
  128. .capture = {
  129. .stream_name = "DP8 Capture",
  130. .channels_min = 1,
  131. .channels_max = 2,
  132. },
  133. .ops = &sdw_mockup_ops,
  134. },
  135. };
  136. static int sdw_mockup_update_status(struct sdw_slave *slave,
  137. enum sdw_slave_status status)
  138. {
  139. return 0;
  140. }
  141. static int sdw_mockup_read_prop(struct sdw_slave *slave)
  142. {
  143. struct sdw_slave_prop *prop = &slave->prop;
  144. int nval;
  145. int i, j;
  146. u32 bit;
  147. unsigned long addr;
  148. struct sdw_dpn_prop *dpn;
  149. prop->paging_support = false;
  150. /*
  151. * first we need to allocate memory for set bits in port lists
  152. * the port allocation is completely arbitrary:
  153. * DP0 is not supported
  154. * DP1 is sink
  155. * DP8 is source
  156. */
  157. prop->source_ports = BIT(8);
  158. prop->sink_ports = BIT(1);
  159. nval = hweight32(prop->source_ports);
  160. prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
  161. sizeof(*prop->src_dpn_prop),
  162. GFP_KERNEL);
  163. if (!prop->src_dpn_prop)
  164. return -ENOMEM;
  165. i = 0;
  166. dpn = prop->src_dpn_prop;
  167. addr = prop->source_ports;
  168. for_each_set_bit(bit, &addr, 32) {
  169. dpn[i].num = bit;
  170. dpn[i].type = SDW_DPN_FULL;
  171. dpn[i].simple_ch_prep_sm = true;
  172. i++;
  173. }
  174. /* do this again for sink now */
  175. nval = hweight32(prop->sink_ports);
  176. prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
  177. sizeof(*prop->sink_dpn_prop),
  178. GFP_KERNEL);
  179. if (!prop->sink_dpn_prop)
  180. return -ENOMEM;
  181. j = 0;
  182. dpn = prop->sink_dpn_prop;
  183. addr = prop->sink_ports;
  184. for_each_set_bit(bit, &addr, 32) {
  185. dpn[j].num = bit;
  186. dpn[j].type = SDW_DPN_FULL;
  187. dpn[j].simple_ch_prep_sm = true;
  188. j++;
  189. }
  190. prop->simple_clk_stop_capable = true;
  191. /* wake-up event */
  192. prop->wake_capable = 0;
  193. return 0;
  194. }
  195. static int sdw_mockup_bus_config(struct sdw_slave *slave,
  196. struct sdw_bus_params *params)
  197. {
  198. return 0;
  199. }
  200. static int sdw_mockup_interrupt_callback(struct sdw_slave *slave,
  201. struct sdw_slave_intr_status *status)
  202. {
  203. return 0;
  204. }
  205. static const struct sdw_slave_ops sdw_mockup_slave_ops = {
  206. .read_prop = sdw_mockup_read_prop,
  207. .interrupt_callback = sdw_mockup_interrupt_callback,
  208. .update_status = sdw_mockup_update_status,
  209. .bus_config = sdw_mockup_bus_config,
  210. };
  211. static int sdw_mockup_sdw_probe(struct sdw_slave *slave,
  212. const struct sdw_device_id *id)
  213. {
  214. struct device *dev = &slave->dev;
  215. struct sdw_mockup_priv *sdw_mockup;
  216. int ret;
  217. sdw_mockup = devm_kzalloc(dev, sizeof(*sdw_mockup), GFP_KERNEL);
  218. if (!sdw_mockup)
  219. return -ENOMEM;
  220. dev_set_drvdata(dev, sdw_mockup);
  221. sdw_mockup->slave = slave;
  222. slave->is_mockup_device = true;
  223. ret = devm_snd_soc_register_component(dev,
  224. &snd_soc_sdw_mockup_component,
  225. sdw_mockup_dai,
  226. ARRAY_SIZE(sdw_mockup_dai));
  227. return ret;
  228. }
  229. static int sdw_mockup_sdw_remove(struct sdw_slave *slave)
  230. {
  231. return 0;
  232. }
  233. /*
  234. * Intel reserved parts ID with the following mapping expected:
  235. * 0xAAAA: generic full-duplex codec
  236. * 0xAA55: headset codec (mock-up of RT711/RT5682) - full-duplex
  237. * 0x55AA: amplifier (mock-up of RT1308/Maxim 98373) - playback only with
  238. * IV feedback
  239. * 0x5555: mic codec (mock-up of RT715) - capture-only
  240. */
  241. static const struct sdw_device_id sdw_mockup_id[] = {
  242. SDW_SLAVE_ENTRY_EXT(0x0105, 0xAAAA, 0x0, 0, 0),
  243. SDW_SLAVE_ENTRY_EXT(0x0105, 0xAA55, 0x0, 0, 0),
  244. SDW_SLAVE_ENTRY_EXT(0x0105, 0x55AA, 0x0, 0, 0),
  245. SDW_SLAVE_ENTRY_EXT(0x0105, 0x5555, 0x0, 0, 0),
  246. {},
  247. };
  248. MODULE_DEVICE_TABLE(sdw, sdw_mockup_id);
  249. static struct sdw_driver sdw_mockup_sdw_driver = {
  250. .driver = {
  251. .name = "sdw-mockup",
  252. .owner = THIS_MODULE,
  253. },
  254. .probe = sdw_mockup_sdw_probe,
  255. .remove = sdw_mockup_sdw_remove,
  256. .ops = &sdw_mockup_slave_ops,
  257. .id_table = sdw_mockup_id,
  258. };
  259. module_sdw_driver(sdw_mockup_sdw_driver);
  260. MODULE_DESCRIPTION("ASoC SDW mockup codec driver");
  261. MODULE_AUTHOR("Pierre-Louis Bossart <[email protected]>");
  262. MODULE_LICENSE("GPL");