mirror of
https://github.com/torvalds/linux.git
synced 2024-11-05 19:41:54 +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
|
#ifndef __LINUX_SND_SOC_H
|
||||||
#define __LINUX_SND_SOC_H
|
#define __LINUX_SND_SOC_H
|
||||||
|
|
||||||
|
#include <linux/of.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
@ -670,6 +671,26 @@ struct snd_soc_cache_ops {
|
|||||||
int (*sync)(struct snd_soc_codec *codec);
|
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 */
|
/* SoC Audio Codec device */
|
||||||
struct snd_soc_codec {
|
struct snd_soc_codec {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -715,6 +736,9 @@ struct snd_soc_codec {
|
|||||||
struct mutex cache_rw_mutex;
|
struct mutex cache_rw_mutex;
|
||||||
int val_bytes;
|
int val_bytes;
|
||||||
|
|
||||||
|
/* component */
|
||||||
|
struct snd_soc_component component;
|
||||||
|
|
||||||
/* dapm */
|
/* dapm */
|
||||||
struct snd_soc_dapm_context dapm;
|
struct snd_soc_dapm_context dapm;
|
||||||
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
|
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 (*remove)(struct snd_soc_codec *);
|
||||||
int (*suspend)(struct snd_soc_codec *);
|
int (*suspend)(struct snd_soc_codec *);
|
||||||
int (*resume)(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 */
|
/* Default control and setup, added after probe() is run */
|
||||||
const struct snd_kcontrol_new *controls;
|
const struct snd_kcontrol_new *controls;
|
||||||
@ -849,20 +874,6 @@ struct snd_soc_platform {
|
|||||||
#endif
|
#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 {
|
struct snd_soc_dai_link {
|
||||||
/* config - must be set by machine driver */
|
/* config - must be set by machine driver */
|
||||||
const char *name; /* Codec name */
|
const char *name; /* Codec name */
|
||||||
@ -1201,6 +1212,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
|
|||||||
const char *propname);
|
const char *propname);
|
||||||
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
|
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
|
||||||
const char *prefix);
|
const char *prefix);
|
||||||
|
int snd_soc_of_get_dai_name(struct device_node *of_node,
|
||||||
|
const char **dai_name);
|
||||||
|
|
||||||
#include <sound/soc-dai.h>
|
#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_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
|
* snd_soc_add_platform - Add a platform to the ASoC core
|
||||||
* @dev: The parent device for the platform
|
* @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);
|
list_add(&codec->list, &codec_list);
|
||||||
mutex_unlock(&client_mutex);
|
mutex_unlock(&client_mutex);
|
||||||
|
|
||||||
/* register any DAIs */
|
/* register component */
|
||||||
ret = snd_soc_register_dais(dev, dai_drv, num_dai);
|
ret = __snd_soc_register_component(dev, &codec->component,
|
||||||
|
&codec_drv->component_driver,
|
||||||
|
dai_drv, num_dai, false);
|
||||||
if (ret < 0) {
|
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;
|
goto fail_codec_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4295,7 +4403,7 @@ void snd_soc_unregister_codec(struct device *dev)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
snd_soc_unregister_dais(dev, codec->num_dai);
|
snd_soc_unregister_component(dev);
|
||||||
|
|
||||||
mutex_lock(&client_mutex);
|
mutex_lock(&client_mutex);
|
||||||
list_del(&codec->list);
|
list_del(&codec->list);
|
||||||
@ -4310,92 +4418,6 @@ found:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
|
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 */
|
/* Retrieve a card's name from device tree */
|
||||||
int snd_soc_of_parse_card_name(struct snd_soc_card *card,
|
int snd_soc_of_parse_card_name(struct snd_soc_card *card,
|
||||||
const char *propname)
|
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);
|
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)
|
static int __init snd_soc_init(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
Loading…
Reference in New Issue
Block a user