hda-dai.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  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) 2018 Intel Corporation. All rights reserved.
  7. //
  8. // Authors: Keyon Jie <[email protected]>
  9. //
  10. #include <sound/pcm_params.h>
  11. #include <sound/hdaudio_ext.h>
  12. #include <sound/intel-nhlt.h>
  13. #include <sound/sof/ipc4/header.h>
  14. #include <uapi/sound/sof/header.h>
  15. #include "../ipc4-priv.h"
  16. #include "../ipc4-topology.h"
  17. #include "../sof-priv.h"
  18. #include "../sof-audio.h"
  19. #include "hda.h"
  20. /*
  21. * The default method is to fetch NHLT from BIOS. With this parameter set
  22. * it is possible to override that with NHLT in the SOF topology manifest.
  23. */
  24. static bool hda_use_tplg_nhlt;
  25. module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444);
  26. MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override");
  27. #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
  28. struct hda_pipe_params {
  29. u32 ch;
  30. u32 s_freq;
  31. u32 s_fmt;
  32. u8 linktype;
  33. snd_pcm_format_t format;
  34. int link_index;
  35. int stream;
  36. unsigned int link_bps;
  37. };
  38. /*
  39. * This function checks if the host dma channel corresponding
  40. * to the link DMA stream_tag argument is assigned to one
  41. * of the FEs connected to the BE DAI.
  42. */
  43. static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd,
  44. int dir, int stream_tag)
  45. {
  46. struct snd_pcm_substream *fe_substream;
  47. struct hdac_stream *fe_hstream;
  48. struct snd_soc_dpcm *dpcm;
  49. for_each_dpcm_fe(rtd, dir, dpcm) {
  50. fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, dir);
  51. fe_hstream = fe_substream->runtime->private_data;
  52. if (fe_hstream->stream_tag == stream_tag)
  53. return true;
  54. }
  55. return false;
  56. }
  57. static struct hdac_ext_stream *
  58. hda_link_stream_assign(struct hdac_bus *bus,
  59. struct snd_pcm_substream *substream)
  60. {
  61. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  62. struct sof_intel_hda_stream *hda_stream;
  63. const struct sof_intel_dsp_desc *chip;
  64. struct snd_sof_dev *sdev;
  65. struct hdac_ext_stream *res = NULL;
  66. struct hdac_stream *hstream = NULL;
  67. int stream_dir = substream->stream;
  68. if (!bus->ppcap) {
  69. dev_err(bus->dev, "stream type not supported\n");
  70. return NULL;
  71. }
  72. spin_lock_irq(&bus->reg_lock);
  73. list_for_each_entry(hstream, &bus->stream_list, list) {
  74. struct hdac_ext_stream *hext_stream =
  75. stream_to_hdac_ext_stream(hstream);
  76. if (hstream->direction != substream->stream)
  77. continue;
  78. hda_stream = hstream_to_sof_hda_stream(hext_stream);
  79. sdev = hda_stream->sdev;
  80. chip = get_chip_info(sdev->pdata);
  81. /* check if link is available */
  82. if (!hext_stream->link_locked) {
  83. /*
  84. * choose the first available link for platforms that do not have the
  85. * PROCEN_FMT_QUIRK set.
  86. */
  87. if (!(chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) {
  88. res = hext_stream;
  89. break;
  90. }
  91. if (hstream->opened) {
  92. /*
  93. * check if the stream tag matches the stream
  94. * tag of one of the connected FEs
  95. */
  96. if (hda_check_fes(rtd, stream_dir,
  97. hstream->stream_tag)) {
  98. res = hext_stream;
  99. break;
  100. }
  101. } else {
  102. res = hext_stream;
  103. /*
  104. * This must be a hostless stream.
  105. * So reserve the host DMA channel.
  106. */
  107. hda_stream->host_reserved = 1;
  108. break;
  109. }
  110. }
  111. }
  112. if (res) {
  113. /* Make sure that host and link DMA is decoupled. */
  114. snd_hdac_ext_stream_decouple_locked(bus, res, true);
  115. res->link_locked = 1;
  116. res->link_substream = substream;
  117. }
  118. spin_unlock_irq(&bus->reg_lock);
  119. return res;
  120. }
  121. static int hda_link_dma_cleanup(struct snd_pcm_substream *substream,
  122. struct hdac_stream *hstream,
  123. struct snd_soc_dai *cpu_dai,
  124. struct snd_soc_dai *codec_dai,
  125. bool trigger_suspend_stop)
  126. {
  127. struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
  128. struct hdac_bus *bus = hstream->bus;
  129. struct sof_intel_hda_stream *hda_stream;
  130. struct hdac_ext_link *link;
  131. int stream_tag;
  132. link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
  133. if (!link)
  134. return -EINVAL;
  135. if (trigger_suspend_stop)
  136. snd_hdac_ext_link_stream_clear(hext_stream);
  137. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  138. stream_tag = hdac_stream(hext_stream)->stream_tag;
  139. snd_hdac_ext_link_clear_stream_id(link, stream_tag);
  140. }
  141. snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
  142. snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
  143. hext_stream->link_prepared = 0;
  144. /* free the host DMA channel reserved by hostless streams */
  145. hda_stream = hstream_to_sof_hda_stream(hext_stream);
  146. hda_stream->host_reserved = 0;
  147. return 0;
  148. }
  149. static int hda_link_dma_params(struct hdac_ext_stream *hext_stream,
  150. struct hda_pipe_params *params)
  151. {
  152. struct hdac_stream *hstream = &hext_stream->hstream;
  153. unsigned char stream_tag = hstream->stream_tag;
  154. struct hdac_bus *bus = hstream->bus;
  155. struct hdac_ext_link *link;
  156. unsigned int format_val;
  157. snd_hdac_ext_link_stream_reset(hext_stream);
  158. format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch,
  159. params->format,
  160. params->link_bps, 0);
  161. dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
  162. format_val, params->s_freq, params->ch, params->format);
  163. snd_hdac_ext_link_stream_setup(hext_stream, format_val);
  164. if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) {
  165. list_for_each_entry(link, &bus->hlink_list, list) {
  166. if (link->index == params->link_index)
  167. snd_hdac_ext_link_set_stream_id(link,
  168. stream_tag);
  169. }
  170. }
  171. hext_stream->link_prepared = 1;
  172. return 0;
  173. }
  174. static int hda_link_dma_hw_params(struct snd_pcm_substream *substream,
  175. struct snd_pcm_hw_params *params)
  176. {
  177. struct hdac_stream *hstream = substream->runtime->private_data;
  178. struct hdac_ext_stream *hext_stream;
  179. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  180. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  181. struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  182. struct hda_pipe_params p_params = {0};
  183. struct hdac_bus *bus = hstream->bus;
  184. struct hdac_ext_link *link;
  185. link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
  186. if (!link)
  187. return -EINVAL;
  188. hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
  189. if (!hext_stream) {
  190. hext_stream = hda_link_stream_assign(bus, substream);
  191. if (!hext_stream)
  192. return -EBUSY;
  193. snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream);
  194. }
  195. /* set the hdac_stream in the codec dai */
  196. snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream);
  197. p_params.s_fmt = snd_pcm_format_width(params_format(params));
  198. p_params.ch = params_channels(params);
  199. p_params.s_freq = params_rate(params);
  200. p_params.stream = substream->stream;
  201. p_params.link_index = link->index;
  202. p_params.format = params_format(params);
  203. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  204. p_params.link_bps = codec_dai->driver->playback.sig_bits;
  205. else
  206. p_params.link_bps = codec_dai->driver->capture.sig_bits;
  207. return hda_link_dma_params(hext_stream, &p_params);
  208. }
  209. static int hda_link_dma_prepare(struct snd_pcm_substream *substream)
  210. {
  211. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  212. int stream = substream->stream;
  213. return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params);
  214. }
  215. static int hda_link_dma_trigger(struct snd_pcm_substream *substream, int cmd)
  216. {
  217. struct hdac_stream *hstream = substream->runtime->private_data;
  218. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  219. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  220. struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  221. struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
  222. int ret;
  223. if (!hext_stream)
  224. return 0;
  225. switch (cmd) {
  226. case SNDRV_PCM_TRIGGER_START:
  227. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  228. snd_hdac_ext_link_stream_start(hext_stream);
  229. break;
  230. case SNDRV_PCM_TRIGGER_SUSPEND:
  231. case SNDRV_PCM_TRIGGER_STOP:
  232. ret = hda_link_dma_cleanup(substream, hstream, cpu_dai, codec_dai, true);
  233. if (ret < 0)
  234. return ret;
  235. break;
  236. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  237. snd_hdac_ext_link_stream_clear(hext_stream);
  238. break;
  239. default:
  240. return -EINVAL;
  241. }
  242. return 0;
  243. }
  244. static int hda_link_dma_hw_free(struct snd_pcm_substream *substream)
  245. {
  246. struct hdac_stream *hstream = substream->runtime->private_data;
  247. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  248. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  249. struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  250. struct hdac_ext_stream *hext_stream;
  251. hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
  252. if (!hext_stream)
  253. return 0;
  254. return hda_link_dma_cleanup(substream, hstream, cpu_dai, codec_dai, false);
  255. }
  256. static int hda_dai_widget_update(struct snd_soc_dapm_widget *w,
  257. int channel, bool widget_setup)
  258. {
  259. struct snd_sof_dai_config_data data;
  260. data.dai_data = channel;
  261. /* set up/free DAI widget and send DAI_CONFIG IPC */
  262. if (widget_setup)
  263. return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_2_STEP_STOP, &data);
  264. return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data);
  265. }
  266. static int hda_dai_hw_params_update(struct snd_pcm_substream *substream,
  267. struct snd_pcm_hw_params *params,
  268. struct snd_soc_dai *dai)
  269. {
  270. struct hdac_ext_stream *hext_stream;
  271. struct snd_soc_dapm_widget *w;
  272. int stream_tag;
  273. hext_stream = snd_soc_dai_get_dma_data(dai, substream);
  274. if (!hext_stream)
  275. return -EINVAL;
  276. stream_tag = hdac_stream(hext_stream)->stream_tag;
  277. w = snd_soc_dai_get_widget(dai, substream->stream);
  278. /* set up the DAI widget and send the DAI_CONFIG with the new tag */
  279. return hda_dai_widget_update(w, stream_tag - 1, true);
  280. }
  281. static int hda_dai_hw_params(struct snd_pcm_substream *substream,
  282. struct snd_pcm_hw_params *params,
  283. struct snd_soc_dai *dai)
  284. {
  285. struct hdac_ext_stream *hext_stream =
  286. snd_soc_dai_get_dma_data(dai, substream);
  287. int ret;
  288. if (hext_stream && hext_stream->link_prepared)
  289. return 0;
  290. ret = hda_link_dma_hw_params(substream, params);
  291. if (ret < 0)
  292. return ret;
  293. return hda_dai_hw_params_update(substream, params, dai);
  294. }
  295. static int hda_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w)
  296. {
  297. struct snd_sof_widget *swidget = w->dobj.private;
  298. struct snd_soc_component *component = swidget->scomp;
  299. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  300. const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg;
  301. int ret = 0;
  302. if (tplg_ops->dai_config) {
  303. ret = tplg_ops->dai_config(sdev, swidget, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL);
  304. if (ret < 0)
  305. dev_err(sdev->dev, "%s: DAI config failed for widget %s\n", __func__,
  306. w->name);
  307. }
  308. return ret;
  309. }
  310. static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
  311. {
  312. struct hdac_ext_stream *hext_stream =
  313. snd_soc_dai_get_dma_data(dai, substream);
  314. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
  315. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  316. int stream = substream->stream;
  317. int ret;
  318. if (hext_stream && hext_stream->link_prepared)
  319. return 0;
  320. dev_dbg(sdev->dev, "prepare stream dir %d\n", substream->stream);
  321. ret = hda_link_dma_prepare(substream);
  322. if (ret < 0)
  323. return ret;
  324. return hda_dai_hw_params_update(substream, &rtd->dpcm[stream].hw_params, dai);
  325. }
  326. static int hda_dai_hw_free_ipc(int stream, /* direction */
  327. struct snd_soc_dai *dai)
  328. {
  329. struct snd_soc_dapm_widget *w;
  330. w = snd_soc_dai_get_widget(dai, stream);
  331. /* free the link DMA channel in the FW and the DAI widget */
  332. return hda_dai_widget_update(w, DMA_CHAN_INVALID, false);
  333. }
  334. static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream,
  335. int cmd, struct snd_soc_dai *dai)
  336. {
  337. struct snd_soc_dapm_widget *w;
  338. int ret;
  339. dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd,
  340. dai->name, substream->stream);
  341. ret = hda_link_dma_trigger(substream, cmd);
  342. if (ret < 0)
  343. return ret;
  344. w = snd_soc_dai_get_widget(dai, substream->stream);
  345. switch (cmd) {
  346. case SNDRV_PCM_TRIGGER_SUSPEND:
  347. case SNDRV_PCM_TRIGGER_STOP:
  348. /*
  349. * free DAI widget during stop/suspend to keep widget use_count's balanced.
  350. */
  351. ret = hda_dai_hw_free_ipc(substream->stream, dai);
  352. if (ret < 0)
  353. return ret;
  354. break;
  355. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  356. ret = hda_dai_config_pause_push_ipc(w);
  357. if (ret < 0)
  358. return ret;
  359. break;
  360. default:
  361. break;
  362. }
  363. return 0;
  364. }
  365. /*
  366. * In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes
  367. * (over IPC channel) and DMA state change (direct host register changes).
  368. */
  369. static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream,
  370. int cmd, struct snd_soc_dai *dai)
  371. {
  372. struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(dai, substream);
  373. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
  374. struct snd_soc_pcm_runtime *rtd;
  375. struct snd_sof_widget *swidget;
  376. struct snd_soc_dapm_widget *w;
  377. struct snd_soc_dai *codec_dai;
  378. struct hdac_stream *hstream;
  379. struct snd_soc_dai *cpu_dai;
  380. int ret;
  381. dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd,
  382. dai->name, substream->stream);
  383. hstream = substream->runtime->private_data;
  384. rtd = asoc_substream_to_rtd(substream);
  385. cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  386. codec_dai = asoc_rtd_to_codec(rtd, 0);
  387. w = snd_soc_dai_get_widget(dai, substream->stream);
  388. swidget = w->dobj.private;
  389. switch (cmd) {
  390. case SNDRV_PCM_TRIGGER_START:
  391. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  392. snd_hdac_ext_link_stream_start(hext_stream);
  393. break;
  394. case SNDRV_PCM_TRIGGER_SUSPEND:
  395. case SNDRV_PCM_TRIGGER_STOP:
  396. {
  397. struct snd_sof_widget *pipe_widget = swidget->pipe_widget;
  398. struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
  399. ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
  400. SOF_IPC4_PIPE_PAUSED);
  401. if (ret < 0)
  402. return ret;
  403. pipeline->state = SOF_IPC4_PIPE_PAUSED;
  404. snd_hdac_ext_link_stream_clear(hext_stream);
  405. ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
  406. SOF_IPC4_PIPE_RESET);
  407. if (ret < 0)
  408. return ret;
  409. pipeline->state = SOF_IPC4_PIPE_RESET;
  410. ret = hda_link_dma_cleanup(substream, hstream, cpu_dai, codec_dai, false);
  411. if (ret < 0) {
  412. dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__);
  413. return ret;
  414. }
  415. break;
  416. }
  417. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  418. {
  419. struct snd_sof_widget *pipe_widget = swidget->pipe_widget;
  420. struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
  421. ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
  422. SOF_IPC4_PIPE_PAUSED);
  423. if (ret < 0)
  424. return ret;
  425. pipeline->state = SOF_IPC4_PIPE_PAUSED;
  426. snd_hdac_ext_link_stream_clear(hext_stream);
  427. break;
  428. }
  429. default:
  430. dev_err(sdev->dev, "%s: unknown trigger command %d\n", __func__, cmd);
  431. return -EINVAL;
  432. }
  433. return 0;
  434. }
  435. static int hda_dai_hw_free(struct snd_pcm_substream *substream,
  436. struct snd_soc_dai *dai)
  437. {
  438. int ret;
  439. ret = hda_link_dma_hw_free(substream);
  440. if (ret < 0)
  441. return ret;
  442. return hda_dai_hw_free_ipc(substream->stream, dai);
  443. }
  444. static const struct snd_soc_dai_ops ipc3_hda_dai_ops = {
  445. .hw_params = hda_dai_hw_params,
  446. .hw_free = hda_dai_hw_free,
  447. .trigger = ipc3_hda_dai_trigger,
  448. .prepare = hda_dai_prepare,
  449. };
  450. static int hda_dai_suspend(struct hdac_bus *bus)
  451. {
  452. struct snd_soc_pcm_runtime *rtd;
  453. struct hdac_ext_stream *hext_stream;
  454. struct hdac_stream *s;
  455. int ret;
  456. /* set internal flag for BE */
  457. list_for_each_entry(s, &bus->stream_list, list) {
  458. hext_stream = stream_to_hdac_ext_stream(s);
  459. /*
  460. * clear stream. This should already be taken care for running
  461. * streams when the SUSPEND trigger is called. But paused
  462. * streams do not get suspended, so this needs to be done
  463. * explicitly during suspend.
  464. */
  465. if (hext_stream->link_substream) {
  466. struct snd_soc_dai *cpu_dai;
  467. struct snd_soc_dai *codec_dai;
  468. rtd = asoc_substream_to_rtd(hext_stream->link_substream);
  469. cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  470. codec_dai = asoc_rtd_to_codec(rtd, 0);
  471. ret = hda_link_dma_cleanup(hext_stream->link_substream, s,
  472. cpu_dai, codec_dai, false);
  473. if (ret < 0)
  474. return ret;
  475. /* for consistency with TRIGGER_SUSPEND we free DAI resources */
  476. ret = hda_dai_hw_free_ipc(hdac_stream(hext_stream)->direction, cpu_dai);
  477. if (ret < 0)
  478. return ret;
  479. }
  480. }
  481. return 0;
  482. }
  483. static const struct snd_soc_dai_ops ipc4_hda_dai_ops = {
  484. .hw_params = hda_dai_hw_params,
  485. .hw_free = hda_dai_hw_free,
  486. .trigger = ipc4_hda_dai_trigger,
  487. .prepare = hda_dai_prepare,
  488. };
  489. #endif
  490. /* only one flag used so far to harden hw_params/hw_free/trigger/prepare */
  491. struct ssp_dai_dma_data {
  492. bool setup;
  493. };
  494. static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai,
  495. bool setup)
  496. {
  497. struct snd_soc_dapm_widget *w;
  498. w = snd_soc_dai_get_widget(dai, substream->stream);
  499. if (setup)
  500. return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL);
  501. return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL);
  502. }
  503. static int ssp_dai_startup(struct snd_pcm_substream *substream,
  504. struct snd_soc_dai *dai)
  505. {
  506. struct ssp_dai_dma_data *dma_data;
  507. dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
  508. if (!dma_data)
  509. return -ENOMEM;
  510. snd_soc_dai_set_dma_data(dai, substream, dma_data);
  511. return 0;
  512. }
  513. static int ssp_dai_setup(struct snd_pcm_substream *substream,
  514. struct snd_soc_dai *dai,
  515. bool setup)
  516. {
  517. struct ssp_dai_dma_data *dma_data;
  518. int ret = 0;
  519. dma_data = snd_soc_dai_get_dma_data(dai, substream);
  520. if (!dma_data) {
  521. dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
  522. return -EIO;
  523. }
  524. if (dma_data->setup != setup) {
  525. ret = ssp_dai_setup_or_free(substream, dai, setup);
  526. if (!ret)
  527. dma_data->setup = setup;
  528. }
  529. return ret;
  530. }
  531. static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
  532. struct snd_pcm_hw_params *params,
  533. struct snd_soc_dai *dai)
  534. {
  535. /* params are ignored for now */
  536. return ssp_dai_setup(substream, dai, true);
  537. }
  538. static int ssp_dai_prepare(struct snd_pcm_substream *substream,
  539. struct snd_soc_dai *dai)
  540. {
  541. /*
  542. * the SSP will only be reconfigured during resume operations and
  543. * not in case of xruns
  544. */
  545. return ssp_dai_setup(substream, dai, true);
  546. }
  547. static int ipc3_ssp_dai_trigger(struct snd_pcm_substream *substream,
  548. int cmd, struct snd_soc_dai *dai)
  549. {
  550. if (cmd != SNDRV_PCM_TRIGGER_SUSPEND)
  551. return 0;
  552. return ssp_dai_setup(substream, dai, false);
  553. }
  554. static int ssp_dai_hw_free(struct snd_pcm_substream *substream,
  555. struct snd_soc_dai *dai)
  556. {
  557. return ssp_dai_setup(substream, dai, false);
  558. }
  559. static void ssp_dai_shutdown(struct snd_pcm_substream *substream,
  560. struct snd_soc_dai *dai)
  561. {
  562. struct ssp_dai_dma_data *dma_data;
  563. dma_data = snd_soc_dai_get_dma_data(dai, substream);
  564. if (!dma_data) {
  565. dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
  566. return;
  567. }
  568. snd_soc_dai_set_dma_data(dai, substream, NULL);
  569. kfree(dma_data);
  570. }
  571. static const struct snd_soc_dai_ops ipc3_ssp_dai_ops = {
  572. .startup = ssp_dai_startup,
  573. .hw_params = ssp_dai_hw_params,
  574. .prepare = ssp_dai_prepare,
  575. .trigger = ipc3_ssp_dai_trigger,
  576. .hw_free = ssp_dai_hw_free,
  577. .shutdown = ssp_dai_shutdown,
  578. };
  579. static int ipc4_be_dai_common_trigger(struct snd_soc_dai *dai, int cmd, int stream)
  580. {
  581. struct snd_sof_widget *pipe_widget;
  582. struct sof_ipc4_pipeline *pipeline;
  583. struct snd_sof_widget *swidget;
  584. struct snd_soc_dapm_widget *w;
  585. struct snd_sof_dev *sdev;
  586. int ret;
  587. w = snd_soc_dai_get_widget(dai, stream);
  588. swidget = w->dobj.private;
  589. pipe_widget = swidget->pipe_widget;
  590. pipeline = pipe_widget->private;
  591. sdev = snd_soc_component_get_drvdata(swidget->scomp);
  592. switch (cmd) {
  593. case SNDRV_PCM_TRIGGER_SUSPEND:
  594. case SNDRV_PCM_TRIGGER_STOP:
  595. ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
  596. SOF_IPC4_PIPE_PAUSED);
  597. if (ret < 0)
  598. return ret;
  599. pipeline->state = SOF_IPC4_PIPE_PAUSED;
  600. ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
  601. SOF_IPC4_PIPE_RESET);
  602. if (ret < 0)
  603. return ret;
  604. pipeline->state = SOF_IPC4_PIPE_RESET;
  605. break;
  606. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  607. ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
  608. SOF_IPC4_PIPE_PAUSED);
  609. if (ret < 0)
  610. return ret;
  611. pipeline->state = SOF_IPC4_PIPE_PAUSED;
  612. break;
  613. default:
  614. break;
  615. }
  616. return 0;
  617. }
  618. static int ipc4_be_dai_trigger(struct snd_pcm_substream *substream,
  619. int cmd, struct snd_soc_dai *dai)
  620. {
  621. return ipc4_be_dai_common_trigger(dai, cmd, substream->stream);
  622. }
  623. static const struct snd_soc_dai_ops ipc4_dmic_dai_ops = {
  624. .trigger = ipc4_be_dai_trigger,
  625. };
  626. static const struct snd_soc_dai_ops ipc4_ssp_dai_ops = {
  627. .trigger = ipc4_be_dai_trigger,
  628. };
  629. void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
  630. {
  631. int i;
  632. switch (sdev->pdata->ipc_type) {
  633. case SOF_IPC:
  634. for (i = 0; i < ops->num_drv; i++) {
  635. if (strstr(ops->drv[i].name, "SSP")) {
  636. ops->drv[i].ops = &ipc3_ssp_dai_ops;
  637. continue;
  638. }
  639. #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
  640. if (strstr(ops->drv[i].name, "iDisp") ||
  641. strstr(ops->drv[i].name, "Analog") ||
  642. strstr(ops->drv[i].name, "Digital"))
  643. ops->drv[i].ops = &ipc3_hda_dai_ops;
  644. #endif
  645. }
  646. break;
  647. case SOF_INTEL_IPC4:
  648. {
  649. struct sof_ipc4_fw_data *ipc4_data = sdev->private;
  650. for (i = 0; i < ops->num_drv; i++) {
  651. if (strstr(ops->drv[i].name, "DMIC")) {
  652. ops->drv[i].ops = &ipc4_dmic_dai_ops;
  653. continue;
  654. }
  655. if (strstr(ops->drv[i].name, "SSP")) {
  656. ops->drv[i].ops = &ipc4_ssp_dai_ops;
  657. continue;
  658. }
  659. #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
  660. if (strstr(ops->drv[i].name, "iDisp") ||
  661. strstr(ops->drv[i].name, "Analog") ||
  662. strstr(ops->drv[i].name, "Digital"))
  663. ops->drv[i].ops = &ipc4_hda_dai_ops;
  664. #endif
  665. }
  666. if (!hda_use_tplg_nhlt)
  667. ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
  668. if (IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE))
  669. sdw_callback.trigger = ipc4_be_dai_common_trigger;
  670. break;
  671. }
  672. default:
  673. break;
  674. }
  675. }
  676. void hda_ops_free(struct snd_sof_dev *sdev)
  677. {
  678. if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
  679. struct sof_ipc4_fw_data *ipc4_data = sdev->private;
  680. if (!hda_use_tplg_nhlt)
  681. intel_nhlt_free(ipc4_data->nhlt);
  682. }
  683. }
  684. EXPORT_SYMBOL_NS(hda_ops_free, SND_SOC_SOF_INTEL_HDA_COMMON);
  685. /*
  686. * common dai driver for skl+ platforms.
  687. * some products who use this DAI array only physically have a subset of
  688. * the DAIs, but no harm is done here by adding the whole set.
  689. */
  690. struct snd_soc_dai_driver skl_dai[] = {
  691. {
  692. .name = "SSP0 Pin",
  693. .playback = {
  694. .channels_min = 1,
  695. .channels_max = 8,
  696. },
  697. .capture = {
  698. .channels_min = 1,
  699. .channels_max = 8,
  700. },
  701. },
  702. {
  703. .name = "SSP1 Pin",
  704. .playback = {
  705. .channels_min = 1,
  706. .channels_max = 8,
  707. },
  708. .capture = {
  709. .channels_min = 1,
  710. .channels_max = 8,
  711. },
  712. },
  713. {
  714. .name = "SSP2 Pin",
  715. .playback = {
  716. .channels_min = 1,
  717. .channels_max = 8,
  718. },
  719. .capture = {
  720. .channels_min = 1,
  721. .channels_max = 8,
  722. },
  723. },
  724. {
  725. .name = "SSP3 Pin",
  726. .playback = {
  727. .channels_min = 1,
  728. .channels_max = 8,
  729. },
  730. .capture = {
  731. .channels_min = 1,
  732. .channels_max = 8,
  733. },
  734. },
  735. {
  736. .name = "SSP4 Pin",
  737. .playback = {
  738. .channels_min = 1,
  739. .channels_max = 8,
  740. },
  741. .capture = {
  742. .channels_min = 1,
  743. .channels_max = 8,
  744. },
  745. },
  746. {
  747. .name = "SSP5 Pin",
  748. .playback = {
  749. .channels_min = 1,
  750. .channels_max = 8,
  751. },
  752. .capture = {
  753. .channels_min = 1,
  754. .channels_max = 8,
  755. },
  756. },
  757. {
  758. .name = "DMIC01 Pin",
  759. .capture = {
  760. .channels_min = 1,
  761. .channels_max = 4,
  762. },
  763. },
  764. {
  765. .name = "DMIC16k Pin",
  766. .capture = {
  767. .channels_min = 1,
  768. .channels_max = 4,
  769. },
  770. },
  771. #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
  772. {
  773. .name = "iDisp1 Pin",
  774. .playback = {
  775. .channels_min = 1,
  776. .channels_max = 8,
  777. },
  778. },
  779. {
  780. .name = "iDisp2 Pin",
  781. .playback = {
  782. .channels_min = 1,
  783. .channels_max = 8,
  784. },
  785. },
  786. {
  787. .name = "iDisp3 Pin",
  788. .playback = {
  789. .channels_min = 1,
  790. .channels_max = 8,
  791. },
  792. },
  793. {
  794. .name = "iDisp4 Pin",
  795. .playback = {
  796. .channels_min = 1,
  797. .channels_max = 8,
  798. },
  799. },
  800. {
  801. .name = "Analog CPU DAI",
  802. .playback = {
  803. .channels_min = 1,
  804. .channels_max = 16,
  805. },
  806. .capture = {
  807. .channels_min = 1,
  808. .channels_max = 16,
  809. },
  810. },
  811. {
  812. .name = "Digital CPU DAI",
  813. .playback = {
  814. .channels_min = 1,
  815. .channels_max = 16,
  816. },
  817. .capture = {
  818. .channels_min = 1,
  819. .channels_max = 16,
  820. },
  821. },
  822. {
  823. .name = "Alt Analog CPU DAI",
  824. .playback = {
  825. .channels_min = 1,
  826. .channels_max = 16,
  827. },
  828. .capture = {
  829. .channels_min = 1,
  830. .channels_max = 16,
  831. },
  832. },
  833. #endif
  834. };
  835. int hda_dsp_dais_suspend(struct snd_sof_dev *sdev)
  836. {
  837. /*
  838. * In the corner case where a SUSPEND happens during a PAUSE, the ALSA core
  839. * does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state.
  840. * Since the component suspend is called last, we can trap this corner case
  841. * and force the DAIs to release their resources.
  842. */
  843. #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
  844. int ret;
  845. ret = hda_dai_suspend(sof_to_bus(sdev));
  846. if (ret < 0)
  847. return ret;
  848. #endif
  849. return 0;
  850. }