mirror of https://gitee.com/openkylin/linux.git
Merge remote-tracking branch 'asoc/topic/core' into asoc-next
This commit is contained in:
commit
da8ab21cfe
|
@ -2240,6 +2240,18 @@ int regmap_get_val_bytes(struct regmap *map)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
|
||||
|
||||
int regmap_parse_val(struct regmap *map, const void *buf,
|
||||
unsigned int *val)
|
||||
{
|
||||
if (!map->format.parse_val)
|
||||
return -EINVAL;
|
||||
|
||||
*val = map->format.parse_val(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_parse_val);
|
||||
|
||||
static int __init regmap_initcall(void)
|
||||
{
|
||||
regmap_debugfs_initcall();
|
||||
|
|
|
@ -423,6 +423,8 @@ bool regmap_check_range_table(struct regmap *map, unsigned int reg,
|
|||
|
||||
int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
|
||||
int num_regs);
|
||||
int regmap_parse_val(struct regmap *map, const void *buf,
|
||||
unsigned int *val);
|
||||
|
||||
static inline bool regmap_reg_in_range(unsigned int reg,
|
||||
const struct regmap_range *range)
|
||||
|
@ -695,6 +697,13 @@ static inline int regmap_register_patch(struct regmap *map,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int regmap_parse_val(struct regmap *map, const void *buf,
|
||||
unsigned int *val)
|
||||
{
|
||||
WARN_ONCE(1, "regmap API is disabled");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline struct regmap *dev_get_regmap(struct device *dev,
|
||||
const char *name)
|
||||
{
|
||||
|
|
|
@ -270,6 +270,7 @@ struct snd_soc_dai {
|
|||
/* parent platform/codec */
|
||||
struct snd_soc_platform *platform;
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_component *component;
|
||||
|
||||
struct snd_soc_card *card;
|
||||
|
||||
|
|
|
@ -413,6 +413,10 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
|
|||
struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
|
||||
const char *dai_link);
|
||||
|
||||
bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd);
|
||||
void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream);
|
||||
void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream);
|
||||
|
||||
/* Utility functions to get clock rates from various things */
|
||||
int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
|
||||
int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
|
||||
|
@ -656,12 +660,19 @@ struct snd_soc_component {
|
|||
const char *name;
|
||||
int id;
|
||||
struct device *dev;
|
||||
|
||||
unsigned int active;
|
||||
|
||||
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
|
||||
|
||||
struct list_head list;
|
||||
|
||||
struct snd_soc_dai_driver *dai_drv;
|
||||
int num_dai;
|
||||
|
||||
const struct snd_soc_component_driver *driver;
|
||||
|
||||
struct list_head dai_list;
|
||||
};
|
||||
|
||||
/* SoC Audio Codec device */
|
||||
|
@ -683,7 +694,6 @@ struct snd_soc_codec {
|
|||
|
||||
/* runtime */
|
||||
struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
|
||||
unsigned int active;
|
||||
unsigned int cache_bypass:1; /* Suppress access to the cache */
|
||||
unsigned int suspended:1; /* Codec is in suspend PM state */
|
||||
unsigned int probed:1; /* Codec has been probed */
|
||||
|
@ -709,7 +719,6 @@ struct snd_soc_codec {
|
|||
|
||||
/* dapm */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_codec_root;
|
||||
|
@ -1168,6 +1177,17 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static inline bool snd_soc_component_is_active(
|
||||
struct snd_soc_component *component)
|
||||
{
|
||||
return component->active != 0;
|
||||
}
|
||||
|
||||
static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec)
|
||||
{
|
||||
return snd_soc_component_is_active(&codec->component);
|
||||
}
|
||||
|
||||
int snd_soc_util_init(void);
|
||||
void snd_soc_util_exit(void);
|
||||
|
||||
|
|
|
@ -722,7 +722,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (!codec->active || !adav80x->rate)
|
||||
if (!snd_soc_codec_is_active(codec) || !adav80x->rate)
|
||||
return 0;
|
||||
|
||||
return snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
|
@ -735,7 +735,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (!codec->active)
|
||||
if (!snd_soc_codec_is_active(codec))
|
||||
adav80x->rate = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -400,7 +400,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
|
|||
struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
/* deactivate */
|
||||
if (!codec->active) {
|
||||
if (!snd_soc_codec_is_active(codec)) {
|
||||
udelay(50);
|
||||
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
|
||||
}
|
||||
|
|
|
@ -461,7 +461,7 @@ static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol,
|
|||
if (dac33->fifo_mode == ucontrol->value.integer.value[0])
|
||||
return 0;
|
||||
/* Do not allow changes while stream is running*/
|
||||
if (codec->active)
|
||||
if (snd_soc_codec_is_active(codec))
|
||||
return -EPERM;
|
||||
|
||||
if (ucontrol->value.integer.value[0] < 0 ||
|
||||
|
|
|
@ -108,7 +108,7 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
|
|||
/* the interpolator & decimator regs must only be written when the
|
||||
* codec DAI is active.
|
||||
*/
|
||||
if (!codec->active && (reg >= UDA1380_MVOL))
|
||||
if (!snd_soc_codec_is_active(codec) && (reg >= UDA1380_MVOL))
|
||||
return 0;
|
||||
pr_debug("uda1380: hw write %x val %x\n", reg, value);
|
||||
if (codec->hw_write(codec->control_data, data, 3) == 3) {
|
||||
|
|
|
@ -197,7 +197,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
|
|||
return 0;
|
||||
|
||||
/* Do not allow changes while stream is running */
|
||||
if (codec->active)
|
||||
if (snd_soc_codec_is_active(codec))
|
||||
return -EPERM;
|
||||
|
||||
if (ucontrol->value.integer.value[0] < 0 ||
|
||||
|
|
|
@ -201,7 +201,7 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_codec *codec = dai->codec;
|
||||
|
||||
/* deactivate */
|
||||
if (!codec->active) {
|
||||
if (!snd_soc_codec_is_active(codec)) {
|
||||
udelay(50);
|
||||
snd_soc_write(codec, WM8711_ACTIVE, 0x0);
|
||||
}
|
||||
|
|
|
@ -251,7 +251,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
|
|||
if (wm8753->dai_func == ucontrol->value.integer.value[0])
|
||||
return 0;
|
||||
|
||||
if (codec->active)
|
||||
if (snd_soc_codec_is_active(codec))
|
||||
return -EBUSY;
|
||||
|
||||
ioctl = snd_soc_read(codec, WM8753_IOCTL);
|
||||
|
@ -1314,7 +1314,7 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
|
|||
/* the digital mute covers the HiFi and Voice DAC's on the WM8753.
|
||||
* make sure we check if they are not both active when we mute */
|
||||
if (mute && wm8753->dai_func == 1) {
|
||||
if (!codec->active)
|
||||
if (!snd_soc_codec_is_active(codec))
|
||||
snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
|
||||
} else {
|
||||
if (mute)
|
||||
|
|
|
@ -96,8 +96,7 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec)
|
|||
{
|
||||
dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n",
|
||||
codec->name);
|
||||
if (!codec->reg_cache)
|
||||
return 0;
|
||||
|
||||
kfree(codec->reg_cache);
|
||||
codec->reg_cache = NULL;
|
||||
return 0;
|
||||
|
@ -117,8 +116,9 @@ int snd_soc_cache_read(struct snd_soc_codec *codec,
|
|||
return -EINVAL;
|
||||
|
||||
mutex_lock(&codec->cache_rw_mutex);
|
||||
*value = snd_soc_get_cache_val(codec->reg_cache, reg,
|
||||
codec->driver->reg_word_size);
|
||||
if (!ZERO_OR_NULL_PTR(codec->reg_cache))
|
||||
*value = snd_soc_get_cache_val(codec->reg_cache, reg,
|
||||
codec->driver->reg_word_size);
|
||||
mutex_unlock(&codec->cache_rw_mutex);
|
||||
|
||||
return 0;
|
||||
|
@ -136,8 +136,9 @@ int snd_soc_cache_write(struct snd_soc_codec *codec,
|
|||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
mutex_lock(&codec->cache_rw_mutex);
|
||||
snd_soc_set_cache_val(codec->reg_cache, reg, value,
|
||||
codec->driver->reg_word_size);
|
||||
if (!ZERO_OR_NULL_PTR(codec->reg_cache))
|
||||
snd_soc_set_cache_val(codec->reg_cache, reg, value,
|
||||
codec->driver->reg_word_size);
|
||||
mutex_unlock(&codec->cache_rw_mutex);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -30,8 +30,6 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
|
|||
{
|
||||
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
||||
|
@ -52,17 +50,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
|
|||
}
|
||||
}
|
||||
|
||||
if (cstream->direction == SND_COMPRESS_PLAYBACK) {
|
||||
cpu_dai->playback_active++;
|
||||
codec_dai->playback_active++;
|
||||
} else {
|
||||
cpu_dai->capture_active++;
|
||||
codec_dai->capture_active++;
|
||||
}
|
||||
|
||||
cpu_dai->active++;
|
||||
codec_dai->active++;
|
||||
rtd->codec->active++;
|
||||
snd_soc_runtime_activate(rtd, cstream->direction);
|
||||
|
||||
mutex_unlock(&rtd->pcm_mutex);
|
||||
|
||||
|
@ -81,8 +69,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
|
|||
struct snd_soc_pcm_runtime *fe = cstream->private_data;
|
||||
struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
|
||||
struct snd_soc_platform *platform = fe->platform;
|
||||
struct snd_soc_dai *cpu_dai = fe->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = fe->codec_dai;
|
||||
struct snd_soc_dpcm *dpcm;
|
||||
struct snd_soc_dapm_widget_list *list;
|
||||
int stream;
|
||||
|
@ -140,17 +126,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
|
|||
fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
|
||||
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
|
||||
|
||||
if (cstream->direction == SND_COMPRESS_PLAYBACK) {
|
||||
cpu_dai->playback_active++;
|
||||
codec_dai->playback_active++;
|
||||
} else {
|
||||
cpu_dai->capture_active++;
|
||||
codec_dai->capture_active++;
|
||||
}
|
||||
|
||||
cpu_dai->active++;
|
||||
codec_dai->active++;
|
||||
fe->codec->active++;
|
||||
snd_soc_runtime_activate(fe, stream);
|
||||
|
||||
mutex_unlock(&fe->card->mutex);
|
||||
|
||||
|
@ -202,24 +178,19 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
|
|||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
int stream;
|
||||
|
||||
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
||||
|
||||
if (cstream->direction == SND_COMPRESS_PLAYBACK) {
|
||||
cpu_dai->playback_active--;
|
||||
codec_dai->playback_active--;
|
||||
} else {
|
||||
cpu_dai->capture_active--;
|
||||
codec_dai->capture_active--;
|
||||
}
|
||||
if (cstream->direction == SND_COMPRESS_PLAYBACK)
|
||||
stream = SNDRV_PCM_STREAM_PLAYBACK;
|
||||
else
|
||||
stream = SNDRV_PCM_STREAM_CAPTURE;
|
||||
|
||||
snd_soc_runtime_deactivate(rtd, stream);
|
||||
|
||||
snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
|
||||
|
||||
cpu_dai->active--;
|
||||
codec_dai->active--;
|
||||
codec->active--;
|
||||
|
||||
if (!cpu_dai->active)
|
||||
cpu_dai->rate = 0;
|
||||
|
||||
|
@ -235,8 +206,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
|
|||
cpu_dai->runtime = NULL;
|
||||
|
||||
if (cstream->direction == SND_COMPRESS_PLAYBACK) {
|
||||
if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
|
||||
rtd->dai_link->ignore_pmdown_time) {
|
||||
if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
|
||||
snd_soc_dapm_stream_event(rtd,
|
||||
SNDRV_PCM_STREAM_PLAYBACK,
|
||||
SND_SOC_DAPM_STREAM_STOP);
|
||||
|
@ -261,26 +231,17 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)
|
|||
{
|
||||
struct snd_soc_pcm_runtime *fe = cstream->private_data;
|
||||
struct snd_soc_platform *platform = fe->platform;
|
||||
struct snd_soc_dai *cpu_dai = fe->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = fe->codec_dai;
|
||||
struct snd_soc_dpcm *dpcm;
|
||||
int stream, ret;
|
||||
|
||||
mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
|
||||
|
||||
if (cstream->direction == SND_COMPRESS_PLAYBACK) {
|
||||
if (cstream->direction == SND_COMPRESS_PLAYBACK)
|
||||
stream = SNDRV_PCM_STREAM_PLAYBACK;
|
||||
cpu_dai->playback_active--;
|
||||
codec_dai->playback_active--;
|
||||
} else {
|
||||
else
|
||||
stream = SNDRV_PCM_STREAM_CAPTURE;
|
||||
cpu_dai->capture_active--;
|
||||
codec_dai->capture_active--;
|
||||
}
|
||||
|
||||
cpu_dai->active--;
|
||||
codec_dai->active--;
|
||||
fe->codec->active--;
|
||||
snd_soc_runtime_deactivate(fe, stream);
|
||||
|
||||
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
|
|||
#endif
|
||||
|
||||
static DEFINE_MUTEX(client_mutex);
|
||||
static LIST_HEAD(dai_list);
|
||||
static LIST_HEAD(platform_list);
|
||||
static LIST_HEAD(codec_list);
|
||||
static LIST_HEAD(component_list);
|
||||
|
@ -370,18 +369,22 @@ static ssize_t dai_list_read_file(struct file *file, char __user *user_buf,
|
|||
{
|
||||
char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
ssize_t len, ret = 0;
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_dai *dai;
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
list_for_each_entry(dai, &dai_list, list) {
|
||||
len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", dai->name);
|
||||
if (len >= 0)
|
||||
ret += len;
|
||||
if (ret > PAGE_SIZE) {
|
||||
ret = PAGE_SIZE;
|
||||
break;
|
||||
list_for_each_entry(component, &component_list, list) {
|
||||
list_for_each_entry(dai, &component->dai_list, list) {
|
||||
len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
|
||||
dai->name);
|
||||
if (len >= 0)
|
||||
ret += len;
|
||||
if (ret > PAGE_SIZE) {
|
||||
ret = PAGE_SIZE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -855,6 +858,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
|
|||
{
|
||||
struct snd_soc_dai_link *dai_link = &card->dai_link[num];
|
||||
struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_platform *platform;
|
||||
struct snd_soc_dai *codec_dai, *cpu_dai;
|
||||
|
@ -863,18 +867,20 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
|
|||
dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num);
|
||||
|
||||
/* Find CPU DAI from registered DAIs*/
|
||||
list_for_each_entry(cpu_dai, &dai_list, list) {
|
||||
list_for_each_entry(component, &component_list, list) {
|
||||
if (dai_link->cpu_of_node &&
|
||||
(cpu_dai->dev->of_node != dai_link->cpu_of_node))
|
||||
component->dev->of_node != dai_link->cpu_of_node)
|
||||
continue;
|
||||
if (dai_link->cpu_name &&
|
||||
strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name))
|
||||
continue;
|
||||
if (dai_link->cpu_dai_name &&
|
||||
strcmp(cpu_dai->name, dai_link->cpu_dai_name))
|
||||
strcmp(dev_name(component->dev), dai_link->cpu_name))
|
||||
continue;
|
||||
list_for_each_entry(cpu_dai, &component->dai_list, list) {
|
||||
if (dai_link->cpu_dai_name &&
|
||||
strcmp(cpu_dai->name, dai_link->cpu_dai_name))
|
||||
continue;
|
||||
|
||||
rtd->cpu_dai = cpu_dai;
|
||||
rtd->cpu_dai = cpu_dai;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rtd->cpu_dai) {
|
||||
|
@ -899,12 +905,10 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
|
|||
* CODEC found, so find CODEC DAI from registered DAIs from
|
||||
* this CODEC
|
||||
*/
|
||||
list_for_each_entry(codec_dai, &dai_list, list) {
|
||||
if (codec->dev == codec_dai->dev &&
|
||||
!strcmp(codec_dai->name,
|
||||
dai_link->codec_dai_name)) {
|
||||
|
||||
list_for_each_entry(codec_dai, &codec->component.dai_list, list) {
|
||||
if (!strcmp(codec_dai->name, dai_link->codec_dai_name)) {
|
||||
rtd->codec_dai = codec_dai;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1128,12 +1132,8 @@ static int soc_probe_codec(struct snd_soc_card *card,
|
|||
driver->num_dapm_widgets);
|
||||
|
||||
/* Create DAPM widgets for each DAI stream */
|
||||
list_for_each_entry(dai, &dai_list, list) {
|
||||
if (dai->dev != codec->dev)
|
||||
continue;
|
||||
|
||||
list_for_each_entry(dai, &codec->component.dai_list, list)
|
||||
snd_soc_dapm_new_dai_widgets(&codec->dapm, dai);
|
||||
}
|
||||
|
||||
codec->dapm.idle_bias_off = driver->idle_bias_off;
|
||||
|
||||
|
@ -1180,6 +1180,7 @@ static int soc_probe_platform(struct snd_soc_card *card,
|
|||
{
|
||||
int ret = 0;
|
||||
const struct snd_soc_platform_driver *driver = platform->driver;
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_dai *dai;
|
||||
|
||||
platform->card = card;
|
||||
|
@ -1195,11 +1196,11 @@ static int soc_probe_platform(struct snd_soc_card *card,
|
|||
driver->dapm_widgets, driver->num_dapm_widgets);
|
||||
|
||||
/* Create DAPM widgets for each DAI stream */
|
||||
list_for_each_entry(dai, &dai_list, list) {
|
||||
if (dai->dev != platform->dev)
|
||||
list_for_each_entry(component, &component_list, list) {
|
||||
if (component->dev != platform->dev)
|
||||
continue;
|
||||
|
||||
snd_soc_dapm_new_dai_widgets(&platform->dapm, dai);
|
||||
list_for_each_entry(dai, &component->dai_list, list)
|
||||
snd_soc_dapm_new_dai_widgets(&platform->dapm, dai);
|
||||
}
|
||||
|
||||
platform->dapm.idle_bias_off = 1;
|
||||
|
@ -2818,7 +2819,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
|
|||
unsigned int mask = (1 << fls(max)) - 1;
|
||||
unsigned int invert = mc->invert;
|
||||
int err;
|
||||
bool type_2r = 0;
|
||||
bool type_2r = false;
|
||||
unsigned int val2 = 0;
|
||||
unsigned int val, val_mask;
|
||||
|
||||
|
@ -2836,7 +2837,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
|
|||
val |= val2 << rshift;
|
||||
} else {
|
||||
val2 = val2 << shift;
|
||||
type_2r = 1;
|
||||
type_2r = true;
|
||||
}
|
||||
}
|
||||
err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
|
||||
|
@ -3234,7 +3235,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
|
|||
struct soc_bytes *params = (void *)kcontrol->private_value;
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
int ret, len;
|
||||
unsigned int val;
|
||||
unsigned int val, mask;
|
||||
void *data;
|
||||
|
||||
if (!codec->using_regmap)
|
||||
|
@ -3264,12 +3265,36 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
|
|||
((u8 *)data)[0] |= val;
|
||||
break;
|
||||
case 2:
|
||||
((u16 *)data)[0] &= cpu_to_be16(~params->mask);
|
||||
((u16 *)data)[0] |= cpu_to_be16(val);
|
||||
mask = ~params->mask;
|
||||
ret = regmap_parse_val(codec->control_data,
|
||||
&mask, &mask);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
((u16 *)data)[0] &= mask;
|
||||
|
||||
ret = regmap_parse_val(codec->control_data,
|
||||
&val, &val);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
((u16 *)data)[0] |= val;
|
||||
break;
|
||||
case 4:
|
||||
((u32 *)data)[0] &= cpu_to_be32(~params->mask);
|
||||
((u32 *)data)[0] |= cpu_to_be32(val);
|
||||
mask = ~params->mask;
|
||||
ret = regmap_parse_val(codec->control_data,
|
||||
&mask, &mask);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
((u32 *)data)[0] &= mask;
|
||||
|
||||
ret = regmap_parse_val(codec->control_data,
|
||||
&val, &val);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
((u32 *)data)[0] |= val;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
@ -3626,7 +3651,7 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
|
|||
return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
|
||||
slots, slot_width);
|
||||
else
|
||||
return -EINVAL;
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
|
||||
|
||||
|
@ -3882,95 +3907,42 @@ static inline char *fmt_multiple_name(struct device *dev,
|
|||
}
|
||||
|
||||
/**
|
||||
* snd_soc_register_dai - Register a DAI with the ASoC core
|
||||
* snd_soc_unregister_dai - Unregister DAIs from the ASoC core
|
||||
*
|
||||
* @dai: DAI to register
|
||||
* @component: The component for which the DAIs should be unregistered
|
||||
*/
|
||||
static int snd_soc_register_dai(struct device *dev,
|
||||
struct snd_soc_dai_driver *dai_drv)
|
||||
static void snd_soc_unregister_dais(struct snd_soc_component *component)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_dai *dai;
|
||||
struct snd_soc_dai *dai, *_dai;
|
||||
|
||||
dev_dbg(dev, "ASoC: dai register %s\n", dev_name(dev));
|
||||
|
||||
dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
|
||||
if (dai == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* create DAI component name */
|
||||
dai->name = fmt_single_name(dev, &dai->id);
|
||||
if (dai->name == NULL) {
|
||||
list_for_each_entry_safe(dai, _dai, &component->dai_list, list) {
|
||||
dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n",
|
||||
dai->name);
|
||||
list_del(&dai->list);
|
||||
kfree(dai->name);
|
||||
kfree(dai);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dai->dev = dev;
|
||||
dai->driver = dai_drv;
|
||||
dai->dapm.dev = dev;
|
||||
if (!dai->driver->ops)
|
||||
dai->driver->ops = &null_dai_ops;
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
|
||||
list_for_each_entry(codec, &codec_list, list) {
|
||||
if (codec->dev == dev) {
|
||||
dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n",
|
||||
dai->name, codec->name);
|
||||
dai->codec = codec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dai->codec)
|
||||
dai->dapm.idle_bias_off = 1;
|
||||
|
||||
list_add(&dai->list, &dai_list);
|
||||
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_unregister_dai - Unregister a DAI from the ASoC core
|
||||
* snd_soc_register_dais - Register a DAI with the ASoC core
|
||||
*
|
||||
* @dai: DAI to unregister
|
||||
*/
|
||||
static void snd_soc_unregister_dai(struct device *dev)
|
||||
{
|
||||
struct snd_soc_dai *dai;
|
||||
|
||||
list_for_each_entry(dai, &dai_list, list) {
|
||||
if (dev == dai->dev)
|
||||
goto found;
|
||||
}
|
||||
return;
|
||||
|
||||
found:
|
||||
mutex_lock(&client_mutex);
|
||||
list_del(&dai->list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(dev, "ASoC: Unregistered DAI '%s'\n", dai->name);
|
||||
kfree(dai->name);
|
||||
kfree(dai);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_register_dais - Register multiple DAIs with the ASoC core
|
||||
*
|
||||
* @dai: Array of DAIs to register
|
||||
* @component: The component the DAIs are registered for
|
||||
* @codec: The CODEC that the DAIs are registered for, NULL if the component is
|
||||
* not a CODEC.
|
||||
* @dai_drv: DAI driver to use for the DAIs
|
||||
* @count: Number of DAIs
|
||||
* @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the
|
||||
* parent's name.
|
||||
*/
|
||||
static int snd_soc_register_dais(struct device *dev,
|
||||
struct snd_soc_dai_driver *dai_drv, size_t count)
|
||||
static int snd_soc_register_dais(struct snd_soc_component *component,
|
||||
struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv,
|
||||
size_t count, bool legacy_dai_naming)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
struct device *dev = component->dev;
|
||||
struct snd_soc_dai *dai;
|
||||
int i, ret = 0;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count);
|
||||
|
||||
|
@ -3982,69 +3954,53 @@ static int snd_soc_register_dais(struct device *dev,
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* create DAI component name */
|
||||
dai->name = fmt_multiple_name(dev, &dai_drv[i]);
|
||||
/*
|
||||
* Back in the old days when we still had component-less DAIs,
|
||||
* instead of having a static name, component-less DAIs would
|
||||
* inherit the name of the parent device so it is possible to
|
||||
* register multiple instances of the DAI. We still need to keep
|
||||
* the same naming style even though those DAIs are not
|
||||
* component-less anymore.
|
||||
*/
|
||||
if (count == 1 && legacy_dai_naming) {
|
||||
dai->name = fmt_single_name(dev, &dai->id);
|
||||
} else {
|
||||
dai->name = fmt_multiple_name(dev, &dai_drv[i]);
|
||||
if (dai_drv[i].id)
|
||||
dai->id = dai_drv[i].id;
|
||||
else
|
||||
dai->id = i;
|
||||
}
|
||||
if (dai->name == NULL) {
|
||||
kfree(dai);
|
||||
ret = -EINVAL;
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dai->component = component;
|
||||
dai->codec = codec;
|
||||
dai->dev = dev;
|
||||
dai->driver = &dai_drv[i];
|
||||
if (dai->driver->id)
|
||||
dai->id = dai->driver->id;
|
||||
else
|
||||
dai->id = i;
|
||||
dai->dapm.dev = dev;
|
||||
if (!dai->driver->ops)
|
||||
dai->driver->ops = &null_dai_ops;
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
|
||||
list_for_each_entry(codec, &codec_list, list) {
|
||||
if (codec->dev == dev) {
|
||||
dev_dbg(dev,
|
||||
"ASoC: Mapped DAI %s to CODEC %s\n",
|
||||
dai->name, codec->name);
|
||||
dai->codec = codec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dai->codec)
|
||||
dai->dapm.idle_bias_off = 1;
|
||||
|
||||
list_add(&dai->list, &dai_list);
|
||||
list_add(&dai->list, &component->dai_list);
|
||||
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(dai->dev, "ASoC: Registered DAI '%s'\n", dai->name);
|
||||
dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
for (i--; i >= 0; i--)
|
||||
snd_soc_unregister_dai(dev);
|
||||
snd_soc_unregister_dais(component);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
|
||||
*
|
||||
* @dai: Array of DAIs to unregister
|
||||
* @count: Number of DAIs
|
||||
*/
|
||||
static void snd_soc_unregister_dais(struct device *dev, size_t count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
snd_soc_unregister_dai(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_register_component - Register a component with the ASoC core
|
||||
*
|
||||
|
@ -4053,6 +4009,7 @@ static int
|
|||
__snd_soc_register_component(struct device *dev,
|
||||
struct snd_soc_component *cmpnt,
|
||||
const struct snd_soc_component_driver *cmpnt_drv,
|
||||
struct snd_soc_codec *codec,
|
||||
struct snd_soc_dai_driver *dai_drv,
|
||||
int num_dai, bool allow_single_dai)
|
||||
{
|
||||
|
@ -4075,20 +4032,10 @@ __snd_soc_register_component(struct device *dev,
|
|||
cmpnt->driver = cmpnt_drv;
|
||||
cmpnt->dai_drv = dai_drv;
|
||||
cmpnt->num_dai = num_dai;
|
||||
INIT_LIST_HEAD(&cmpnt->dai_list);
|
||||
|
||||
/*
|
||||
* snd_soc_register_dai() uses fmt_single_name(), and
|
||||
* snd_soc_register_dais() uses fmt_multiple_name()
|
||||
* for dai->name which is used for name based matching
|
||||
*
|
||||
* this function is used from cpu/codec.
|
||||
* allow_single_dai flag can ignore "codec" driver reworking
|
||||
* since it had been used snd_soc_register_dais(),
|
||||
*/
|
||||
if ((1 == num_dai) && allow_single_dai)
|
||||
ret = snd_soc_register_dai(dev, dai_drv);
|
||||
else
|
||||
ret = snd_soc_register_dais(dev, dai_drv, num_dai);
|
||||
ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai,
|
||||
allow_single_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
|
||||
goto error_component_name;
|
||||
|
@ -4121,7 +4068,9 @@ int snd_soc_register_component(struct device *dev,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return __snd_soc_register_component(dev, cmpnt, cmpnt_drv,
|
||||
cmpnt->ignore_pmdown_time = true;
|
||||
|
||||
return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL,
|
||||
dai_drv, num_dai, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_register_component);
|
||||
|
@ -4141,7 +4090,7 @@ void snd_soc_unregister_component(struct device *dev)
|
|||
return;
|
||||
|
||||
found:
|
||||
snd_soc_unregister_dais(dev, cmpnt->num_dai);
|
||||
snd_soc_unregister_dais(cmpnt);
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_del(&cmpnt->list);
|
||||
|
@ -4319,7 +4268,7 @@ int snd_soc_register_codec(struct device *dev,
|
|||
codec->volatile_register = codec_drv->volatile_register;
|
||||
codec->readable_register = codec_drv->readable_register;
|
||||
codec->writable_register = codec_drv->writable_register;
|
||||
codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time;
|
||||
codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;
|
||||
codec->dapm.bias_level = SND_SOC_BIAS_OFF;
|
||||
codec->dapm.dev = dev;
|
||||
codec->dapm.codec = codec;
|
||||
|
@ -4342,7 +4291,7 @@ int snd_soc_register_codec(struct device *dev,
|
|||
/* register component */
|
||||
ret = __snd_soc_register_component(dev, &codec->component,
|
||||
&codec_drv->component_driver,
|
||||
dai_drv, num_dai, false);
|
||||
codec, dai_drv, num_dai, false);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret);
|
||||
goto fail_codec_name;
|
||||
|
|
|
@ -34,6 +34,86 @@
|
|||
|
||||
#define DPCM_MAX_BE_USERS 8
|
||||
|
||||
/**
|
||||
* snd_soc_runtime_activate() - Increment active count for PCM runtime components
|
||||
* @rtd: ASoC PCM runtime that is activated
|
||||
* @stream: Direction of the PCM stream
|
||||
*
|
||||
* Increments the active count for all the DAIs and components attached to a PCM
|
||||
* runtime. Should typically be called when a stream is opened.
|
||||
*
|
||||
* Must be called with the rtd->pcm_mutex being held
|
||||
*/
|
||||
void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
|
||||
{
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
|
||||
lockdep_assert_held(&rtd->pcm_mutex);
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
cpu_dai->playback_active++;
|
||||
codec_dai->playback_active++;
|
||||
} else {
|
||||
cpu_dai->capture_active++;
|
||||
codec_dai->capture_active++;
|
||||
}
|
||||
|
||||
cpu_dai->active++;
|
||||
codec_dai->active++;
|
||||
cpu_dai->component->active++;
|
||||
codec_dai->component->active++;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components
|
||||
* @rtd: ASoC PCM runtime that is deactivated
|
||||
* @stream: Direction of the PCM stream
|
||||
*
|
||||
* Decrements the active count for all the DAIs and components attached to a PCM
|
||||
* runtime. Should typically be called when a stream is closed.
|
||||
*
|
||||
* Must be called with the rtd->pcm_mutex being held
|
||||
*/
|
||||
void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
|
||||
{
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
|
||||
lockdep_assert_held(&rtd->pcm_mutex);
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
cpu_dai->playback_active--;
|
||||
codec_dai->playback_active--;
|
||||
} else {
|
||||
cpu_dai->capture_active--;
|
||||
codec_dai->capture_active--;
|
||||
}
|
||||
|
||||
cpu_dai->active--;
|
||||
codec_dai->active--;
|
||||
cpu_dai->component->active--;
|
||||
codec_dai->component->active--;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay
|
||||
* @rtd: The ASoC PCM runtime that should be checked.
|
||||
*
|
||||
* This function checks whether the power down delay should be ignored for a
|
||||
* specific PCM runtime. Returns true if the delay is 0, if it the DAI link has
|
||||
* been configured to ignore the delay, or if none of the components benefits
|
||||
* from having the delay.
|
||||
*/
|
||||
bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time)
|
||||
return true;
|
||||
|
||||
return rtd->cpu_dai->component->ignore_pmdown_time &&
|
||||
rtd->codec_dai->component->ignore_pmdown_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_set_runtime_hwparams - set the runtime hardware parameters
|
||||
* @substream: the pcm substream
|
||||
|
@ -378,16 +458,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
|
|||
runtime->hw.rate_max);
|
||||
|
||||
dynamic:
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
cpu_dai->playback_active++;
|
||||
codec_dai->playback_active++;
|
||||
} else {
|
||||
cpu_dai->capture_active++;
|
||||
codec_dai->capture_active++;
|
||||
}
|
||||
cpu_dai->active++;
|
||||
codec_dai->active++;
|
||||
rtd->codec->active++;
|
||||
|
||||
snd_soc_runtime_activate(rtd, substream->stream);
|
||||
|
||||
mutex_unlock(&rtd->pcm_mutex);
|
||||
return 0;
|
||||
|
||||
|
@ -459,21 +532,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
|
|||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
|
||||
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
cpu_dai->playback_active--;
|
||||
codec_dai->playback_active--;
|
||||
} else {
|
||||
cpu_dai->capture_active--;
|
||||
codec_dai->capture_active--;
|
||||
}
|
||||
|
||||
cpu_dai->active--;
|
||||
codec_dai->active--;
|
||||
codec->active--;
|
||||
snd_soc_runtime_deactivate(rtd, substream->stream);
|
||||
|
||||
/* clear the corresponding DAIs rate when inactive */
|
||||
if (!cpu_dai->active)
|
||||
|
@ -496,8 +558,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
|
|||
cpu_dai->runtime = NULL;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
|
||||
rtd->dai_link->ignore_pmdown_time) {
|
||||
if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
|
||||
/* powered down playback stream now */
|
||||
snd_soc_dapm_stream_event(rtd,
|
||||
SNDRV_PCM_STREAM_PLAYBACK,
|
||||
|
|
Loading…
Reference in New Issue