From patchwork Wed Sep 24 09:55:20 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Jiang X-Patchwork-Id: 4954801 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.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 679789F348 for ; Tue, 23 Sep 2014 09:59:01 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 07B5B2024D for ; Tue, 23 Sep 2014 09:59:00 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 7AB9120221 for ; Tue, 23 Sep 2014 09:58:58 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id A3936265050; Tue, 23 Sep 2014 11:58:56 +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.3 required=5.0 tests=BAYES_00, DATE_IN_FUTURE_12_24, DKIM_ADSP_CUSTOM_MED,FREEMAIL_FROM,UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id B07132625FF; Tue, 23 Sep 2014 11:58:48 +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 0FE8D262606; Tue, 23 Sep 2014 11:58:47 +0200 (CEST) Received: from na01-bn1-obe.outbound.protection.outlook.com (mail-bn1on0087.outbound.protection.outlook.com [157.56.110.87]) by alsa0.perex.cz (Postfix) with ESMTP id CF2ED261AE4 for ; Tue, 23 Sep 2014 11:58:34 +0200 (CEST) Received: from BY2PR03CA058.namprd03.prod.outlook.com (10.141.249.31) by BL2PR03MB1010.namprd03.prod.outlook.com (10.141.182.148) with Microsoft SMTP Server (TLS) id 15.0.1034.13; Tue, 23 Sep 2014 09:58:32 +0000 Received: from BL2FFO11FD018.protection.gbl (2a01:111:f400:7c09::197) by BY2PR03CA058.outlook.office365.com (2a01:111:e400:2c5d::31) with Microsoft SMTP Server (TLS) id 15.0.1034.13 via Frontend Transport; Tue, 23 Sep 2014 09:58:31 +0000 Received: from nwd2mta1.analog.com (137.71.25.55) by BL2FFO11FD018.mail.protection.outlook.com (10.173.161.36) with Microsoft SMTP Server (TLS) id 15.0.1029.15 via Frontend Transport; Tue, 23 Sep 2014 09:58:31 +0000 Received: from NWD2HUBCAS7.ad.analog.com (nwd2hubcas7.ad.analog.com [10.64.72.140]) by nwd2mta1.analog.com (8.13.8/8.13.8) with ESMTP id s8N9uTBM020256 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL); Tue, 23 Sep 2014 02:57:51 -0700 Received: from zeus.spd.analog.com (10.64.82.11) by NWD2HUBCAS7.ad.analog.com (10.64.72.140) with Microsoft SMTP Server id 14.3.210.2; Tue, 23 Sep 2014 05:57:49 -0400 Received: from linux.site ([10.99.22.20]) by zeus.spd.analog.com (8.14.6/8.14.6) with ESMTP id s8N9vkFu023351; Tue, 23 Sep 2014 05:57:48 -0400 Received: from localhost.localdomain (unknown [10.99.24.124]) by linux.site (Postfix) with ESMTP id C7F463AEB9F0; Mon, 22 Sep 2014 19:57:35 -0600 (MDT) From: Scott Jiang To: Mark Brown Date: Wed, 24 Sep 2014 17:55:20 +0800 Message-ID: <1411552520-26090-1-git-send-email-scott.jiang.linux@gmail.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-Matching-Connectors: 130559399113654854; (52f37747-95c3-483a-bd05-08d153b03fac); () X-Forefront-Antispam-Report: CIP:137.71.25.55; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(199003)(189002)(107046002)(82202001)(19580405001)(50226001)(81542003)(88136002)(87936001)(95666004)(36756003)(73972006)(89996001)(19580395003)(90102001)(50466002)(4396001)(48376002)(74502003)(80022003)(44976005)(6806004)(81342003)(49486002)(105596002)(74662003)(77982003)(46102003)(79102003)(102836001)(77156001)(87286001)(21056001)(92726001)(83072002)(55446002)(229853001)(93916002)(33646002)(62966002)(87572001)(92566001)(86362001)(106466001)(64706001)(81442002)(47776003)(104166001)(73392002)(31966008)(85306004)(61266001)(85852003)(50986999)(120916001)(10300001)(110136001)(20776003)(99396002)(2004002)(32563001); DIR:OUT; SFP:1101; SCL:1; SRVR:BL2PR03MB1010; H:nwd2mta1.analog.com; FPR:; MLV:sfv; PTR:nwd2mail10.analog.com; A:1; MX:1; LANG:en; X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:;SRVR:BL2PR03MB1010; X-Forefront-PRVS: 0343AC1D30 Received-SPF: SoftFail (protection.outlook.com: domain of transitioning gmail.com discourages use of 137.71.25.55 as permitted sender) Authentication-Results: spf=softfail (sender IP is 137.71.25.55) smtp.mailfrom=scott.jiang.linux@gmail.com; Cc: uclinux-dist-devel@blackfin.uclinux.org, alsa-devel@alsa-project.org, Scott Jiang Subject: [alsa-devel] [PATCH] ASoC: blackfin: add bf6xx audio dma driver 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP Bf5xx and bf6xx reused bf5xx-i2s-pcm.c before. Recently tdm driver has been merged into bf5xx-i2s-pcm.c and it's not compatible with bf6xx audio. So create this dma driver and add tdm support later. Signed-off-by: Scott Jiang --- sound/soc/blackfin/Kconfig | 22 ++-- sound/soc/blackfin/Makefile | 2 + sound/soc/blackfin/bf6xx-pcm.c | 230 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 248 insertions(+), 6 deletions(-) create mode 100644 sound/soc/blackfin/bf6xx-pcm.c diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 6410aa2..9d6bd9d 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -1,8 +1,17 @@ config SND_BF5XX_I2S tristate "SoC I2S Audio for the ADI Blackfin chip" - depends on BLACKFIN - select SND_BF5XX_SOC_SPORT if !BF60x - select SND_BF6XX_SOC_SPORT if BF60x + depends on BLACKFIN && !BF60x + select SND_BF5XX_SOC_SPORT + help + Say Y or M if you want to add support for codecs attached to + the Blackfin SPORT (synchronous serial ports) interface in I2S + mode (supports single stereo In/Out). + You will also need to select the audio interfaces to support below. + +config SND_BF6XX_PCM + tristate "SoC Audio for the ADI Blackfin BF6xx chip" + depends on BF60x + select SND_BF6XX_SOC_SPORT help Say Y or M if you want to add support for codecs attached to the Blackfin SPORT (synchronous serial ports) interface in I2S @@ -11,7 +20,7 @@ config SND_BF5XX_I2S config SND_BF5XX_SOC_SSM2602 tristate "SoC SSM2602 Audio Codec Add-On Card support" - depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI + depends on (SND_BF5XX_I2S || SND_BF6XX_PCM) && SND_SOC_I2C_AND_SPI select SND_BF5XX_SOC_I2S if !BF60x select SND_BF6XX_SOC_I2S if BF60x select SND_SOC_SSM2602_SPI if SPI_MASTER @@ -45,8 +54,9 @@ config SND_SOC_BFIN_EVAL_ADAU1373 config SND_SOC_BFIN_EVAL_ADAU1X61 tristate "Support for the EVAL-ADAU1X61 board on Blackfin eval boards" - depends on SND_BF5XX_I2S && I2C - select SND_BF5XX_SOC_I2S + depends on (SND_BF5XX_I2S || SND_BF6XX_PCM) && I2C + select SND_BF5XX_SOC_I2S if !BF60x + select SND_BF6XX_SOC_I2S if BF60x select SND_SOC_ADAU1761_I2C help Say Y if you want to add support for the Analog Devices EVAL-ADAU1X61 diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile index f21e948..cef39f6 100644 --- a/sound/soc/blackfin/Makefile +++ b/sound/soc/blackfin/Makefile @@ -1,6 +1,7 @@ # Blackfin Platform Support snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o +snd-bf6xx-pcm-objs := bf6xx-pcm.o snd-soc-bf5xx-sport-objs := bf5xx-sport.o snd-soc-bf6xx-sport-objs := bf6xx-sport.o snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o @@ -9,6 +10,7 @@ snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o +obj-$(CONFIG_SND_BF6XX_PCM) += snd-bf6xx-pcm.o obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o diff --git a/sound/soc/blackfin/bf6xx-pcm.c b/sound/soc/blackfin/bf6xx-pcm.c new file mode 100644 index 0000000..bad9fbf --- /dev/null +++ b/sound/soc/blackfin/bf6xx-pcm.c @@ -0,0 +1,230 @@ +/* + * bf6xx-pcm.c - Analog Devices BF6XX audio dma driver + * + * Copyright (c) 2014 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bf6xx-sport.h" + +static void bf6xx_dma_irq(void *data) +{ + struct snd_pcm_substream *pcm = data; + snd_pcm_period_elapsed(pcm); +} + +static const struct snd_pcm_hardware bf6xx_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BLOCK_TRANSFER, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .period_bytes_min = 32, + .period_bytes_max = 0x10000, + .periods_min = 1, + .periods_max = PAGE_SIZE/32, + .buffer_bytes_max = 0x20000, /* 128 kbytes */ + .fifo_size = 16, +}; + +static int bf6xx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + size_t size = params_buffer_bytes(params); + snd_pcm_lib_malloc_pages(substream, size); + + return 0; +} + +static int bf6xx_pcm_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_lib_free_pages(substream); + + return 0; +} + +static int bf6xx_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct sport_device *sport = runtime->private_data; + int period_bytes = frames_to_bytes(runtime, runtime->period_size); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + sport_set_tx_callback(sport, bf6xx_dma_irq, substream); + sport_config_tx_dma(sport, runtime->dma_area, + runtime->periods, period_bytes); + } else { + sport_set_rx_callback(sport, bf6xx_dma_irq, substream); + sport_config_rx_dma(sport, runtime->dma_area, + runtime->periods, period_bytes); + } + + return 0; +} + +static int bf6xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct sport_device *sport = runtime->private_data; + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + sport_tx_start(sport); + else + sport_rx_start(sport); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + sport_tx_stop(sport); + else + sport_rx_stop(sport); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static snd_pcm_uframes_t bf6xx_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct sport_device *sport = runtime->private_data; + unsigned int diff; + snd_pcm_uframes_t frames; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + diff = sport_curr_offset_tx(sport); + else + diff = sport_curr_offset_rx(sport); + + /* + * TX at least can report one frame beyond the end of the + * buffer if we hit the wraparound case - clamp to within the + * buffer as the ALSA APIs require. + */ + if (diff == snd_pcm_lib_buffer_bytes(substream)) + diff = 0; + + frames = bytes_to_frames(substream->runtime, diff); + + return frames; +} + +static int bf6xx_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct sport_device *sport = snd_soc_dai_get_drvdata(cpu_dai); + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_dma_buffer *buf = &substream->dma_buffer; + int ret; + + snd_soc_set_runtime_hwparams(substream, &bf6xx_pcm_hardware); + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + sport->tx_buf = buf->area; + else + sport->rx_buf = buf->area; + + runtime->private_data = sport; + return 0; +} + +static int bf6xx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + size_t size = vma->vm_end - vma->vm_start; + vma->vm_start = (unsigned long)runtime->dma_area; + vma->vm_end = vma->vm_start + size; + vma->vm_flags |= VM_SHARED; + + return 0 ; +} + +static struct snd_pcm_ops bf6xx_pcm_ops = { + .open = bf6xx_pcm_open, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = bf6xx_pcm_hw_params, + .hw_free = bf6xx_pcm_hw_free, + .prepare = bf6xx_pcm_prepare, + .trigger = bf6xx_pcm_trigger, + .pointer = bf6xx_pcm_pointer, + .mmap = bf6xx_pcm_mmap, +}; + +static int bf6xx_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_card *card = rtd->card->snd_card; + size_t size = bf6xx_pcm_hardware.buffer_bytes_max; + int ret = 0; + + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, + SNDRV_DMA_TYPE_DEV, card->dev, size, size); +} + +static struct snd_soc_platform_driver bf6xx_soc_platform = { + .ops = &bf6xx_pcm_ops, + .pcm_new = bf6xx_pcm_new, +}; + +static int bfin_soc_platform_probe(struct platform_device *pdev) +{ + return snd_soc_register_platform(&pdev->dev, &bf6xx_soc_platform); +} + +static int bfin_soc_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver bfin_pcm_driver = { + .driver = { + .name = "bfin-i2s-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = bfin_soc_platform_probe, + .remove = bfin_soc_platform_remove, +}; + +module_platform_driver(bfin_pcm_driver); + +MODULE_DESCRIPTION("Analog Devices BF6XX audio dma driver"); +MODULE_AUTHOR("Scott Jiang "); +MODULE_LICENSE("GPL v2");