From patchwork Mon Apr 18 11:20:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: zhengxing X-Patchwork-Id: 8871211 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 98B939F1C1 for ; Mon, 18 Apr 2016 11:22:05 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 86332200FE for ; Mon, 18 Apr 2016 11:22:04 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id CA2DB2010E for ; Mon, 18 Apr 2016 11:22:02 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id C05AF265885; Mon, 18 Apr 2016 13:22:01 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,NO_DNS_FOR_FROM, RCVD_IN_DNSWL_NONE,UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id CF85A265512; Mon, 18 Apr 2016 13:20:33 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id BF586265132; Mon, 18 Apr 2016 13:20:31 +0200 (CEST) Received: from regular1.263xmail.com (regular1.263xmail.com [211.150.99.131]) by alsa0.perex.cz (Postfix) with ESMTP id 2FB39265112 for ; Mon, 18 Apr 2016 13:20:22 +0200 (CEST) Received: from zhengxing?rock-chips.com (unknown [192.168.167.225]) by regular1.263xmail.com (Postfix) with SMTP id 0036362FC; Mon, 18 Apr 2016 19:20:17 +0800 (CST) X-263anti-spam: KSV:0; X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ABS-CHECKED: 4 X-ADDR-CHECKED: 0 X-KSVirus-check: 0 Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.263.net (Postfix) with ESMTP id 4221529E5; Mon, 18 Apr 2016 19:20:16 +0800 (CST) X-RL-SENDER: zhengxing@rock-chips.com X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: zhengxing@rock-chips.com X-UNIQUE-TAG: X-ATTACHMENT-NUM: 0 X-SENDER: zhengxing@rock-chips.com X-DNS-TYPE: 0 Received: from unknown (unknown [58.22.7.114]) by smtp.263.net (Postfix) whith SMTP id 11846IZG5PI; Mon, 18 Apr 2016 19:20:18 +0800 (CST) From: Xing Zheng To: linux-rockchip@lists.infradead.org Date: Mon, 18 Apr 2016 19:20:02 +0800 Message-Id: <1460978403-4754-3-git-send-email-zhengxing@rock-chips.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1460978403-4754-1-git-send-email-zhengxing@rock-chips.com> References: <1460978403-4754-1-git-send-email-zhengxing@rock-chips.com> Cc: Mark Rutland , Andrew Lunn , alsa-devel@alsa-project.org, Mengdong Lin , heiko@sntech.de, Liam Girdwood , dianders@chromium.org, Xing Zheng , Aaro Koskinen , sugar.zhang@rock-chips.com, jay.xu@rock-chips.com, devicetree@vger.kernel.org, Pawel Moll , Ian Campbell , Jyri Sarha , Rob Herring , Arnaud Pouliquen , Takashi Iwai , linux-kernel@vger.kernel.org, Adam.Thomson@diasemi.com, broonie@kernel.org, Kumar Gala , Jun Nie Subject: [alsa-devel] [PATCH v2 2/3] ASoC: simple-card: Add support call the codec jack detection after parse dts X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP In most cases, many codecs already supports jack detection, previouslly, we need to create a customized machine driver every time. Hence, the simple-card need to support use them dynamically via parse dts file for better flexibility. Signed-off-by: Xing Zheng --- Changes in v1: None .../devicetree/bindings/sound/simple-card.txt | 17 +++ sound/soc/generic/simple-card.c | 126 +++++++++++++++++++- 2 files changed, 140 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index cf3979e..d25c8eb 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -22,6 +22,23 @@ Optional properties: headphones are attached. - simple-audio-card,mic-det-gpio : Reference to GPIO that signals when a microphone is attached. +- simple-audio-card,codec-jack : A list of the codec supports jack detection. + The jack types which are supported refer to include/sound/jack.h. + All of the jack types: + "JACK_HEADPHONE", + "JACK_MICROPHONE", + "JACK_HEADSET", + "JACK_LINEOUT", + "JACK_MECHANICAL", + "JACK_VIDEOOUT", + "JACK_AVOUT", + "JACK_LINEIN", + "JACK_BTN_0", + "JACK_BTN_1", + "JACK_BTN_2", + "JACK_BTN_3", + "JACK_BTN_4", + "JACK_BTN_5". Optional subnodes: diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 2389ab4..bc61022 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -33,12 +33,35 @@ struct simple_card_data { int gpio_hp_det_invert; int gpio_mic_det; int gpio_mic_det_invert; + struct simple_codecs_jack { + int jack_det; + int jack_types; + struct snd_soc_jack codec_jack; + } *codec_det_jack; struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ }; #define simple_priv_to_dev(priv) ((priv)->snd_card.dev) #define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) #define simple_priv_to_props(priv, i) ((priv)->dai_props + i) +#define simple_priv_to_codecdetjack(priv, i) ((priv)->codec_det_jack + i) + +static const char * const jack_types_list[] = { + "JACK_HEADPHONE", + "JACK_MICROPHONE", + "JACK_HEADSET", + "JACK_LINEOUT", + "JACK_MECHANICAL", + "JACK_VIDEOOUT", + "JACK_AVOUT", + "JACK_LINEIN", + "JACK_BTN_0", + "JACK_BTN_1", + "JACK_BTN_2", + "JACK_BTN_3", + "JACK_BTN_4", + "JACK_BTN_5", +}; static int asoc_simple_card_startup(struct snd_pcm_substream *substream) { @@ -136,6 +159,8 @@ static struct snd_soc_jack_gpio simple_card_mic_jack_gpio = { .debounce_time = 150, }; +static struct snd_soc_jack simple_card_codecs_jack; + static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, struct asoc_simple_dai *set) { @@ -173,9 +198,12 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; struct simple_dai_props *dai_props; + struct simple_codecs_jack *codec_det_jack; int ret; dai_props = &priv->dai_props[rtd->num]; + codec_det_jack = &priv->codec_det_jack[rtd->num]; + ret = __asoc_simple_card_dai_init(codec, &dai_props->codec_dai); if (ret < 0) return ret; @@ -208,6 +236,80 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) snd_soc_jack_add_gpios(&simple_card_mic_jack, 1, &simple_card_mic_jack_gpio); } + + if (codec_det_jack->jack_det) { + ret = snd_soc_card_jack_new(rtd->card, "Simple-card Codec Jack", + codec_det_jack->jack_types, + &simple_card_codecs_jack, NULL, 0); + if (ret) { + dev_err(rtd->card->dev, "New Simple-card Codec Jack failed! (%d)\n", ret); + return ret; + } + + snd_soc_jack_codec_detect(rtd->codec, &simple_card_codecs_jack); + } + + return 0; +} + +static int asoc_simple_card_parse_jack(struct device_node *np, int *jack_types) +{ + const char *propname = "simple-audio-card,codec-jack"; + const char *jack_name; + int num_jacks, i, j, ret; + + /* init with invalid, don't need to de-init if get count strings failed. */ + *jack_types = -1; + + num_jacks = of_property_count_strings(np, propname); + if (num_jacks < 0) { + pr_err("simple-card: Property '%s' number is invalid\n", propname); + return -EINVAL; + } + + /* init and clean value */ + *jack_types = 0; + + for (i = 0; i < num_jacks; i++) { + ret = of_property_read_string_index(np, propname, i, &jack_name); + if (ret) { + pr_err("simple-card: Property '%s' index %d read error: %d\n", + propname, i, ret); + return -EINVAL; + } + + for (j = 0; j < ARRAY_SIZE(jack_types_list); j++) { + if (!strcmp(jack_name, "JACK_HEADPHONE")) + *jack_types |= SND_JACK_HEADPHONE; + else if (!strcmp(jack_name, "JACK_MICROPHONE")) + *jack_types |= SND_JACK_MICROPHONE; + else if (!strcmp(jack_name, "JACK_HEADSET")) + *jack_types |= SND_JACK_HEADSET; + else if (!strcmp(jack_name, "JACK_LINEOUT")) + *jack_types |= SND_JACK_LINEOUT; + else if (!strcmp(jack_name, "JACK_MECHANICAL")) + *jack_types |= SND_JACK_MECHANICAL; + else if (!strcmp(jack_name, "JACK_VIDEOOUT")) + *jack_types |= SND_JACK_VIDEOOUT; + else if (!strcmp(jack_name, "JACK_AVOUT")) + *jack_types |= SND_JACK_AVOUT; + else if (!strcmp(jack_name, "JACK_LINEIN")) + *jack_types |= SND_JACK_LINEIN; + else if (!strcmp(jack_name, "JACK_BTN_0")) + *jack_types |= SND_JACK_BTN_0; + else if (!strcmp(jack_name, "JACK_BTN_1")) + *jack_types |= SND_JACK_BTN_1; + else if (!strcmp(jack_name, "JACK_BTN_2")) + *jack_types |= SND_JACK_BTN_2; + else if (!strcmp(jack_name, "JACK_BTN_3")) + *jack_types |= SND_JACK_BTN_3; + else if (!strcmp(jack_name, "JACK_BTN_4")) + *jack_types |= SND_JACK_BTN_4; + else if (!strcmp(jack_name, "JACK_BTN_5")) + *jack_types |= SND_JACK_BTN_5; + } + } + return 0; } @@ -216,7 +318,8 @@ asoc_simple_card_sub_parse_of(struct device_node *np, struct asoc_simple_dai *dai, struct device_node **p_node, const char **name, - int *args_count) + int *args_count, + struct simple_codecs_jack *codec_det_jack) { struct of_phandle_args args; struct clk *clk; @@ -272,6 +375,13 @@ asoc_simple_card_sub_parse_of(struct device_node *np, dai->sysclk = clk_get_rate(clk); } + if (codec_det_jack) { + codec_det_jack->jack_det = of_property_read_bool(np, + "simple-audio-card,codec-jack"); + if (codec_det_jack->jack_det) + asoc_simple_card_parse_jack(np, &codec_det_jack->jack_types); + } + return 0; } @@ -325,6 +435,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, struct device *dev = simple_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); + struct simple_codecs_jack *codec_det_jack = simple_priv_to_codecdetjack(priv, idx); struct device_node *cpu = NULL; struct device_node *plat = NULL; struct device_node *codec = NULL; @@ -364,13 +475,15 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, ret = asoc_simple_card_sub_parse_of(cpu, &dai_props->cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_dai_name, - &cpu_args); + &cpu_args, NULL); if (ret < 0) goto dai_link_of_err; ret = asoc_simple_card_sub_parse_of(codec, &dai_props->codec_dai, &dai_link->codec_of_node, - &dai_link->codec_dai_name, NULL); + &dai_link->codec_dai_name, NULL, + codec_det_jack); + if (ret < 0) goto dai_link_of_err; @@ -565,6 +678,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) if (!priv->dai_props) return -ENOMEM; + /* Get room for the other properties */ + priv->codec_det_jack = devm_kzalloc(dev, + sizeof(*priv->codec_det_jack) * num_links, + GFP_KERNEL); + if (!priv->codec_det_jack) + return -ENOMEM; + if (np && of_device_is_available(np)) { ret = asoc_simple_card_parse_of(np, priv);