mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Current ASoC is supporting snd_soc_dai_link_component for binding,
it is more useful than current legacy style.
Currently only codec is supporting it as multicodec (= codecs).
CPU will support multi style in the future.
We want to have it on Platform too in the future.
If all Codec/CPU/Platform are replaced into snd_soc_dai_link_component
style, we can remove legacy complex style.
This patch supports snd_soc_dai_link_component style
for simple_card_utils for codec.
[current]
struct snd_soc_dai_link {
	...
	*cpu_name;
	*cpu_of_node;
	*cpu_dai_name;
	*codec_name;
	*codec_of_node;
	*codec_dai_name;
	*codecs;
	num_codecs;
	*platform_name;
	*platform_of_node;
	...
}
[in the future]
struct snd_soc_dai_link {
	...
	*cpus
	num_cpus;
	*codecs;
	num_codecs;
	*platform;
	...
}
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
		
	
			
		
			
				
	
	
		
			519 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			519 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0
 | 
						|
//
 | 
						|
// simple-card-utils.c
 | 
						|
//
 | 
						|
// Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 | 
						|
 | 
						|
#include <linux/clk.h>
 | 
						|
#include <linux/gpio.h>
 | 
						|
#include <linux/gpio/consumer.h>
 | 
						|
#include <linux/module.h>
 | 
						|
#include <linux/of.h>
 | 
						|
#include <linux/of_gpio.h>
 | 
						|
#include <linux/of_graph.h>
 | 
						|
#include <sound/jack.h>
 | 
						|
#include <sound/simple_card_utils.h>
 | 
						|
 | 
						|
void asoc_simple_card_convert_fixup(struct asoc_simple_card_data *data,
 | 
						|
				    struct snd_pcm_hw_params *params)
 | 
						|
{
 | 
						|
	struct snd_interval *rate = hw_param_interval(params,
 | 
						|
						SNDRV_PCM_HW_PARAM_RATE);
 | 
						|
	struct snd_interval *channels = hw_param_interval(params,
 | 
						|
						SNDRV_PCM_HW_PARAM_CHANNELS);
 | 
						|
 | 
						|
	if (data->convert_rate)
 | 
						|
		rate->min =
 | 
						|
		rate->max = data->convert_rate;
 | 
						|
 | 
						|
	if (data->convert_channels)
 | 
						|
		channels->min =
 | 
						|
		channels->max = data->convert_channels;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_convert_fixup);
 | 
						|
 | 
						|
void asoc_simple_card_parse_convert(struct device *dev, char *prefix,
 | 
						|
				    struct asoc_simple_card_data *data)
 | 
						|
{
 | 
						|
	struct device_node *np = dev->of_node;
 | 
						|
	char prop[128];
 | 
						|
 | 
						|
	if (!prefix)
 | 
						|
		prefix = "";
 | 
						|
 | 
						|
	/* sampling rate convert */
 | 
						|
	snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-rate");
 | 
						|
	of_property_read_u32(np, prop, &data->convert_rate);
 | 
						|
 | 
						|
	/* channels transfer */
 | 
						|
	snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-channels");
 | 
						|
	of_property_read_u32(np, prop, &data->convert_channels);
 | 
						|
 | 
						|
	dev_dbg(dev, "convert_rate     %d\n", data->convert_rate);
 | 
						|
	dev_dbg(dev, "convert_channels %d\n", data->convert_channels);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_convert);
 | 
						|
 | 
						|
int asoc_simple_card_parse_daifmt(struct device *dev,
 | 
						|
				  struct device_node *node,
 | 
						|
				  struct device_node *codec,
 | 
						|
				  char *prefix,
 | 
						|
				  unsigned int *retfmt)
 | 
						|
{
 | 
						|
	struct device_node *bitclkmaster = NULL;
 | 
						|
	struct device_node *framemaster = NULL;
 | 
						|
	unsigned int daifmt;
 | 
						|
 | 
						|
	daifmt = snd_soc_of_parse_daifmt(node, prefix,
 | 
						|
					 &bitclkmaster, &framemaster);
 | 
						|
	daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
 | 
						|
 | 
						|
	if (!bitclkmaster && !framemaster) {
 | 
						|
		/*
 | 
						|
		 * No dai-link level and master setting was not found from
 | 
						|
		 * sound node level, revert back to legacy DT parsing and
 | 
						|
		 * take the settings from codec node.
 | 
						|
		 */
 | 
						|
		dev_dbg(dev, "Revert to legacy daifmt parsing\n");
 | 
						|
 | 
						|
		daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
 | 
						|
			(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
 | 
						|
	} else {
 | 
						|
		if (codec == bitclkmaster)
 | 
						|
			daifmt |= (codec == framemaster) ?
 | 
						|
				SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
 | 
						|
		else
 | 
						|
			daifmt |= (codec == framemaster) ?
 | 
						|
				SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
 | 
						|
	}
 | 
						|
 | 
						|
	of_node_put(bitclkmaster);
 | 
						|
	of_node_put(framemaster);
 | 
						|
 | 
						|
	*retfmt = daifmt;
 | 
						|
 | 
						|
	dev_dbg(dev, "format : %04x\n", daifmt);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_daifmt);
 | 
						|
 | 
						|
int asoc_simple_card_set_dailink_name(struct device *dev,
 | 
						|
				      struct snd_soc_dai_link *dai_link,
 | 
						|
				      const char *fmt, ...)
 | 
						|
{
 | 
						|
	va_list ap;
 | 
						|
	char *name = NULL;
 | 
						|
	int ret = -ENOMEM;
 | 
						|
 | 
						|
	va_start(ap, fmt);
 | 
						|
	name = devm_kvasprintf(dev, GFP_KERNEL, fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	if (name) {
 | 
						|
		ret = 0;
 | 
						|
 | 
						|
		dai_link->name		= name;
 | 
						|
		dai_link->stream_name	= name;
 | 
						|
 | 
						|
		dev_dbg(dev, "name : %s\n", name);
 | 
						|
	}
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_set_dailink_name);
 | 
						|
 | 
						|
int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
 | 
						|
				     char *prefix)
 | 
						|
{
 | 
						|
	int ret;
 | 
						|
 | 
						|
	if (!prefix)
 | 
						|
		prefix = "";
 | 
						|
 | 
						|
	/* Parse the card name from DT */
 | 
						|
	ret = snd_soc_of_parse_card_name(card, "label");
 | 
						|
	if (ret < 0 || !card->name) {
 | 
						|
		char prop[128];
 | 
						|
 | 
						|
		snprintf(prop, sizeof(prop), "%sname", prefix);
 | 
						|
		ret = snd_soc_of_parse_card_name(card, prop);
 | 
						|
		if (ret < 0)
 | 
						|
			return ret;
 | 
						|
	}
 | 
						|
 | 
						|
	if (!card->name && card->dai_link)
 | 
						|
		card->name = card->dai_link->name;
 | 
						|
 | 
						|
	dev_dbg(card->dev, "Card Name: %s\n", card->name ? card->name : "");
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name);
 | 
						|
 | 
						|
static void asoc_simple_card_clk_register(struct asoc_simple_dai *dai,
 | 
						|
					  struct clk *clk)
 | 
						|
{
 | 
						|
	dai->clk = clk;
 | 
						|
}
 | 
						|
 | 
						|
int asoc_simple_card_clk_enable(struct asoc_simple_dai *dai)
 | 
						|
{
 | 
						|
	return clk_prepare_enable(dai->clk);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_clk_enable);
 | 
						|
 | 
						|
void asoc_simple_card_clk_disable(struct asoc_simple_dai *dai)
 | 
						|
{
 | 
						|
	clk_disable_unprepare(dai->clk);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_clk_disable);
 | 
						|
 | 
						|
int asoc_simple_card_parse_clk(struct device *dev,
 | 
						|
			       struct device_node *node,
 | 
						|
			       struct device_node *dai_of_node,
 | 
						|
			       struct asoc_simple_dai *simple_dai,
 | 
						|
			       const char *dai_name,
 | 
						|
			       struct snd_soc_dai_link_component *dlc)
 | 
						|
{
 | 
						|
	struct clk *clk;
 | 
						|
	u32 val;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Use snd_soc_dai_link_component instead of legacy style.
 | 
						|
	 * It is only for codec, but cpu will be supported in the future.
 | 
						|
	 * see
 | 
						|
	 *	soc-core.c :: snd_soc_init_multicodec()
 | 
						|
	 */
 | 
						|
	if (dlc) {
 | 
						|
		dai_of_node	= dlc->of_node;
 | 
						|
		dai_name	= dlc->dai_name;
 | 
						|
	}
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Parse dai->sysclk come from "clocks = <&xxx>"
 | 
						|
	 * (if system has common clock)
 | 
						|
	 *  or "system-clock-frequency = <xxx>"
 | 
						|
	 *  or device's module clock.
 | 
						|
	 */
 | 
						|
	clk = devm_get_clk_from_child(dev, node, NULL);
 | 
						|
	if (!IS_ERR(clk)) {
 | 
						|
		simple_dai->sysclk = clk_get_rate(clk);
 | 
						|
 | 
						|
		asoc_simple_card_clk_register(simple_dai, clk);
 | 
						|
	} else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
 | 
						|
		simple_dai->sysclk = val;
 | 
						|
	} else {
 | 
						|
		clk = devm_get_clk_from_child(dev, dai_of_node, NULL);
 | 
						|
		if (!IS_ERR(clk))
 | 
						|
			simple_dai->sysclk = clk_get_rate(clk);
 | 
						|
	}
 | 
						|
 | 
						|
	if (of_property_read_bool(node, "system-clock-direction-out"))
 | 
						|
		simple_dai->clk_direction = SND_SOC_CLOCK_OUT;
 | 
						|
 | 
						|
	dev_dbg(dev, "%s : sysclk = %d, direction %d\n", dai_name,
 | 
						|
		simple_dai->sysclk, simple_dai->clk_direction);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk);
 | 
						|
 | 
						|
int asoc_simple_card_parse_dai(struct device_node *node,
 | 
						|
				    struct snd_soc_dai_link_component *dlc,
 | 
						|
				    struct device_node **dai_of_node,
 | 
						|
				    const char **dai_name,
 | 
						|
				    const char *list_name,
 | 
						|
				    const char *cells_name,
 | 
						|
				    int *is_single_link)
 | 
						|
{
 | 
						|
	struct of_phandle_args args;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	if (!node)
 | 
						|
		return 0;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Use snd_soc_dai_link_component instead of legacy style.
 | 
						|
	 * It is only for codec, but cpu will be supported in the future.
 | 
						|
	 * see
 | 
						|
	 *	soc-core.c :: snd_soc_init_multicodec()
 | 
						|
	 */
 | 
						|
	if (dlc) {
 | 
						|
		dai_name	= &dlc->dai_name;
 | 
						|
		dai_of_node	= &dlc->of_node;
 | 
						|
	}
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Get node via "sound-dai = <&phandle port>"
 | 
						|
	 * it will be used as xxx_of_node on soc_bind_dai_link()
 | 
						|
	 */
 | 
						|
	ret = of_parse_phandle_with_args(node, list_name, cells_name, 0, &args);
 | 
						|
	if (ret)
 | 
						|
		return ret;
 | 
						|
 | 
						|
	/* Get dai->name */
 | 
						|
	if (dai_name) {
 | 
						|
		ret = snd_soc_of_get_dai_name(node, dai_name);
 | 
						|
		if (ret < 0)
 | 
						|
			return ret;
 | 
						|
	}
 | 
						|
 | 
						|
	*dai_of_node = args.np;
 | 
						|
 | 
						|
	if (is_single_link)
 | 
						|
		*is_single_link = !args.args_count;
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai);
 | 
						|
 | 
						|
static int asoc_simple_card_get_dai_id(struct device_node *ep)
 | 
						|
{
 | 
						|
	struct device_node *node;
 | 
						|
	struct device_node *endpoint;
 | 
						|
	int i, id;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	ret = snd_soc_get_dai_id(ep);
 | 
						|
	if (ret != -ENOTSUPP)
 | 
						|
		return ret;
 | 
						|
 | 
						|
	node = of_graph_get_port_parent(ep);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Non HDMI sound case, counting port/endpoint on its DT
 | 
						|
	 * is enough. Let's count it.
 | 
						|
	 */
 | 
						|
	i = 0;
 | 
						|
	id = -1;
 | 
						|
	for_each_endpoint_of_node(node, endpoint) {
 | 
						|
		if (endpoint == ep)
 | 
						|
			id = i;
 | 
						|
		i++;
 | 
						|
	}
 | 
						|
 | 
						|
	of_node_put(node);
 | 
						|
 | 
						|
	if (id < 0)
 | 
						|
		return -ENODEV;
 | 
						|
 | 
						|
	return id;
 | 
						|
}
 | 
						|
 | 
						|
