From patchwork Mon Jul 1 08:39:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Genoud X-Patchwork-Id: 2806681 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B9AD69F3EB for ; Mon, 1 Jul 2013 09:52:49 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2F46620159 for ; Mon, 1 Jul 2013 09:52:48 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5E0712014A for ; Mon, 1 Jul 2013 09:52:46 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UtZgy-0003hI-5A; Mon, 01 Jul 2013 08:42:42 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UtZfi-0003OT-1x; Mon, 01 Jul 2013 08:41:18 +0000 Received: from mail-wi0-x233.google.com ([2a00:1450:400c:c05::233]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UtZf1-0003G0-EO for linux-arm-kernel@lists.infradead.org; Mon, 01 Jul 2013 08:40:38 +0000 Received: by mail-wi0-f179.google.com with SMTP id hj3so2790893wib.0 for ; Mon, 01 Jul 2013 01:40:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=R2vnPdyFgG+5ybUXSRLvj3d6pENdDyIxtYh9gpZThwE=; b=ArkATUmN5zYlNVZmkOEnLF1WycpZRpR6OXBbYqllD4nc5+k4VnColQFEF3BockftQ+ aDNQMvfM3qBqOiQyvdzULKhZWJAPsqSRj2VWbOKlKvbVu9XJZxNOXe429sA+Ot/+bcQR dPKTplyQ6B+yawXSj9CEaj9pt7zgKbJZpiuWNjGBnCIMVokKtuhyw9mh4THiPEg//isE omaZ+N3IK+N21FKJs5jqkO/yw9MVjl+57OQoHwlXeNKHm7rRsgdIoa3COcA3HL9J5Crm a7pNP0kTMrQrymjkUYRTImelXj9C+Fc/LylV8zWybGOHfKZzOewIoVUoKXiz6bWEtoAi lQSw== X-Received: by 10.180.78.98 with SMTP id a2mr11241097wix.27.1372668013680; Mon, 01 Jul 2013 01:40:13 -0700 (PDT) Received: from lnx-rg.pr (lyon.paratronic.fr. [213.41.177.106]) by mx.google.com with ESMTPSA id h8sm14786574wie.1.2013.07.01.01.40.11 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 01 Jul 2013 01:40:13 -0700 (PDT) From: Richard Genoud To: devicetree-discuss@lists.ozlabs.org Subject: [RFC PATCH 08/13] sound: sam9x5_wm8731: machine driver for at91sam9x5 wm8731 boards Date: Mon, 1 Jul 2013 10:39:33 +0200 Message-Id: <1372667978-4718-9-git-send-email-richard.genoud@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1372667978-4718-1-git-send-email-richard.genoud@gmail.com> References: <1372667978-4718-1-git-send-email-richard.genoud@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130701_044035_792033_AEF40F8D X-CRM114-Status: GOOD ( 21.16 ) X-Spam-Score: -2.0 (--) Cc: Richard Genoud , Nicolas Ferre , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Nicolas Ferre Description of the Asoc machine driver for an at91sam9x5 based board with a wm8731 audio DAC. Wm8731 is clocked by a crystal and used as a master on the SSC/I2S interface. Its connections are a headphone jack and an Line input jack. [Richard: this is based on an old patch from Nicolas that I forward ported and reworked to use only device tree] Signed-off-by: Nicolas Ferre Signed-off-by: Uwe Kleine-König Signed-off-by: Richard Genoud --- sound/soc/atmel/Kconfig | 12 ++ sound/soc/atmel/Makefile | 2 + sound/soc/atmel/sam9x5_wm8731.c | 232 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 246 insertions(+) create mode 100644 sound/soc/atmel/sam9x5_wm8731.c diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index 3fdd87f..f24d601 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -13,6 +13,7 @@ config SND_ATMEL_SOC_PDC config SND_ATMEL_SOC_DMA tristate depends on SND_ATMEL_SOC + select SND_SOC_DMAENGINE_PCM config SND_ATMEL_SOC_SSC tristate @@ -32,6 +33,17 @@ config SND_AT91_SOC_SAM9G20_WM8731 Say Y if you want to add support for SoC audio on WM8731-based AT91sam9g20 evaluation board. +config SND_AT91_SOC_SAM9X5_WM8731 + tristate "SoC Audio support for WM8731-based at91sam9x5 board" + depends on ATMEL_SSC && SND_ATMEL_SOC && SOC_AT91SAM9X5 + select SND_ATMEL_SOC_SSC + select SND_ATMEL_SOC_DMA + select SND_ATMEL_SOC_PDC + select SND_SOC_WM8731 + help + Say Y if you want to add support for audio SoC on an + at91sam9x5 based board that is using WM8731 codec. + config SND_AT91_SOC_AFEB9260 tristate "SoC Audio support for AFEB9260 board" depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile index 41967cc..7784c09 100644 --- a/sound/soc/atmel/Makefile +++ b/sound/soc/atmel/Makefile @@ -11,6 +11,8 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o # AT91 Machine Support snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o +snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o +obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c new file mode 100644 index 0000000..83ca457 --- /dev/null +++ b/sound/soc/atmel/sam9x5_wm8731.c @@ -0,0 +1,232 @@ +/* + * sam9x5_wm8731 -- SoC audio for AT91SAM9X5-based boards + * that are using WM8731 as codec. + * + * Copyright (C) 2011 Atmel, + * Nicolas Ferre + * + * Based on sam9g20_wm8731.c by: + * Sedji Gaouaou + * + * GPL + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "../codecs/wm8731.h" +#include "atmel-pcm.h" +#include "atmel_ssc_dai.h" + +#define MCLK_RATE 12288000 + +#define DRV_NAME "sam9x5-snd-wm8731" + +/* + * Audio paths on at91sam9x5ek board: + * + * |A| ------------> | | ---R----> Headphone Jack + * |T| <----\ | WM | ---L--/ + * |9| ---> CLK <--> | 8751 | <--R----- Line In Jack + * |1| <------------ | | <--L--/ + */ +static const struct snd_soc_dapm_widget at91sam9x5ek_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_LINE("Line In Jack", NULL), +}; + +/* + * Logic for a wm8731 as connected on a at91sam9x5 based board. + */ +static int at91sam9x5ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct device *dev = rtd->dev; + int ret; + + dev_dbg(dev, "ASoC: at91sam9x5ek_wm8731_init() called\n"); + + /* + * remove some not supported rates in relation with clock + * provided to the wm8731 codec + */ + switch (MCLK_RATE) { + case 12288000: + codec_dai->driver->playback.rates &= SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000; + codec_dai->driver->capture.rates &= SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000; + break; + case 12000000: + /* all wm8731 rates supported */ + break; + default: + dev_err(dev, "ASoC: Codec Master clock rate not defined\n"); + return -EINVAL; + } + + /* set not connected pins */ + snd_soc_dapm_nc_pin(dapm, "Mic Bias"); + snd_soc_dapm_nc_pin(dapm, "MICIN"); + snd_soc_dapm_nc_pin(dapm, "LOUT"); + snd_soc_dapm_nc_pin(dapm, "ROUT"); + + /* always connected */ + snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin(dapm, "Line In Jack"); + + /* set the codec system clock for DAC and ADC */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, + MCLK_RATE, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(dev, "ASoC: Failed to set WM8731 SYSCLK: %d\n", ret); + return ret; + } + + /* signal a DAPM event */ + snd_soc_dapm_sync(dapm); + return 0; +} + +static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *codec_np, *cpu_np; + struct snd_soc_card *card; + struct snd_soc_dai_link *dai; + int ret; + + if (!np) { + dev_err(&pdev->dev, "No device node supplied\n"); + return -EINVAL; + } + + ret = atmel_ssc_set_audio(0); + if (ret != 0) { + dev_err(&pdev->dev, + "ASoC: Failed to set SSC 0 for audio: %d\n", ret); + return ret; + } + + card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL); + dai = devm_kzalloc(&pdev->dev, sizeof(*dai), GFP_KERNEL); + if (!dai || !card) { + ret = -ENOMEM; + goto out; + } + + card->dev = &pdev->dev; + card->owner = THIS_MODULE; + card->dai_link = dai; + card->num_links = 1; + dai->name = "WM8731"; + dai->stream_name = "WM8731 PCM"; + dai->codec_dai_name = "wm8731-hifi"; + dai->init = at91sam9x5ek_wm8731_init; + card->dapm_widgets = at91sam9x5ek_dapm_widgets; + card->num_dapm_widgets = ARRAY_SIZE(at91sam9x5ek_dapm_widgets); + + ret = snd_soc_of_parse_card_name(card, "atmel,model"); + if (ret) + goto out; + + ret = snd_soc_of_parse_audio_routing(card, "atmel,audio-routing"); + if (ret) + goto out; + + codec_np = of_parse_phandle(np, "atmel,audio-codec", 0); + if (!codec_np) { + dev_err(&pdev->dev, "codec info missing\n"); + ret = -EINVAL; + goto out; + } + + dai->codec_of_node = codec_np; + + cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); + if (!cpu_np) { + dev_err(&pdev->dev, "ssc controller node missing\n"); + ret = -EINVAL; + goto out; + } + dai->cpu_of_node = cpu_np; + dai->platform_of_node = cpu_np; + + of_node_put(codec_np); + of_node_put(cpu_np); + + dai->dai_fmt = snd_soc_of_parse_daifmt(np, "atmel,"); + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, + "ASoC: Platform device allocation failed\n"); + goto out; + } + + platform_set_drvdata(pdev, card); + + dev_info(&pdev->dev, "ASoC: at91sam9x5ek_init ok\n"); + + return ret; + +out: + atmel_ssc_put_audio(0); + return ret; +} + +static int sam9x5_wm8731_driver_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + atmel_ssc_put_audio(0); + + return 0; +} + +static const struct of_device_id sam9x5_wm8731_of_match[] = { + { .compatible = "atmel,sam9x5-audio-wm8731", }, + {}, +}; +MODULE_DEVICE_TABLE(of, sam9x5_wm8731_of_match); + +static struct platform_driver sam9x5_wm8731_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(sam9x5_wm8731_of_match), + }, + .probe = sam9x5_wm8731_driver_probe, + .remove = sam9x5_wm8731_driver_remove, +}; +module_platform_driver(sam9x5_wm8731_driver); + +/* Module information */ +MODULE_AUTHOR("Nicolas Ferre "); +MODULE_AUTHOR("Richard Genoud "); +MODULE_DESCRIPTION("ALSA SoC machine driver for AT91SAM9x5 - WM8731"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME);