From patchwork Wed Feb 26 06:04:50 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: rjying X-Patchwork-Id: 3721171 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7EE66BF13A for ; Wed, 26 Feb 2014 06:09:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 473D7201DD for ; Wed, 26 Feb 2014 06:09:18 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 8383720173 for ; Wed, 26 Feb 2014 06:09:16 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 84E2B26558D; Wed, 26 Feb 2014 07:09:15 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id B271F26569E; Wed, 26 Feb 2014 07:08:18 +0100 (CET) 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 AD5FE2656E8; Wed, 26 Feb 2014 07:08:17 +0100 (CET) Received: from mail-pb0-f44.google.com (mail-pb0-f44.google.com [209.85.160.44]) by alsa0.perex.cz (Postfix) with ESMTP id 52D552655A0 for ; Wed, 26 Feb 2014 07:07:07 +0100 (CET) Received: by mail-pb0-f44.google.com with SMTP id rp16so519958pbb.31 for ; Tue, 25 Feb 2014 22:07:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/c7MqnsWlzcNmIEZOupD7o9lbm9X3ERjeUIXlwEUXGo=; b=j8OtAI7qLvO2HFInJe3BVDd8U7G5va5jR+HjjKV6P0Lw8JT4u5lTsXnzqg11gfi3Cd A9NBHqnvqxPwnZkIW1EuStZgfoQ6ao7VH2Tn4Cva2ump8kPLqXTdM0cfHvN0jfuUH9Rk LhDniV8k5zxhgktZ5AX1nRDJm6obmi2zD658odhEpwGiqeO9Bp64pezF10quLivbElnt H+oB/dDmnZ+jdMX+javbizInIC+OHm2BRKeOKJ2wC7Uc4xEW/XNewBgCjTkrYsBNiktO rAcH9cIHKvv8qlB47ELiHEMNDdGwyi+y4htU3RRrgzydqO//DAccdmr0hxMc1Jn6igLo 2sRQ== X-Received: by 10.68.143.196 with SMTP id sg4mr4404152pbb.155.1393394825940; Tue, 25 Feb 2014 22:07:05 -0800 (PST) Received: from localhost.localdomain ([183.192.68.118]) by mx.google.com with ESMTPSA id yh4sm17034769pbb.19.2014.02.25.22.06.59 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 25 Feb 2014 22:07:05 -0800 (PST) From: RongJun Ying To: Liam Girdwood , Mark Brown , rjying@gmail.com Date: Wed, 26 Feb 2014 14:04:50 +0800 Message-Id: <1393394695-29735-3-git-send-email-rongjun.ying@csr.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1393394695-29735-1-git-send-email-rongjun.ying@csr.com> References: <1393394695-29735-1-git-send-email-rongjun.ying@csr.com> Cc: Takashi Iwai , Rongjun Ying , alsa-devel@alsa-project.org, workgroup.linux@csr.com Subject: [alsa-devel] [PATCH v4 2/7] ASoC: sirf: Add SiRF audio port driver is used by SiRF internal audio codec 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 From: Rongjun Ying Signed-off-by: Rongjun Ying --- -v4: 1. Add SiRF audio port driver split from sirf-soc-inner driver. 2. Use the generic dmaengine pcm register. 3. Add binding document. 4. Use MMIO regmap. .../devicetree/bindings/sound/sirf-audio-port.txt | 20 ++ sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/sirf/Kconfig | 9 + sound/soc/sirf/Makefile | 3 + sound/soc/sirf/sirf-audio-port.c | 194 ++++++++++++++++++++ sound/soc/sirf/sirf-audio-port.h | 62 +++++++ 7 files changed, 290 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/sirf-audio-port.txt create mode 100644 sound/soc/sirf/Kconfig create mode 100644 sound/soc/sirf/Makefile create mode 100644 sound/soc/sirf/sirf-audio-port.c create mode 100644 sound/soc/sirf/sirf-audio-port.h diff --git a/Documentation/devicetree/bindings/sound/sirf-audio-port.txt b/Documentation/devicetree/bindings/sound/sirf-audio-port.txt new file mode 100644 index 0000000..1f66de3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sirf-audio-port.txt @@ -0,0 +1,20 @@ +* SiRF SoC audio port + +Required properties: +- compatible: "sirf,audio-port" +- reg: Base address and size entries: +- dmas: List of DMA controller phandle and DMA request line ordered pairs. +- dma-names: Identifier string for each DMA request line in the dmas property. + These strings correspond 1:1 with the ordered pairs in dmas. + + One of the DMA channels will be responsible for transmission (should be + named "tx") and one for reception (should be named "rx"). + +Example: + +audioport: audioport@b0040000 { + compatible = "sirf,audio-port"; + reg = <0xb0040000 0x10000>; + dmas = <&dmac1 3>, <&dmac1 8>; + dma-names = "rx", "tx"; +}; diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index d62ce48..23946c2 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -54,6 +54,7 @@ source "sound/soc/spear/Kconfig" source "sound/soc/tegra/Kconfig" source "sound/soc/txx9/Kconfig" source "sound/soc/ux500/Kconfig" +source "sound/soc/sirf/Kconfig" # Supported codecs source "sound/soc/codecs/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 62a1822..f09210c 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -31,3 +31,4 @@ obj-$(CONFIG_SND_SOC) += spear/ obj-$(CONFIG_SND_SOC) += tegra/ obj-$(CONFIG_SND_SOC) += txx9/ obj-$(CONFIG_SND_SOC) += ux500/ +obj-$(CONFIG_SND_SOC) += sirf/ diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig new file mode 100644 index 0000000..5b5407f --- /dev/null +++ b/sound/soc/sirf/Kconfig @@ -0,0 +1,9 @@ +config SND_SOC_SIRF + tristate "SoC Audio for the SiRF SoC chips" + depends on ARCH_SIRF || COMPILE_TEST + select SND_SOC_GENERIC_DMAENGINE_PCM + +config SND_SOC_SIRF_AUDIO_PORT + select REGMAP_MMIO + tristate + diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile new file mode 100644 index 0000000..fb012c8 --- /dev/null +++ b/sound/soc/sirf/Makefile @@ -0,0 +1,3 @@ +snd-soc-sirf-audio-port-objs := sirf-audio-port.o + +obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c new file mode 100644 index 0000000..4169b59 --- /dev/null +++ b/sound/soc/sirf/sirf-audio-port.c @@ -0,0 +1,194 @@ +/* + * SiRF Audio port driver + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ +#include +#include +#include +#include +#include + +#include "sirf-audio-port.h" + +struct sirf_audio_port { + struct regmap *regmap; + struct snd_dmaengine_dai_dma_data playback_dma_data; + struct snd_dmaengine_dai_dma_data capture_dma_data; +}; + +static inline void sirf_audio_port_tx_enable(struct sirf_audio_port *port) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0); + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, + IC_TX_ENABLE, IC_TX_ENABLE); +} + +static inline void sirf_audio_port_tx_disable(struct sirf_audio_port *port) +{ + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, + IC_TX_ENABLE, ~IC_TX_ENABLE); +} + +static inline void sirf_audio_port_rx_enable(struct sirf_audio_port *port, + int channels) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_INT_MSK, 0); + regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + if (channels == 1) + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO); + else + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO); +} + +static inline void sirf_audio_port_rx_disable(struct sirf_audio_port *port) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO); +} + +static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) +{ + struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); + snd_soc_dai_init_dma_data(dai, &port->playback_dma_data, + &port->capture_dma_data); + return 0; +} + +static int sirf_audio_port_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (playback) + sirf_audio_port_tx_disable(port); + else + sirf_audio_port_rx_disable(port); + break; + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (playback) + sirf_audio_port_tx_enable(port); + else + sirf_audio_port_rx_enable(port, + substream->runtime->channels); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops sirf_audio_port_dai_ops = { + .trigger = sirf_audio_port_trigger, +}; + +static struct snd_soc_dai_driver sirf_audio_port_dai = { + .probe = sirf_audio_port_dai_probe, + .name = "sirf-audio-port", + .id = 0, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &sirf_audio_port_dai_ops, +}; + +static const struct snd_soc_component_driver sirf_audio_port_component = { + .name = "sirf-audio-port", +}; + +static const struct regmap_config sirf_audio_port_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK, + .cache_type = REGCACHE_NONE, +}; + +static int sirf_audio_port_probe(struct platform_device *pdev) +{ + int ret; + struct sirf_audio_port *port; + void __iomem *base; + struct resource *mem_res; + + port = devm_kzalloc(&pdev->dev, + sizeof(struct sirf_audio_port), GFP_KERNEL); + if (!port) + return -ENOMEM; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem_res) { + dev_err(&pdev->dev, "no mem resource?\n"); + return -ENODEV; + } + + base = devm_ioremap(&pdev->dev, mem_res->start, + resource_size(mem_res)); + if (base == NULL) + return -ENOMEM; + + port->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sirf_audio_port_regmap_config); + if (IS_ERR(port->regmap)) + return PTR_ERR(port->regmap); + + ret = devm_snd_soc_register_component(&pdev->dev, + &sirf_audio_port_component, &sirf_audio_port_dai, 1); + if (ret) + return ret; + + platform_set_drvdata(pdev, port); + return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); +} + +static const struct of_device_id sirf_audio_port_of_match[] = { + { .compatible = "sirf,audio-port", }, + {} +}; +MODULE_DEVICE_TABLE(of, sirf_audio_port_of_match); + +static struct platform_driver sirf_audio_port_driver = { + .driver = { + .name = "sirf-audio-port", + .owner = THIS_MODULE, + .of_match_table = sirf_audio_port_of_match, + }, + .probe = sirf_audio_port_probe, +}; + +module_platform_driver(sirf_audio_port_driver); + +MODULE_DESCRIPTION("SiRF Audio Port driver"); +MODULE_AUTHOR("RongJun Ying "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/sirf/sirf-audio-port.h b/sound/soc/sirf/sirf-audio-port.h new file mode 100644 index 0000000..f32dc54 --- /dev/null +++ b/sound/soc/sirf/sirf-audio-port.h @@ -0,0 +1,62 @@ +/* + * SiRF Audio port controllers define + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _SIRF_AUDIO_PORT_H +#define _SIRF_AUDIO_PORT_H + +#define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK 0x3F +#define AUDIO_PORT_TX_FIFO_SC_OFFSET 0 +#define AUDIO_PORT_TX_FIFO_LC_OFFSET 10 +#define AUDIO_PORT_TX_FIFO_HC_OFFSET 20 + +#define TX_FIFO_SC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_SC_OFFSET) +#define TX_FIFO_LC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_LC_OFFSET) +#define TX_FIFO_HC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_HC_OFFSET) + +#define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK 0x0F +#define AUDIO_PORT_RX_FIFO_SC_OFFSET 0 +#define AUDIO_PORT_RX_FIFO_LC_OFFSET 10 +#define AUDIO_PORT_RX_FIFO_HC_OFFSET 20 + +#define RX_FIFO_SC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_SC_OFFSET) +#define RX_FIFO_LC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_LC_OFFSET) +#define RX_FIFO_HC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_HC_OFFSET) +#define AUDIO_PORT_IC_CODEC_TX_CTRL (0x00F4) +#define AUDIO_PORT_IC_CODEC_RX_CTRL (0x00F8) + +#define AUDIO_PORT_IC_TXFIFO_OP (0x00FC) +#define AUDIO_PORT_IC_TXFIFO_LEV_CHK (0x0100) +#define AUDIO_PORT_IC_TXFIFO_STS (0x0104) +#define AUDIO_PORT_IC_TXFIFO_INT (0x0108) +#define AUDIO_PORT_IC_TXFIFO_INT_MSK (0x010C) + +#define AUDIO_PORT_IC_RXFIFO_OP (0x0110) +#define AUDIO_PORT_IC_RXFIFO_LEV_CHK (0x0114) +#define AUDIO_PORT_IC_RXFIFO_STS (0x0118) +#define AUDIO_PORT_IC_RXFIFO_INT (0x011C) +#define AUDIO_PORT_IC_RXFIFO_INT_MSK (0x0120) + +#define AUDIO_FIFO_START (1 << 0) +#define AUDIO_FIFO_RESET (1 << 1) + +#define AUDIO_FIFO_FULL (1 << 0) +#define AUDIO_FIFO_EMPTY (1 << 1) +#define AUDIO_FIFO_OFLOW (1 << 2) +#define AUDIO_FIFO_UFLOW (1 << 3) + +#define IC_TX_ENABLE (0x03) +#define IC_RX_ENABLE_MONO (0x01) +#define IC_RX_ENABLE_STEREO (0x03) + +#endif /*__SIRF_AUDIO_PORT_H*/