cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

soc-link.c (5750B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// soc-link.c
      4//
      5// Copyright (C) 2019 Renesas Electronics Corp.
      6// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
      7//
      8#include <sound/soc.h>
      9#include <sound/soc-link.h>
     10
     11#define soc_link_ret(rtd, ret) _soc_link_ret(rtd, __func__, ret)
     12static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd,
     13				const char *func, int ret)
     14{
     15	/* Positive, Zero values are not errors */
     16	if (ret >= 0)
     17		return ret;
     18
     19	/* Negative values might be errors */
     20	switch (ret) {
     21	case -EPROBE_DEFER:
     22	case -ENOTSUPP:
     23		break;
     24	default:
     25		dev_err(rtd->dev,
     26			"ASoC: error at %s on %s: %d\n",
     27			func, rtd->dai_link->name, ret);
     28	}
     29
     30	return ret;
     31}
     32
     33/*
     34 * We might want to check substream by using list.
     35 * In such case, we can update these macros.
     36 */
     37#define soc_link_mark_push(rtd, substream, tgt)		((rtd)->mark_##tgt = substream)
     38#define soc_link_mark_pop(rtd, substream, tgt)		((rtd)->mark_##tgt = NULL)
     39#define soc_link_mark_match(rtd, substream, tgt)	((rtd)->mark_##tgt == substream)
     40
     41int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd)
     42{
     43	int ret = 0;
     44
     45	if (rtd->dai_link->init)
     46		ret = rtd->dai_link->init(rtd);
     47
     48	return soc_link_ret(rtd, ret);
     49}
     50
     51void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd)
     52{
     53	if (rtd->dai_link->exit)
     54		rtd->dai_link->exit(rtd);
     55}
     56
     57int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
     58				    struct snd_pcm_hw_params *params)
     59{
     60	int ret = 0;
     61
     62	if (rtd->dai_link->be_hw_params_fixup)
     63		ret = rtd->dai_link->be_hw_params_fixup(rtd, params);
     64
     65	return soc_link_ret(rtd, ret);
     66}
     67
     68int snd_soc_link_startup(struct snd_pcm_substream *substream)
     69{
     70	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
     71	int ret = 0;
     72
     73	if (rtd->dai_link->ops &&
     74	    rtd->dai_link->ops->startup)
     75		ret = rtd->dai_link->ops->startup(substream);
     76
     77	/* mark substream if succeeded */
     78	if (ret == 0)
     79		soc_link_mark_push(rtd, substream, startup);
     80
     81	return soc_link_ret(rtd, ret);
     82}
     83
     84void snd_soc_link_shutdown(struct snd_pcm_substream *substream,
     85			   int rollback)
     86{
     87	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
     88
     89	if (rollback && !soc_link_mark_match(rtd, substream, startup))
     90		return;
     91
     92	if (rtd->dai_link->ops &&
     93	    rtd->dai_link->ops->shutdown)
     94		rtd->dai_link->ops->shutdown(substream);
     95
     96	/* remove marked substream */
     97	soc_link_mark_pop(rtd, substream, startup);
     98}
     99
    100int snd_soc_link_prepare(struct snd_pcm_substream *substream)
    101{
    102	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    103	int ret = 0;
    104
    105	if (rtd->dai_link->ops &&
    106	    rtd->dai_link->ops->prepare)
    107		ret = rtd->dai_link->ops->prepare(substream);
    108
    109	return soc_link_ret(rtd, ret);
    110}
    111
    112int snd_soc_link_hw_params(struct snd_pcm_substream *substream,
    113			   struct snd_pcm_hw_params *params)
    114{
    115	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    116	int ret = 0;
    117
    118	if (rtd->dai_link->ops &&
    119	    rtd->dai_link->ops->hw_params)
    120		ret = rtd->dai_link->ops->hw_params(substream, params);
    121
    122	/* mark substream if succeeded */
    123	if (ret == 0)
    124		soc_link_mark_push(rtd, substream, hw_params);
    125
    126	return soc_link_ret(rtd, ret);
    127}
    128
    129void snd_soc_link_hw_free(struct snd_pcm_substream *substream, int rollback)
    130{
    131	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    132
    133	if (rollback && !soc_link_mark_match(rtd, substream, hw_params))
    134		return;
    135
    136	if (rtd->dai_link->ops &&
    137	    rtd->dai_link->ops->hw_free)
    138		rtd->dai_link->ops->hw_free(substream);
    139
    140	/* remove marked substream */
    141	soc_link_mark_pop(rtd, substream, hw_params);
    142}
    143
    144static int soc_link_trigger(struct snd_pcm_substream *substream, int cmd)
    145{
    146	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    147	int ret = 0;
    148
    149	if (rtd->dai_link->ops &&
    150	    rtd->dai_link->ops->trigger)
    151		ret = rtd->dai_link->ops->trigger(substream, cmd);
    152
    153	return soc_link_ret(rtd, ret);
    154}
    155
    156int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd,
    157			 int rollback)
    158{
    159	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    160	int ret = 0;
    161
    162	switch (cmd) {
    163	case SNDRV_PCM_TRIGGER_START:
    164	case SNDRV_PCM_TRIGGER_RESUME:
    165	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    166		ret = soc_link_trigger(substream, cmd);
    167		if (ret < 0)
    168			break;
    169		soc_link_mark_push(rtd, substream, trigger);
    170		break;
    171	case SNDRV_PCM_TRIGGER_STOP:
    172	case SNDRV_PCM_TRIGGER_SUSPEND:
    173	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    174		if (rollback && !soc_link_mark_match(rtd, substream, trigger))
    175			break;
    176
    177		ret = soc_link_trigger(substream, cmd);
    178		soc_link_mark_pop(rtd, substream, startup);
    179	}
    180
    181	return ret;
    182}
    183
    184int snd_soc_link_compr_startup(struct snd_compr_stream *cstream)
    185{
    186	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
    187	int ret = 0;
    188
    189	if (rtd->dai_link->compr_ops &&
    190	    rtd->dai_link->compr_ops->startup)
    191		ret = rtd->dai_link->compr_ops->startup(cstream);
    192
    193	if (ret == 0)
    194		soc_link_mark_push(rtd, cstream, compr_startup);
    195
    196	return soc_link_ret(rtd, ret);
    197}
    198EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup);
    199
    200void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream,
    201				 int rollback)
    202{
    203	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
    204
    205	if (rollback && !soc_link_mark_match(rtd, cstream, compr_startup))
    206		return;
    207
    208	if (rtd->dai_link->compr_ops &&
    209	    rtd->dai_link->compr_ops->shutdown)
    210		rtd->dai_link->compr_ops->shutdown(cstream);
    211
    212	soc_link_mark_pop(rtd, cstream, compr_startup);
    213}
    214EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown);
    215
    216int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream)
    217{
    218	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
    219	int ret = 0;
    220
    221	if (rtd->dai_link->compr_ops &&
    222	    rtd->dai_link->compr_ops->set_params)
    223		ret = rtd->dai_link->compr_ops->set_params(cstream);
    224
    225	return soc_link_ret(rtd, ret);
    226}
    227EXPORT_SYMBOL_GPL(snd_soc_link_compr_set_params);