brintos

brintos / linux-shallow public Read only

0
0
Text · 20.4 KiB · 4e08892 Raw
807 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// soc-dai.c4//5// Copyright (C) 2019 Renesas Electronics Corp.6// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>7//8 9#include <sound/soc.h>10#include <sound/soc-dai.h>11#include <sound/soc-link.h>12 13#define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret)14static inline int _soc_dai_ret(const struct snd_soc_dai *dai,15			       const char *func, int ret)16{17	/* Positive, Zero values are not errors */18	if (ret >= 0)19		return ret;20 21	/* Negative values might be errors */22	switch (ret) {23	case -EPROBE_DEFER:24	case -ENOTSUPP:25		break;26	default:27		dev_err(dai->dev,28			"ASoC: error at %s on %s: %d\n",29			func, dai->name, ret);30	}31 32	return ret;33}34 35/*36 * We might want to check substream by using list.37 * In such case, we can update these macros.38 */39#define soc_dai_mark_push(dai, substream, tgt)	((dai)->mark_##tgt = substream)40#define soc_dai_mark_pop(dai, substream, tgt)	((dai)->mark_##tgt = NULL)41#define soc_dai_mark_match(dai, substream, tgt)	((dai)->mark_##tgt == substream)42 43/**44 * snd_soc_dai_set_sysclk - configure DAI system or master clock.45 * @dai: DAI46 * @clk_id: DAI specific clock ID47 * @freq: new clock frequency in Hz48 * @dir: new clock direction (SND_SOC_CLOCK_IN or SND_SOC_CLOCK_OUT)49 *50 * Configures the DAI master (MCLK) or system (SYSCLK) clocking.51 */52int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,53			   unsigned int freq, int dir)54{55	int ret;56 57	if (dai->driver->ops &&58	    dai->driver->ops->set_sysclk)59		ret = dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);60	else61		ret = snd_soc_component_set_sysclk(dai->component, clk_id, 0,62						   freq, dir);63 64	return soc_dai_ret(dai, ret);65}66EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);67 68/**69 * snd_soc_dai_set_clkdiv - configure DAI clock dividers.70 * @dai: DAI71 * @div_id: DAI specific clock divider ID72 * @div: new clock divisor.73 *74 * Configures the clock dividers. This is used to derive the best DAI bit and75 * frame clocks from the system or master clock. It's best to set the DAI bit76 * and frame clocks as low as possible to save system power.77 */78int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,79			   int div_id, int div)80{81	int ret = -EINVAL;82 83	if (dai->driver->ops &&84	    dai->driver->ops->set_clkdiv)85		ret = dai->driver->ops->set_clkdiv(dai, div_id, div);86 87	return soc_dai_ret(dai, ret);88}89EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);90 91/**92 * snd_soc_dai_set_pll - configure DAI PLL.93 * @dai: DAI94 * @pll_id: DAI specific PLL ID95 * @source: DAI specific source for the PLL96 * @freq_in: PLL input clock frequency in Hz97 * @freq_out: requested PLL output clock frequency in Hz98 *99 * Configures and enables PLL to generate output clock based on input clock.100 */101int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,102			unsigned int freq_in, unsigned int freq_out)103{104	int ret;105 106	if (dai->driver->ops &&107	    dai->driver->ops->set_pll)108		ret = dai->driver->ops->set_pll(dai, pll_id, source,109						freq_in, freq_out);110	else111		ret = snd_soc_component_set_pll(dai->component, pll_id, source,112						freq_in, freq_out);113 114	return soc_dai_ret(dai, ret);115}116EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);117 118/**119 * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.120 * @dai: DAI121 * @ratio: Ratio of BCLK to Sample rate.122 *123 * Configures the DAI for a preset BCLK to sample rate ratio.124 */125int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)126{127	int ret = -ENOTSUPP;128 129	if (dai->driver->ops &&130	    dai->driver->ops->set_bclk_ratio)131		ret = dai->driver->ops->set_bclk_ratio(dai, ratio);132 133	return soc_dai_ret(dai, ret);134}135EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);136 137int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd)138{139	struct snd_soc_dai *dai;140	int i, max = 0;141 142	/*143	 * return max num if *ALL* DAIs have .auto_selectable_formats144	 */145	for_each_rtd_dais(rtd, i, dai) {146		if (dai->driver->ops &&147		    dai->driver->ops->num_auto_selectable_formats)148			max = max(max, dai->driver->ops->num_auto_selectable_formats);149		else150			return 0;151	}152 153	return max;154}155 156/**157 * snd_soc_dai_get_fmt - get supported audio format.158 * @dai: DAI159 * @priority: priority level of supported audio format.160 *161 * This should return only formats implemented with high162 * quality by the DAI so that the core can configure a163 * format which will work well with other devices.164 * For example devices which don't support both edges of the165 * LRCLK signal in I2S style formats should only list DSP166 * modes.  This will mean that sometimes fewer formats167 * are reported here than are supported by set_fmt().168 */169u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority)170{171	const struct snd_soc_dai_ops *ops = dai->driver->ops;172	u64 fmt = 0;173	int i, max = 0, until = priority;174 175	/*176	 * Collect auto_selectable_formats until priority177	 *178	 * ex)179	 *	auto_selectable_formats[] = { A, B, C };180	 *	(A, B, C = SND_SOC_POSSIBLE_DAIFMT_xxx)181	 *182	 * priority = 1 :	A183	 * priority = 2 :	A | B184	 * priority = 3 :	A | B | C185	 * priority = 4 :	A | B | C186	 * ...187	 */188	if (ops)189		max = ops->num_auto_selectable_formats;190 191	if (max < until)192		until = max;193 194	for (i = 0; i < until; i++)195		fmt |= ops->auto_selectable_formats[i];196 197	return fmt;198}199 200/**201 * snd_soc_dai_set_fmt - configure DAI hardware audio format.202 * @dai: DAI203 * @fmt: SND_SOC_DAIFMT_* format value.204 *205 * Configures the DAI hardware format and clocking.206 */207int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)208{209	int ret = -ENOTSUPP;210 211	if (dai->driver->ops && dai->driver->ops->set_fmt)212		ret = dai->driver->ops->set_fmt(dai, fmt);213 214	return soc_dai_ret(dai, ret);215}216EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);217 218/**219 * snd_soc_xlate_tdm_slot_mask - generate tx/rx slot mask.220 * @slots: Number of slots in use.221 * @tx_mask: bitmask representing active TX slots.222 * @rx_mask: bitmask representing active RX slots.223 *224 * Generates the TDM tx and rx slot default masks for DAI.225 */226static int snd_soc_xlate_tdm_slot_mask(unsigned int slots,227				       unsigned int *tx_mask,228				       unsigned int *rx_mask)229{230	if (*tx_mask || *rx_mask)231		return 0;232 233	if (!slots)234		return -EINVAL;235 236	*tx_mask = (1 << slots) - 1;237	*rx_mask = (1 << slots) - 1;238 239	return 0;240}241 242/**243 * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation244 * @dai: The DAI to configure245 * @tx_mask: bitmask representing active TX slots.246 * @rx_mask: bitmask representing active RX slots.247 * @slots: Number of slots in use.248 * @slot_width: Width in bits for each slot.249 *250 * This function configures the specified DAI for TDM operation. @slot contains251 * the total number of slots of the TDM stream and @slot_with the width of each252 * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the253 * active slots of the TDM stream for the specified DAI, i.e. which slots the254 * DAI should write to or read from. If a bit is set the corresponding slot is255 * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to256 * the first slot, bit 1 to the second slot and so on. The first active slot257 * maps to the first channel of the DAI, the second active slot to the second258 * channel and so on.259 *260 * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask,261 * @rx_mask and @slot_width will be ignored.262 *263 * Returns 0 on success, a negative error code otherwise.264 */265int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,266			     unsigned int tx_mask, unsigned int rx_mask,267			     int slots, int slot_width)268{269	int ret = -ENOTSUPP;270	int stream;271	unsigned int *tdm_mask[] = {272		&tx_mask,273		&rx_mask,274	};275 276	if (dai->driver->ops &&277	    dai->driver->ops->xlate_tdm_slot_mask)278		dai->driver->ops->xlate_tdm_slot_mask(slots,279						      &tx_mask, &rx_mask);280	else281		snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);282 283	for_each_pcm_streams(stream)284		snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]);285 286	if (dai->driver->ops &&287	    dai->driver->ops->set_tdm_slot)288		ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,289						      slots, slot_width);290	return soc_dai_ret(dai, ret);291}292EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);293 294/**295 * snd_soc_dai_set_channel_map - configure DAI audio channel map296 * @dai: DAI297 * @tx_num: how many TX channels298 * @tx_slot: pointer to an array which imply the TX slot number channel299 *           0~num-1 uses300 * @rx_num: how many RX channels301 * @rx_slot: pointer to an array which imply the RX slot number channel302 *           0~num-1 uses303 *304 * configure the relationship between channel number and TDM slot number.305 */306int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,307				unsigned int tx_num, const unsigned int *tx_slot,308				unsigned int rx_num, const unsigned int *rx_slot)309{310	int ret = -ENOTSUPP;311 312	if (dai->driver->ops &&313	    dai->driver->ops->set_channel_map)314		ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,315							rx_num, rx_slot);316	return soc_dai_ret(dai, ret);317}318EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);319 320/**321 * snd_soc_dai_get_channel_map - Get DAI audio channel map322 * @dai: DAI323 * @tx_num: how many TX channels324 * @tx_slot: pointer to an array which imply the TX slot number channel325 *           0~num-1 uses326 * @rx_num: how many RX channels327 * @rx_slot: pointer to an array which imply the RX slot number channel328 *           0~num-1 uses329 */330int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai,331				unsigned int *tx_num, unsigned int *tx_slot,332				unsigned int *rx_num, unsigned int *rx_slot)333{334	int ret = -ENOTSUPP;335 336	if (dai->driver->ops &&337	    dai->driver->ops->get_channel_map)338		ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,339							rx_num, rx_slot);340	return soc_dai_ret(dai, ret);341}342EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);343 344/**345 * snd_soc_dai_set_tristate - configure DAI system or master clock.346 * @dai: DAI347 * @tristate: tristate enable348 *349 * Tristates the DAI so that others can use it.350 */351int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)352{353	int ret = -EINVAL;354 355	if (dai->driver->ops &&356	    dai->driver->ops->set_tristate)357		ret = dai->driver->ops->set_tristate(dai, tristate);358 359	return soc_dai_ret(dai, ret);360}361EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);362 363/**364 * snd_soc_dai_digital_mute - configure DAI system or master clock.365 * @dai: DAI366 * @mute: mute enable367 * @direction: stream to mute368 *369 * Mutes the DAI DAC.370 */371int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,372			     int direction)373{374	int ret = -ENOTSUPP;375 376	/*377	 * ignore if direction was CAPTURE378	 * and it had .no_capture_mute flag379	 */380	if (dai->driver->ops &&381	    dai->driver->ops->mute_stream &&382	    (direction == SNDRV_PCM_STREAM_PLAYBACK ||383	     !dai->driver->ops->no_capture_mute))384		ret = dai->driver->ops->mute_stream(dai, mute, direction);385 386	return soc_dai_ret(dai, ret);387}388EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);389 390int snd_soc_dai_hw_params(struct snd_soc_dai *dai,391			  struct snd_pcm_substream *substream,392			  struct snd_pcm_hw_params *params)393{394	int ret = 0;395 396	if (dai->driver->ops &&397	    dai->driver->ops->hw_params)398		ret = dai->driver->ops->hw_params(substream, params, dai);399 400	/* mark substream if succeeded */401	if (ret == 0)402		soc_dai_mark_push(dai, substream, hw_params);403 404	return soc_dai_ret(dai, ret);405}406 407void snd_soc_dai_hw_free(struct snd_soc_dai *dai,408			 struct snd_pcm_substream *substream,409			 int rollback)410{411	if (rollback && !soc_dai_mark_match(dai, substream, hw_params))412		return;413 414	if (dai->driver->ops &&415	    dai->driver->ops->hw_free)416		dai->driver->ops->hw_free(substream, dai);417 418	/* remove marked substream */419	soc_dai_mark_pop(dai, substream, hw_params);420}421 422int snd_soc_dai_startup(struct snd_soc_dai *dai,423			struct snd_pcm_substream *substream)424{425	int ret = 0;426 427	if (!snd_soc_dai_stream_valid(dai, substream->stream))428		return 0;429 430	if (dai->driver->ops &&431	    dai->driver->ops->startup)432		ret = dai->driver->ops->startup(substream, dai);433 434	/* mark substream if succeeded */435	if (ret == 0)436		soc_dai_mark_push(dai, substream, startup);437 438	return soc_dai_ret(dai, ret);439}440 441void snd_soc_dai_shutdown(struct snd_soc_dai *dai,442			  struct snd_pcm_substream *substream,443			  int rollback)444{445	if (!snd_soc_dai_stream_valid(dai, substream->stream))446		return;447 448	if (rollback && !soc_dai_mark_match(dai, substream, startup))449		return;450 451	if (dai->driver->ops &&452	    dai->driver->ops->shutdown)453		dai->driver->ops->shutdown(substream, dai);454 455	/* remove marked substream */456	soc_dai_mark_pop(dai, substream, startup);457}458 459int snd_soc_dai_compress_new(struct snd_soc_dai *dai,460			     struct snd_soc_pcm_runtime *rtd, int num)461{462	int ret = -ENOTSUPP;463	if (dai->driver->ops &&464	    dai->driver->ops->compress_new)465		ret = dai->driver->ops->compress_new(rtd, num);466	return soc_dai_ret(dai, ret);467}468 469/*470 * snd_soc_dai_stream_valid() - check if a DAI supports the given stream471 *472 * Returns true if the DAI supports the indicated stream type.473 */474bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int dir)475{476	const struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir);477 478	/* If the codec specifies any channels at all, it supports the stream */479	return stream->channels_min;480}481 482void snd_soc_dai_action(struct snd_soc_dai *dai,483			int stream, int action)484{485	/* see snd_soc_dai_stream_active() */486	dai->stream[stream].active	+= action;487 488	/* see snd_soc_component_active() */489	dai->component->active		+= action;490}491EXPORT_SYMBOL_GPL(snd_soc_dai_action);492 493int snd_soc_dai_active(const struct snd_soc_dai *dai)494{495	int stream, active;496 497	active = 0;498	for_each_pcm_streams(stream)499		active += dai->stream[stream].active;500 501	return active;502}503EXPORT_SYMBOL_GPL(snd_soc_dai_active);504 505int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order)506{507	struct snd_soc_dai *dai;508	int i;509 510	for_each_rtd_dais(rtd, i, dai) {511		if (dai->probed)512			continue;513 514		if (dai->driver->ops) {515			if (dai->driver->ops->probe_order != order)516				continue;517 518			if (dai->driver->ops->probe) {519				int ret = dai->driver->ops->probe(dai);520 521				if (ret < 0)522					return soc_dai_ret(dai, ret);523			}524		}525		dai->probed = 1;526	}527 528	return 0;529}530 531int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order)532{533	struct snd_soc_dai *dai;534	int i, r, ret = 0;535 536	for_each_rtd_dais(rtd, i, dai) {537		if (!dai->probed)538			continue;539 540		if (dai->driver->ops) {541			if (dai->driver->ops->remove_order != order)542				continue;543 544			if (dai->driver->ops->remove) {545				r = dai->driver->ops->remove(dai);546				if (r < 0)547					ret = r; /* use last error */548			}549		}550		dai->probed = 0;551	}552 553	return ret;554}555 556int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd)557{558	struct snd_soc_dai *dai;559	int i;560 561	for_each_rtd_dais(rtd, i, dai) {562		if (dai->driver->ops &&563		    dai->driver->ops->pcm_new) {564			int ret = dai->driver->ops->pcm_new(rtd, dai);565			if (ret < 0)566				return soc_dai_ret(dai, ret);567		}568	}569 570	return 0;571}572 573int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream)574{575	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);576	struct snd_soc_dai *dai;577	int i, ret;578 579	for_each_rtd_dais(rtd, i, dai) {580		if (!snd_soc_dai_stream_valid(dai, substream->stream))581			continue;582		if (dai->driver->ops &&583		    dai->driver->ops->prepare) {584			ret = dai->driver->ops->prepare(substream, dai);585			if (ret < 0)586				return soc_dai_ret(dai, ret);587		}588	}589 590	return 0;591}592 593static int soc_dai_trigger(struct snd_soc_dai *dai,594			   struct snd_pcm_substream *substream, int cmd)595{596	int ret = 0;597 598	if (!snd_soc_dai_stream_valid(dai, substream->stream))599		return 0;600 601	if (dai->driver->ops &&602	    dai->driver->ops->trigger)603		ret = dai->driver->ops->trigger(substream, cmd, dai);604 605	return soc_dai_ret(dai, ret);606}607 608int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream,609			    int cmd, int rollback)610{611	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);612	struct snd_soc_dai *dai;613	int i, r, ret = 0;614 615	switch (cmd) {616	case SNDRV_PCM_TRIGGER_START:617	case SNDRV_PCM_TRIGGER_RESUME:618	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:619		for_each_rtd_dais(rtd, i, dai) {620			ret = soc_dai_trigger(dai, substream, cmd);621			if (ret < 0)622				break;623 624			if (dai->driver->ops && dai->driver->ops->mute_unmute_on_trigger)625				snd_soc_dai_digital_mute(dai, 0, substream->stream);626 627			soc_dai_mark_push(dai, substream, trigger);628		}629		break;630	case SNDRV_PCM_TRIGGER_STOP:631	case SNDRV_PCM_TRIGGER_SUSPEND:632	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:633		for_each_rtd_dais(rtd, i, dai) {634			if (rollback && !soc_dai_mark_match(dai, substream, trigger))635				continue;636 637			if (dai->driver->ops && dai->driver->ops->mute_unmute_on_trigger)638				snd_soc_dai_digital_mute(dai, 1, substream->stream);639 640			r = soc_dai_trigger(dai, substream, cmd);641			if (r < 0)642				ret = r; /* use last ret */643			soc_dai_mark_pop(dai, substream, trigger);644		}645	}646 647	return ret;648}649 650void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,651			   snd_pcm_sframes_t *cpu_delay,652			   snd_pcm_sframes_t *codec_delay)653{654	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);655	struct snd_soc_dai *dai;656	int i;657 658	/*659	 * We're looking for the delay through the full audio path so it needs to660	 * be the maximum of the DAIs doing transmit and the maximum of the DAIs661	 * doing receive (ie, all CPUs and all CODECs) rather than just the maximum662	 * of all DAIs.663	 */664 665	/* for CPU */666	for_each_rtd_cpu_dais(rtd, i, dai)667		if (dai->driver->ops &&668		    dai->driver->ops->delay)669			*cpu_delay = max(*cpu_delay, dai->driver->ops->delay(substream, dai));670 671	/* for Codec */672	for_each_rtd_codec_dais(rtd, i, dai)673		if (dai->driver->ops &&674		    dai->driver->ops->delay)675			*codec_delay = max(*codec_delay, dai->driver->ops->delay(substream, dai));676}677 678int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,679			      struct snd_compr_stream *cstream)680{681	int ret = 0;682 683	if (dai->driver->cops &&684	    dai->driver->cops->startup)685		ret = dai->driver->cops->startup(cstream, dai);686 687	/* mark cstream if succeeded */688	if (ret == 0)689		soc_dai_mark_push(dai, cstream, compr_startup);690 691	return soc_dai_ret(dai, ret);692}693EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup);694 695void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai,696				struct snd_compr_stream *cstream,697				int rollback)698{699	if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup))700		return;701 702	if (dai->driver->cops &&703	    dai->driver->cops->shutdown)704		dai->driver->cops->shutdown(cstream, dai);705 706	/* remove marked cstream */707	soc_dai_mark_pop(dai, cstream, compr_startup);708}709EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown);710 711int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai,712			      struct snd_compr_stream *cstream, int cmd)713{714	int ret = 0;715 716	if (dai->driver->cops &&717	    dai->driver->cops->trigger)718		ret = dai->driver->cops->trigger(cstream, cmd, dai);719 720	return soc_dai_ret(dai, ret);721}722EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger);723 724int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai,725				 struct snd_compr_stream *cstream,726				 struct snd_compr_params *params)727{728	int ret = 0;729 730	if (dai->driver->cops &&731	    dai->driver->cops->set_params)732		ret = dai->driver->cops->set_params(cstream, params, dai);733 734	return soc_dai_ret(dai, ret);735}736EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params);737 738int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai,739				 struct snd_compr_stream *cstream,740				 struct snd_codec *params)741{742	int ret = 0;743 744	if (dai->driver->cops &&745	    dai->driver->cops->get_params)746		ret = dai->driver->cops->get_params(cstream, params, dai);747 748	return soc_dai_ret(dai, ret);749}750EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params);751 752int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,753			  struct snd_compr_stream *cstream,754			  size_t bytes)755{756	int ret = 0;757 758	if (dai->driver->cops &&759	    dai->driver->cops->ack)760		ret = dai->driver->cops->ack(cstream, bytes, dai);761 762	return soc_dai_ret(dai, ret);763}764EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack);765 766int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,767			      struct snd_compr_stream *cstream,768			      struct snd_compr_tstamp *tstamp)769{770	int ret = 0;771 772	if (dai->driver->cops &&773	    dai->driver->cops->pointer)774		ret = dai->driver->cops->pointer(cstream, tstamp, dai);775 776	return soc_dai_ret(dai, ret);777}778EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer);779 780int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,781				   struct snd_compr_stream *cstream,782				   struct snd_compr_metadata *metadata)783{784	int ret = 0;785 786	if (dai->driver->cops &&787	    dai->driver->cops->set_metadata)788		ret = dai->driver->cops->set_metadata(cstream, metadata, dai);789 790	return soc_dai_ret(dai, ret);791}792EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata);793 794int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,795				   struct snd_compr_stream *cstream,796				   struct snd_compr_metadata *metadata)797{798	int ret = 0;799 800	if (dai->driver->cops &&801	    dai->driver->cops->get_metadata)802		ret = dai->driver->cops->get_metadata(cstream, metadata, dai);803 804	return soc_dai_ret(dai, ret);805}806EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata);807