int asoc_simple_card_parse_graph_dai(struct device_node *ep,
 | 
						|
				     struct snd_soc_dai_link_component *dlc,
 | 
						|
				     struct device_node **dai_of_node,
 | 
						|
				     const char **dai_name)
 | 
						|
{
 | 
						|
	struct device_node *node;
 | 
						|
	struct of_phandle_args args;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Use snd_soc_dai_link_component instead of legacy style.
 | 
						|
	 * It is only for codec, but cpu will be supported in the future.
 | 
						|
	 * see
 | 
						|
	 *	soc-core.c :: snd_soc_init_multicodec()
 | 
						|
	 */
 | 
						|
	if (dlc) {
 | 
						|
		dai_name	= &dlc->dai_name;
 | 
						|
		dai_of_node	= &dlc->of_node;
 | 
						|
	}
 | 
						|
 | 
						|
	if (!ep)
 | 
						|
		return 0;
 | 
						|
	if (!dai_name)
 | 
						|
		return 0;
 | 
						|
 | 
						|
	node = of_graph_get_port_parent(ep);
 | 
						|
 | 
						|
	/* Get dai->name */
 | 
						|
	args.np		= node;
 | 
						|
	args.args[0]	= asoc_simple_card_get_dai_id(ep);
 | 
						|
	args.args_count	= (of_graph_get_endpoint_count(node) > 1);
 | 
						|
 | 
						|
	ret = snd_soc_get_dai_name(&args, dai_name);
 | 
						|
	if (ret < 0)
 | 
						|
		return ret;
 | 
						|
 | 
						|
	*dai_of_node = node;
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_graph_dai);
 | 
						|
 | 
						|
int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
 | 
						|
			      struct asoc_simple_dai *simple_dai)
 | 
						|
{
 | 
						|
	int ret;
 | 
						|
 | 
						|
	if (simple_dai->sysclk) {
 | 
						|
		ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk,
 | 
						|
					     simple_dai->clk_direction);
 | 
						|
		if (ret && ret != -ENOTSUPP) {
 | 
						|
			dev_err(dai->dev, "simple-card: set_sysclk error\n");
 | 
						|
			return ret;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (simple_dai->slots) {
 | 
						|
		ret = snd_soc_dai_set_tdm_slot(dai,
 | 
						|
					       simple_dai->tx_slot_mask,
 | 
						|
					       simple_dai->rx_slot_mask,
 | 
						|
					       simple_dai->slots,
 | 
						|
					       simple_dai->slot_width);
 | 
						|
		if (ret && ret != -ENOTSUPP) {
 | 
						|
			dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
 | 
						|
			return ret;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai);
 | 
						|
 | 
						|
int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link)
 | 
						|
{
 | 
						|
	/* Assumes platform == cpu */
 | 
						|
	if (!dai_link->platform_of_node)
 | 
						|
		dai_link->platform_of_node = dai_link->cpu_of_node;
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink);
 | 
						|
 | 
						|
void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
 | 
						|
				       int is_single_links)
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * In soc_bind_dai_link() will check cpu name after
 | 
						|
	 * of_node matching if dai_link has cpu_dai_name.
 | 
						|
	 * but, it will never match if name was created by
 | 
						|
	 * fmt_single_name() remove cpu_dai_name if cpu_args
 | 
						|
	 * was 0. See:
 | 
						|
	 *	fmt_single_name()
 | 
						|
	 *	fmt_multiple_name()
 | 
						|
	 */
 | 
						|
	if (is_single_links)
 | 
						|
		dai_link->cpu_dai_name = NULL;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu);
 | 
						|
 | 
						|
