mirror of
https://github.com/torvalds/linux.git
synced 2024-11-05 11:32:04 +00:00
Merge remote-tracking branch 'asoc/topic/component' into asoc-next
This commit is contained in:
commit
6180561670
@ -13,6 +13,7 @@
|
||||
#ifndef __LINUX_SND_SOC_H
|
||||
#define __LINUX_SND_SOC_H
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/notifier.h>
|
||||
@ -670,6 +671,26 @@ struct snd_soc_cache_ops {
|
||||
int (*sync)(struct snd_soc_codec *codec);
|
||||
};
|
||||
|
||||
/* component interface */
|
||||
struct snd_soc_component_driver {
|
||||
const char *name;
|
||||
|
||||
/* DT */
|
||||
int (*of_xlate_dai_name)(struct snd_soc_component *component,
|
||||
struct of_phandle_args *args,
|
||||
const char **dai_name);
|
||||
};
|
||||
|
||||
struct snd_soc_component {
|
||||
const char *name;
|
||||
int id;
|
||||
int num_dai;
|
||||
struct device *dev;
|
||||
struct list_head list;
|
||||
|
||||
const struct snd_soc_component_driver *driver;
|
||||
};
|
||||
|
||||
/* SoC Audio Codec device */
|
||||
struct snd_soc_codec {
|
||||
const char *name;
|
||||
@ -715,6 +736,9 @@ struct snd_soc_codec {
|
||||
struct mutex cache_rw_mutex;
|
||||
int val_bytes;
|
||||
|
||||
/* component */
|
||||
struct snd_soc_component component;
|
||||
|
||||
/* dapm */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
|
||||
@ -733,6 +757,7 @@ struct snd_soc_codec_driver {
|
||||
int (*remove)(struct snd_soc_codec *);
|
||||
int (*suspend)(struct snd_soc_codec *);
|
||||
int (*resume)(struct snd_soc_codec *);
|
||||
struct snd_soc_component_driver component_driver;
|
||||
|
||||
/* Default control and setup, added after probe() is run */
|
||||
const struct snd_kcontrol_new *controls;
|
||||
@ -849,20 +874,6 @@ struct snd_soc_platform {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct snd_soc_component_driver {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct snd_soc_component {
|
||||
const char *name;
|
||||
int id;
|
||||
int num_dai;
|
||||
struct device *dev;
|
||||
struct list_head list;
|
||||
|
||||
const struct snd_soc_component_driver *driver;
|
||||
};
|
||||
|
||||
struct snd_soc_dai_link {
|
||||
/* config - must be set by machine driver */
|
||||
const char *name; /* Codec name */
|
||||
@ -1201,6 +1212,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
|
||||
const char *propname);
|
||||
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
|
||||
const char *prefix);
|
||||
int snd_soc_of_get_dai_name(struct device_node *of_node,
|
||||
const char **dai_name);
|
||||
|
||||
#include <sound/soc-dai.h>
|
||||
|
||||
|
@ -4035,6 +4035,112 @@ static void snd_soc_unregister_dais(struct device *dev, size_t count)
|
||||
snd_soc_unregister_dai(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_register_component - Register a component with the ASoC core
|
||||
*
|
||||
*/
|
||||
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_dai_driver *dai_drv,
|
||||
int num_dai, bool allow_single_dai)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "component register %s\n", dev_name(dev));
|
||||
|
||||
if (!cmpnt) {
|
||||
dev_err(dev, "ASoC: Failed to connecting component\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmpnt->name = fmt_single_name(dev, &cmpnt->id);
|
||||
if (!cmpnt->name) {
|
||||
dev_err(dev, "ASoC: Failed to simplifying name\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmpnt->dev = dev;
|
||||
cmpnt->driver = cmpnt_drv;
|
||||
cmpnt->num_dai = num_dai;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
|
||||
goto error_component_name;
|
||||
}
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_add(&cmpnt->list, &component_list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
|
||||
|
||||
return ret;
|
||||
|
||||
error_component_name:
|
||||
kfree(cmpnt->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int snd_soc_register_component(struct device *dev,
|
||||
const struct snd_soc_component_driver *cmpnt_drv,
|
||||
struct snd_soc_dai_driver *dai_drv,
|
||||
int num_dai)
|
||||
{
|
||||
struct snd_soc_component *cmpnt;
|
||||
|
||||
cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
|
||||
if (!cmpnt) {
|
||||
dev_err(dev, "ASoC: Failed to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return __snd_soc_register_component(dev, cmpnt, cmpnt_drv,
|
||||
dai_drv, num_dai, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_register_component);
|
||||
|
||||
/**
|
||||
* snd_soc_unregister_component - Unregister a component from the ASoC core
|
||||
*
|
||||
*/
|
||||
void snd_soc_unregister_component(struct device *dev)
|
||||
{
|
||||
struct snd_soc_component *cmpnt;
|
||||
|
||||
list_for_each_entry(cmpnt, &component_list, list) {
|
||||
if (dev == cmpnt->dev)
|
||||
goto found;
|
||||
}
|
||||
return;
|
||||
|
||||
found:
|
||||
snd_soc_unregister_dais(dev, cmpnt->num_dai);
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_del(&cmpnt->list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
|
||||
kfree(cmpnt->name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
|
||||
|
||||
/**
|
||||
* snd_soc_add_platform - Add a platform to the ASoC core
|
||||
* @dev: The parent device for the platform
|
||||
@ -4257,10 +4363,12 @@ int snd_soc_register_codec(struct device *dev,
|
||||
list_add(&codec->list, &codec_list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
/* register any DAIs */
|
||||
ret = snd_soc_register_dais(dev, dai_drv, num_dai);
|
||||
/* register component */
|
||||
ret = __snd_soc_register_component(dev, &codec->component,
|
||||
&codec_drv->component_driver,
|
||||
dai_drv, num_dai, false);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret);
|
||||
dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret);
|
||||
goto fail_codec_name;
|
||||
}
|
||||
|
||||
@ -4295,7 +4403,7 @@ void snd_soc_unregister_codec(struct device *dev)
|
||||
return;
|
||||
|
||||
found:
|
||||
snd_soc_unregister_dais(dev, codec->num_dai);
|
||||
snd_soc_unregister_component(dev);
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_del(&codec->list);
|
||||
@ -4310,92 +4418,6 @@ found:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
|
||||
|
||||
|
||||
/**
|
||||
* snd_soc_register_component - Register a component with the ASoC core
|
||||
*
|
||||
*/
|
||||
int snd_soc_register_component(struct device *dev,
|
||||
const struct snd_soc_component_driver *cmpnt_drv,
|
||||
struct snd_soc_dai_driver *dai_drv,
|
||||
int num_dai)
|
||||
{
|
||||
struct snd_soc_component *cmpnt;
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "component register %s\n", dev_name(dev));
|
||||
|
||||
cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
|
||||
if (!cmpnt) {
|
||||
dev_err(dev, "ASoC: Failed to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmpnt->name = fmt_single_name(dev, &cmpnt->id);
|
||||
if (!cmpnt->name) {
|
||||
dev_err(dev, "ASoC: Failed to simplifying name\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmpnt->dev = dev;
|
||||
cmpnt->driver = cmpnt_drv;
|
||||
cmpnt->num_dai = num_dai;
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
if (1 == num_dai)
|
||||
ret = snd_soc_register_dai(dev, dai_drv);
|
||||
else
|
||||
ret = snd_soc_register_dais(dev, dai_drv, num_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
|
||||
goto error_component_name;
|
||||
}
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_add(&cmpnt->list, &component_list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
|
||||
|
||||
return ret;
|
||||
|
||||
error_component_name:
|
||||
kfree(cmpnt->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_register_component);
|
||||
|
||||
/**
|
||||
* snd_soc_unregister_component - Unregister a component from the ASoC core
|
||||
*
|
||||
*/
|
||||
void snd_soc_unregister_component(struct device *dev)
|
||||
{
|
||||
struct snd_soc_component *cmpnt;
|
||||
|
||||
list_for_each_entry(cmpnt, &component_list, list) {
|
||||
if (dev == cmpnt->dev)
|
||||
goto found;
|
||||
}
|
||||
return;
|
||||
|
||||
found:
|
||||
snd_soc_unregister_dais(dev, cmpnt->num_dai);
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_del(&cmpnt->list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
|
||||
kfree(cmpnt->name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
|
||||
|
||||
/* Retrieve a card's name from device tree */
|
||||
int snd_soc_of_parse_card_name(struct snd_soc_card *card,
|
||||
const char *propname)
|
||||
@ -4583,6 +4605,41 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
|
||||
|
||||
int snd_soc_of_get_dai_name(struct device_node *of_node,
|
||||
const char **dai_name)
|
||||
{
|
||||
struct snd_soc_component *pos;
|
||||
struct of_phandle_args args;
|
||||
int ret;
|
||||
|
||||
ret = of_parse_phandle_with_args(of_node, "sound-dai",
|
||||
"#sound-dai-cells", 0, &args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = -EPROBE_DEFER;
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_for_each_entry(pos, &component_list, list) {
|
||||
if (pos->dev->of_node != args.np)
|
||||
continue;
|
||||
|
||||
if (!pos->driver->of_xlate_dai_name) {
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
of_node_put(args.np);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name);
|
||||
|
||||
static int __init snd_soc_init(void)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
Loading…
Reference in New Issue
Block a user