int asoc_simple_card_clean_reference(struct snd_soc_card *card)
 | 
						|
{
 | 
						|
	struct snd_soc_dai_link *dai_link;
 | 
						|
	int num_links;
 | 
						|
 | 
						|
	for (num_links = 0, dai_link = card->dai_link;
 | 
						|
	     num_links < card->num_links;
 | 
						|
	     num_links++, dai_link++) {
 | 
						|
		of_node_put(dai_link->cpu_of_node);
 | 
						|
		of_node_put(dai_link->codec_of_node);
 | 
						|
		if (dai_link->codecs)
 | 
						|
			of_node_put(dai_link->codecs->of_node);
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference);
 | 
						|
 | 
						|
int asoc_simple_card_of_parse_routing(struct snd_soc_card *card,
 | 
						|
				      char *prefix,
 | 
						|
				      int optional)
 | 
						|
{
 | 
						|
	struct device_node *node = card->dev->of_node;
 | 
						|
	char prop[128];
 | 
						|
 | 
						|
	if (!prefix)
 | 
						|
		prefix = "";
 | 
						|
 | 
						|
	snprintf(prop, sizeof(prop), "%s%s", prefix, "routing");
 | 
						|
 | 
						|
	if (!of_property_read_bool(node, prop)) {
 | 
						|
		if (optional)
 | 
						|
			return 0;
 | 
						|
		return -EINVAL;
 | 
						|
	}
 | 
						|
 | 
						|
	return snd_soc_of_parse_audio_routing(card, prop);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_routing);
 | 
						|
 | 
						|
int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card,
 | 
						|
				      char *prefix)
 | 
						|
{
 | 
						|
	struct device_node *node = card->dev->of_node;
 | 
						|
	char prop[128];
 | 
						|
 | 
						|
	if (!prefix)
 | 
						|
		prefix = "";
 | 
						|
 | 
						|
	snprintf(prop, sizeof(prop), "%s%s", prefix, "widgets");
 | 
						|
 | 
						|
	if (of_property_read_bool(node, prop))
 | 
						|
		return snd_soc_of_parse_audio_simple_widgets(card, prop);
 | 
						|
 | 
						|
	/* no widgets is not error */
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_widgets);
 | 
						|
 | 
						|
int asoc_simple_card_init_jack(struct snd_soc_card *card,
 | 
						|
			       struct asoc_simple_jack *sjack,
 | 
						|
			       int is_hp, char *prefix)
 | 
						|
{
 | 
						|
	struct device *dev = card->dev;
 | 
						|
	enum of_gpio_flags flags;
 | 
						|
	char prop[128];
 | 
						|
	char *pin_name;
 | 
						|
	char *gpio_name;
 | 
						|
	int mask;
 | 
						|
	int det;
 | 
						|
 | 
						|
	if (!prefix)
 | 
						|
		prefix = "";
 | 
						|
 | 
						|
	sjack->gpio.gpio = -ENOENT;
 | 
						|
 | 
						|
	if (is_hp) {
 | 
						|
		snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
 | 
						|
		pin_name	= "Headphones";
 | 
						|
		gpio_name	= "Headphone detection";
 | 
						|
		mask		= SND_JACK_HEADPHONE;
 | 
						|
	} else {
 | 
						|
		snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
 | 
						|
		pin_name	= "Mic Jack";
 | 
						|
		gpio_name	= "Mic detection";
 | 
						|
		mask		= SND_JACK_MICROPHONE;
 | 
						|
	}
 | 
						|
 | 
						|
	det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
 | 
						|
	if (det == -EPROBE_DEFER)
 | 
						|
		return -EPROBE_DEFER;
 | 
						|
 | 
						|
	if (gpio_is_valid(det)) {
 | 
						|
		sjack->pin.pin		= pin_name;
 | 
						|
		sjack->pin.mask		= mask;
 | 
						|
 | 
						|
		sjack->gpio.name	= gpio_name;
 | 
						|
		sjack->gpio.report	= mask;
 | 
						|
		sjack->gpio.gpio	= det;
 | 
						|
		sjack->gpio.invert	= !!(flags & OF_GPIO_ACTIVE_LOW);
 | 
						|
		sjack->gpio.debounce_time = 150;
 | 
						|
 | 
						|
		snd_soc_card_jack_new(card, pin_name, mask,
 | 
						|
				      &sjack->jack,
 | 
						|
				      &sjack->pin, 1);
 | 
						|
 | 
						|
		snd_soc_jack_add_gpios(&sjack->jack, 1,
 | 
						|
				       &sjack->gpio);
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(asoc_simple_card_init_jack);
 | 
						|
 | 
						|
/* Module information */
 | 
						|
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
 | 
						|
MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
 | 
						|
MODULE_LICENSE("GPL v2");
 |