From patchwork Tue Jul 17 15:36:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142152 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3813183ljj; Tue, 17 Jul 2018 08:36:55 -0700 (PDT) X-Google-Smtp-Source: AAOMgpeJgnQxYx+kRw5iAui9Rh5X7Ze6u8+lFlvciJAL9w0lZEIthoBReUzJjRrRtc8QKWyFkahV X-Received: by 2002:a63:3c0c:: with SMTP id j12-v6mr2045652pga.440.1531841815536; Tue, 17 Jul 2018 08:36:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841815; cv=none; d=google.com; s=arc-20160816; b=HmsbLWeoneuKK5n7JEmIDui/aQVi5s37ztm03CktGsNF7wUITtrvX+o/UDCLwBoTpw HOm9K/ckLtB+9ZTRSu2ryq+HPB+YXPa1cePsG90aZr6r0KUB36rT36QCqnO0f4XfX22A kH2P7YWSpDuEmMhSptEDPSeVs9kEkfQ56CC1XY/PSEd/PIPysv/xknYYRhHQfOuAsLep bf/lcMS6Wch9B904i5NQQyBb56mT5ky0nDHuLQX7cYz0B6OSdbUzBDKG7ia3f43SjV0y srzryLTvWbhQb0Y5caQ5tfOsJt6iRs28w/n0O/rvGugW3EgEwHqJtfHJnE0RKWUxzwna sOIg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=fC+XzcCMuHa0NwlijtZDtzKiiO/sBgP44HcxjZomirU=; b=0NIGtTcsH3c+bM9tegm80Dl1/fJ7Dx/vBDAwEyVesv51Jz14ojPNpeHBLmQp8q83E9 h9kWt16hGjrkoR1PEN6JeIW3aBdsSsTQk1ha+wNedmXYSGOE9xbN2K0hIKBC2T0UYCep 8CKZl+BY1l9hXmCcCJxCTGW34wFKY2h9YnZFnUiezBcdxSrYfoffCxJPBVNaBkdHjC6B b4N7LatvZBoWgyIumf0cmki5RopKGewfJWXIZ0isUnoGEDHPBtpicwrDJUeQtTq0Uj+x O2Y5AZ3qVxzRYJyPHeovDX8Its9V1y4HO/2WJIcMDrFFkXfvyrhTrw1n7SRTcMTptjzb oHow== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=IoGwjha9; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o4-v6si1213371pfh.168.2018.07.17.08.36.55; Tue, 17 Jul 2018 08:36:55 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=IoGwjha9; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730238AbeGQQKE (ORCPT + 31 others); Tue, 17 Jul 2018 12:10:04 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:38315 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729659AbeGQQKD (ORCPT ); Tue, 17 Jul 2018 12:10:03 -0400 Received: by mail-wm0-f67.google.com with SMTP id 69-v6so1982270wmf.3 for ; Tue, 17 Jul 2018 08:36:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fC+XzcCMuHa0NwlijtZDtzKiiO/sBgP44HcxjZomirU=; b=IoGwjha9L42hBY6OWP/w8bAELTH0HSjDS+pCrUcCg/clcb3T4k7l/hfpA85uc2AU7l whJgabjZwfZLZHBba4wP9mV6NGc+HcRAz+e3wKRhpXyNmPznbbfUdUbZ2Dj+R4PBrDjy Bg9H2C8eNc1yofMRhskD7Q6lvm/kM6nl84G2S7CGvE//NAFLxGbwwtulq54OwUXn9Wkv 3F7+ZsWHpdHn86uCf0m1RxbYQhLAN+CdhGDebvPbkit47ybNSktTcUhl9muISf9MFWR9 g5OBsppyEpxk7sD4iTpdTOXyvNut0fyXY+32dHSbG5PIPSdVWp0PSi5vgOvFI1v0icvC MFcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fC+XzcCMuHa0NwlijtZDtzKiiO/sBgP44HcxjZomirU=; b=MsNr4T1O/R7gIRQ/G3oxSZS69Y4K96U9huQbmUslHtbOh5BzbtxjqrQcCLOWSHPfnv 6pjL9N0px5b6gj3hMPhSPCfHiGKKxDZN8UChOJFAytTSR0MWjBFWBFQejeCVlp+HGD5m iu1BIP5E7o54dlnHQte96wMvQA3XbwN6cWXBHOWzPSurkSbDUX9/ZJEjAdFeAMKJqGGv uPFaLYz6esVK5ioGG6ykL47tAgi/eoJ/ImxHxGP4+vT5PvLwTv83GoTXZI8QeoBWdiOy IPuQ47ONoeG/T5x1I1wyRtAMVdNvDiJqjwL81iYgheZM+hAh3gPXaMcUd9IZPG0Qtf+n Vddg== X-Gm-Message-State: AOUpUlGqiF3KDDjuD22FIayv4mo7nlgXMg8+5MxuyrMQ6PPtQKhvDMZN Jyy+FnVVoR0yVAY46hZf6VFxow== X-Received: by 2002:a1c:d942:: with SMTP id q63-v6mr1792586wmg.78.1531841809316; Tue, 17 Jul 2018 08:36:49 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.36.48 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:36:48 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 02/15] ASoC: meson: add axg fifo base driver Date: Tue, 17 Jul 2018 17:36:26 +0200 Message-Id: <20180717153643.8806-3-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Amlogic's axg SoCs have two types of fifos which are the memory interfaces of the audio subsystem. FRDDR provides the playback interface while TODDR provides the capture interface. The way these fifos operate is very similar. Only a few settings are specific to each. They implement the same pcm driver here and the specifics of each will be dealt with the related DAI driver. Signed-off-by: Jerome Brunet --- sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/meson/Kconfig | 8 ++ sound/soc/meson/Makefile | 5 + sound/soc/meson/axg-fifo.c | 341 +++++++++++++++++++++++++++++++++++++++++++++ sound/soc/meson/axg-fifo.h | 80 +++++++++++ 6 files changed, 436 insertions(+) create mode 100644 sound/soc/meson/Kconfig create mode 100644 sound/soc/meson/Makefile create mode 100644 sound/soc/meson/axg-fifo.c create mode 100644 sound/soc/meson/axg-fifo.h -- 2.14.4 diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 41af6b9cc350..1cf11cf51e1d 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -57,6 +57,7 @@ source "sound/soc/kirkwood/Kconfig" source "sound/soc/img/Kconfig" source "sound/soc/intel/Kconfig" source "sound/soc/mediatek/Kconfig" +source "sound/soc/meson/Kconfig" source "sound/soc/mxs/Kconfig" source "sound/soc/pxa/Kconfig" source "sound/soc/qcom/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 06389a5385d7..62a5f87c3cfc 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_SND_SOC) += jz4740/ obj-$(CONFIG_SND_SOC) += img/ obj-$(CONFIG_SND_SOC) += intel/ obj-$(CONFIG_SND_SOC) += mediatek/ +obj-$(CONFIG_SND_SOC) += meson/ obj-$(CONFIG_SND_SOC) += mxs/ obj-$(CONFIG_SND_SOC) += nuc900/ obj-$(CONFIG_SND_SOC) += omap/ diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig new file mode 100644 index 000000000000..c3eb5e050308 --- /dev/null +++ b/sound/soc/meson/Kconfig @@ -0,0 +1,8 @@ +menu "ASoC support for Amlogic platforms" + depends on ARCH_MESON || COMPILE_TEST + +config SND_MESON_AXG_FIFO + tristate + select REGMAP_MMIO + +endmenu diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile new file mode 100644 index 000000000000..75289b6b3ade --- /dev/null +++ b/sound/soc/meson/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: (GPL-2.0 OR MIT) + +snd-soc-meson-axg-fifo-objs := axg-fifo.o + +obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c new file mode 100644 index 000000000000..db367d85290f --- /dev/null +++ b/sound/soc/meson/axg-fifo.c @@ -0,0 +1,341 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright (c) 2018 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "axg-fifo.h" + +/* + * This file implements the platform operations common to the playback and + * capture frontend DAI. The logic behind this two types of fifo is very + * similar but some difference exist. + * These differences the respective DAI drivers + */ + +static struct snd_pcm_hardware axg_fifo_hw = { + .info = (SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_PAUSE), + + .formats = AXG_FIFO_FORMATS, + .rate_min = 5512, + .rate_max = 192000, + .channels_min = 1, + .channels_max = AXG_FIFO_CH_MAX, + .period_bytes_min = AXG_FIFO_MIN_DEPTH, + .period_bytes_max = UINT_MAX, + .periods_min = 2, + .periods_max = UINT_MAX, + + /* No real justification for this */ + .buffer_bytes_max = 1 * 1024 * 1024, +}; + +static struct snd_soc_dai *axg_fifo_dai(struct snd_pcm_substream *ss) +{ + struct snd_soc_pcm_runtime *rtd = ss->private_data; + + return rtd->cpu_dai; +} + +static struct axg_fifo *axg_fifo_data(struct snd_pcm_substream *ss) +{ + struct snd_soc_dai *dai = axg_fifo_dai(ss); + + return snd_soc_dai_get_drvdata(dai); +} + +static struct device *axg_fifo_dev(struct snd_pcm_substream *ss) +{ + struct snd_soc_dai *dai = axg_fifo_dai(ss); + + return dai->dev; +} + +static void __dma_enable(struct axg_fifo *fifo, bool enable) +{ + regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_DMA_EN, + enable ? CTRL0_DMA_EN : 0); +} + +static int axg_fifo_pcm_trigger(struct snd_pcm_substream *ss, int cmd) +{ + struct axg_fifo *fifo = axg_fifo_data(ss); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + __dma_enable(fifo, true); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: + __dma_enable(fifo, false); + break; + default: + return -EINVAL; + } + + return 0; +} + +static snd_pcm_uframes_t axg_fifo_pcm_pointer(struct snd_pcm_substream *ss) +{ + struct axg_fifo *fifo = axg_fifo_data(ss); + struct snd_pcm_runtime *runtime = ss->runtime; + unsigned int addr; + + regmap_read(fifo->map, FIFO_STATUS2, &addr); + + return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr); +} + +static int axg_fifo_pcm_hw_params(struct snd_pcm_substream *ss, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = ss->runtime; + struct axg_fifo *fifo = axg_fifo_data(ss); + dma_addr_t end_ptr; + unsigned int burst_num; + int ret; + + ret = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(params)); + if (ret < 0) + return ret; + + /* Setup dma memory pointers */ + end_ptr = runtime->dma_addr + runtime->dma_bytes - AXG_FIFO_BURST; + regmap_write(fifo->map, FIFO_START_ADDR, runtime->dma_addr); + regmap_write(fifo->map, FIFO_FINISH_ADDR, end_ptr); + + /* Setup interrupt periodicity */ + burst_num = params_period_bytes(params) / AXG_FIFO_BURST; + regmap_write(fifo->map, FIFO_INT_ADDR, burst_num); + + /* Enable block count irq */ + regmap_update_bits(fifo->map, FIFO_CTRL0, + CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), + CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT)); + + return 0; +} + +static int axg_fifo_pcm_hw_free(struct snd_pcm_substream *ss) +{ + struct axg_fifo *fifo = axg_fifo_data(ss); + + /* Disable the block count irq */ + regmap_update_bits(fifo->map, FIFO_CTRL0, + CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), 0); + + return snd_pcm_lib_free_pages(ss); +} + +static void axg_fifo_ack_irq(struct axg_fifo *fifo, u8 mask) +{ + regmap_update_bits(fifo->map, FIFO_CTRL1, + CTRL1_INT_CLR(FIFO_INT_MASK), + CTRL1_INT_CLR(mask)); + + /* Clear must also be cleared */ + regmap_update_bits(fifo->map, FIFO_CTRL1, + CTRL1_INT_CLR(FIFO_INT_MASK), + 0); +} + +static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id) +{ + struct snd_pcm_substream *ss = dev_id; + struct axg_fifo *fifo = axg_fifo_data(ss); + unsigned int status; + + regmap_read(fifo->map, FIFO_STATUS1, &status); + + status = STATUS1_INT_STS(status) & FIFO_INT_MASK; + if (status & FIFO_INT_COUNT_REPEAT) + snd_pcm_period_elapsed(ss); + else + dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", + status); + + /* Ack irqs */ + axg_fifo_ack_irq(fifo, status); + + return !status ? IRQ_NONE : IRQ_HANDLED; +} + +static int axg_fifo_pcm_open(struct snd_pcm_substream *ss) +{ + struct axg_fifo *fifo = axg_fifo_data(ss); + struct device *dev = axg_fifo_dev(ss); + int ret; + + snd_soc_set_runtime_hwparams(ss, &axg_fifo_hw); + + /* + * Make sure the buffer and period size are multiple of the FIFO + * minimum depth size + */ + ret = snd_pcm_hw_constraint_step(ss->runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, + AXG_FIFO_MIN_DEPTH); + if (ret) + return ret; + + ret = snd_pcm_hw_constraint_step(ss->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, + AXG_FIFO_MIN_DEPTH); + if (ret) + return ret; + + ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0, + dev_name(dev), ss); + + /* Enable pclk to access registers and clock the fifo ip */ + ret = clk_prepare_enable(fifo->pclk); + if (ret) + return ret; + + /* Setup status2 so it reports the memory pointer */ + regmap_update_bits(fifo->map, FIFO_CTRL1, + CTRL1_STATUS2_SEL_MASK, + CTRL1_STATUS2_SEL(STATUS2_SEL_DDR_READ)); + + /* Make sure the dma is initially disabled */ + __dma_enable(fifo, false); + + /* Disable irqs until params are ready */ + regmap_update_bits(fifo->map, FIFO_CTRL0, + CTRL0_INT_EN(FIFO_INT_MASK), 0); + + /* Clear any pending interrupt */ + axg_fifo_ack_irq(fifo, FIFO_INT_MASK); + + /* Take memory arbitror out of reset */ + ret = reset_control_deassert(fifo->arb); + if (ret) + clk_disable_unprepare(fifo->pclk); + + return ret; +} + +static int axg_fifo_pcm_close(struct snd_pcm_substream *ss) +{ + struct axg_fifo *fifo = axg_fifo_data(ss); + int ret; + + /* Put the memory arbitror back in reset */ + ret = reset_control_assert(fifo->arb); + + /* Disable fifo ip and register access */ + clk_disable_unprepare(fifo->pclk); + + /* remove IRQ */ + free_irq(fifo->irq, ss); + + return ret; +} + +const struct snd_pcm_ops axg_fifo_pcm_ops = { + .open = axg_fifo_pcm_open, + .close = axg_fifo_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = axg_fifo_pcm_hw_params, + .hw_free = axg_fifo_pcm_hw_free, + .pointer = axg_fifo_pcm_pointer, + .trigger = axg_fifo_pcm_trigger, +}; +EXPORT_SYMBOL_GPL(axg_fifo_pcm_ops); + +int axg_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, unsigned int type) +{ + struct snd_card *card = rtd->card->snd_card; + size_t size = axg_fifo_hw.buffer_bytes_max; + + return snd_pcm_lib_preallocate_pages(rtd->pcm->streams[type].substream, + SNDRV_DMA_TYPE_DEV, card->dev, + size, size); +} +EXPORT_SYMBOL_GPL(axg_fifo_pcm_new); + +static const struct regmap_config axg_fifo_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = FIFO_STATUS2, +}; + +int axg_fifo_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct axg_fifo_match_data *data; + struct axg_fifo *fifo; + struct resource *res; + void __iomem *regs; + + data = of_device_get_match_data(dev); + if (!data) { + dev_err(dev, "failed to match device\n"); + return -ENODEV; + } + + fifo = devm_kzalloc(dev, sizeof(*fifo), GFP_KERNEL); + if (!fifo) + return -ENOMEM; + platform_set_drvdata(pdev, fifo); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + fifo->map = devm_regmap_init_mmio(dev, regs, &axg_fifo_regmap_cfg); + if (IS_ERR(fifo->map)) { + dev_err(dev, "failed to init regmap: %ld\n", + PTR_ERR(fifo->map)); + return PTR_ERR(fifo->map); + } + + fifo->pclk = devm_clk_get(dev, NULL); + if (IS_ERR(fifo->pclk)) { + if (PTR_ERR(fifo->pclk) != -EPROBE_DEFER) + dev_err(dev, "failed to get pclk: %ld\n", + PTR_ERR(fifo->pclk)); + return PTR_ERR(fifo->pclk); + } + + fifo->arb = devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(fifo->arb)) { + if (PTR_ERR(fifo->arb) != -EPROBE_DEFER) + dev_err(dev, "failed to get arb reset: %ld\n", + PTR_ERR(fifo->arb)); + return PTR_ERR(fifo->arb); + } + + fifo->irq = of_irq_get(dev->of_node, 0); + if (fifo->irq <= 0) { + dev_err(dev, "failed to get irq: %d\n", fifo->irq); + return fifo->irq; + } + + return devm_snd_soc_register_component(dev, data->component_drv, + data->dai_drv, 1); +} +EXPORT_SYMBOL_GPL(axg_fifo_probe); + +MODULE_DESCRIPTION("Amlogic AXG fifo driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h new file mode 100644 index 000000000000..cb6c4013ca33 --- /dev/null +++ b/sound/soc/meson/axg-fifo.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Copyright (c) 2018 BayLibre, SAS. + * Author: Jerome Brunet + */ + +#ifndef _MESON_AXG_FIFO_H +#define _MESON_AXG_FIFO_H + +struct clk; +struct platform_device; +struct regmap; +struct reset_control; + +struct snd_soc_component_driver; +struct snd_soc_dai; +struct snd_soc_dai_driver; +struct snd_pcm_ops; +struct snd_soc_pcm_runtime; + +#define AXG_FIFO_CH_MAX 128 +#define AXG_FIFO_RATES (SNDRV_PCM_RATE_5512 | \ + SNDRV_PCM_RATE_8000_192000) +#define AXG_FIFO_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define AXG_FIFO_BURST 8 +#define AXG_FIFO_MIN_CNT 64 +#define AXG_FIFO_MIN_DEPTH (AXG_FIFO_BURST * AXG_FIFO_MIN_CNT) + +#define FIFO_INT_ADDR_FINISH BIT(0) +#define FIFO_INT_ADDR_INT BIT(1) +#define FIFO_INT_COUNT_REPEAT BIT(2) +#define FIFO_INT_COUNT_ONCE BIT(3) +#define FIFO_INT_FIFO_ZERO BIT(4) +#define FIFO_INT_FIFO_DEPTH BIT(5) +#define FIFO_INT_MASK GENMASK(7, 0) + +#define FIFO_CTRL0 0x00 +#define CTRL0_DMA_EN BIT(31) +#define CTRL0_INT_EN(x) ((x) << 16) +#define CTRL0_SEL_MASK GENMASK(2, 0) +#define CTRL0_SEL_SHIFT 0 +#define FIFO_CTRL1 0x04 +#define CTRL1_INT_CLR(x) ((x) << 0) +#define CTRL1_STATUS2_SEL_MASK GENMASK(11, 8) +#define CTRL1_STATUS2_SEL(x) ((x) << 8) +#define STATUS2_SEL_DDR_READ 0 +#define CTRL1_THRESHOLD_MASK GENMASK(23, 16) +#define CTRL1_THRESHOLD(x) ((x) << 16) +#define CTRL1_FRDDR_DEPTH_MASK GENMASK(31, 24) +#define CTRL1_FRDDR_DEPTH(x) ((x) << 24) +#define FIFO_START_ADDR 0x08 +#define FIFO_FINISH_ADDR 0x0c +#define FIFO_INT_ADDR 0x10 +#define FIFO_STATUS1 0x14 +#define STATUS1_INT_STS(x) ((x) << 0) +#define FIFO_STATUS2 0x18 + +struct axg_fifo { + struct regmap *map; + struct clk *pclk; + struct reset_control *arb; + int irq; +}; + +struct axg_fifo_match_data { + const struct snd_soc_component_driver *component_drv; + struct snd_soc_dai_driver *dai_drv; +}; + +extern const struct snd_pcm_ops axg_fifo_pcm_ops; + +int axg_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, unsigned int type); +int axg_fifo_probe(struct platform_device *pdev); + +#endif /* _MESON_AXG_FIFO_H */ From patchwork Tue Jul 17 15:36:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142153 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3813250ljj; Tue, 17 Jul 2018 08:36:59 -0700 (PDT) X-Google-Smtp-Source: AAOMgpdLJKUtMumkU2AofH0hv65YNkUb2WfrHBrJ4BJQpNatML9TGKwxEn8Wry7A3AOH0/D3rKDq X-Received: by 2002:a62:41d6:: with SMTP id g83-v6mr1149819pfd.219.1531841819061; Tue, 17 Jul 2018 08:36:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841819; cv=none; d=google.com; s=arc-20160816; b=vrq3Z7DfBvQwgYP+6atnda6Qd8EtqYu6L/e1t9GCo58x3yTP554ksk9D2YjXS2wxo1 eN4gt78OsDBH/SVqlD6MHysWedmWl49NcOQzc3XAlhVlHHqWHEjL/90BqgArswoK5ANe 1p0mSUNGc8dokrLn7VSYMsv3JpPm7MZ3IxE4JP4PBjQk/RH3uBmoCrFkpoKHrpJavCOA bYewltc8yfONjDGwYs15Z3hz27Qw0pWugZt7cHY35bbbdMyv4OMsYMdS0on0pV4XgAbU y2Q3yys3Fa3PIj2l737AwXFcA13MVqwxcP7eL4r/2O1CZc+JozwBWgra1B3+ScwgJ+nW WJNw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=UPId3RG4WBsrstZqBfLByXfWIzs2ghU7EPNjAXXwXys=; b=Y1ua6n4WdjZnMcZPtKgMavwbbzgRMwws/XawK9l2md3kw/WqIxT1NCXZTTL3MG4sp8 JITpmefCqInBGiSoYk21PeqT9P59yTYzEAa+rlMDllaFcoi930DLmBx/UJfdfa1dS3Ir TE3cUSpFVfchrNwhp5c0GJ4GF/np+L6MBOx75KKIC4DiyAjD1efXyaC8DPMWvIqJHyjH ErPvAkK7TGWVsPQ7pJvHs8Snw3qYLB6CXKoZl17UI8ZGUPM0jQNJkPcoao8h5EWWV46E 0YDH8vBbx3tOmHjO8Ji2NCmk8/vq5MkdM5VqHNFR6fkNQVbDguV0fxLxbfSsMFvOc/m9 hHtg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=dQrcN6vI; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f16-v6si1146929pff.13.2018.07.17.08.36.58; Tue, 17 Jul 2018 08:36:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=dQrcN6vI; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730749AbeGQQKH (ORCPT + 31 others); Tue, 17 Jul 2018 12:10:07 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:33002 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729677AbeGQQKF (ORCPT ); Tue, 17 Jul 2018 12:10:05 -0400 Received: by mail-wm0-f67.google.com with SMTP id z6-v6so12862935wma.0 for ; Tue, 17 Jul 2018 08:36:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=UPId3RG4WBsrstZqBfLByXfWIzs2ghU7EPNjAXXwXys=; b=dQrcN6vIj8SVaPP0Ffxb5p+dqO8hbWpkXkJScZFU48/yVRTBrUZjeNNmQlybsjRgOU rtFY0tS0UOZcpBj2aLtkAittHwcNlC15jdllB+pf475av6y2S73egfsw+Gta7ztUJ1sc EhfhchNRCLmbVAraYP47TWhpYgDgsyXMgjaelIBsqvjvwVuY7gXSpSwS1Kyq1Zmn06YV vQfltv1y0QXAi1K3RpRfIiht5Fjpseg5t4pJ/F5qywiIE/ZQVjIhCzkLVRUO62FqZtjv 3BsBxF28K40LQjMJnMJDQdGO+MRJuMkG+5r50CElzAj6P8Ev6+GeVjFAyuNnHQGYLMan npYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=UPId3RG4WBsrstZqBfLByXfWIzs2ghU7EPNjAXXwXys=; b=HYitTWuYQVwx91jBAIOhAbmkzND0Ie30r0TS7sAeNXUlKdHxDmzs+B1h7sNLJLn6Lq WBJ3VNrPLrnn9UqUU1h/hJ3vIRbH1KcvDL7C/FSRj2MRpu/8SnhTMyYjrc8f2WW0ZfOE Nd859SEv/yslB2rBR9sNvxG4FJMXaUqennmYMku06WDi2HvHC5LHQyrIvEnWOu3s8HcJ lsgLx53plDxBq1YNl6bY//fuQHgDUARSm+aHAO7iTxMWGqXpMqfiY9RREr4K3/XuqKJ1 RfEspsTwngbibzXTbaNXTUGilD2t6vGhGkZqnCxbO/Xtvk/s9mgx2lBpiEj/CPFRtf5E MzKw== X-Gm-Message-State: AOUpUlFgBLiRS1wM8qiJTpx7TPx+1pvBlEV2YvgAjjSNUvRVex7dY3IS FeVTSgnAVDNYpfzheBE2JH/ynQ== X-Received: by 2002:a1c:3b54:: with SMTP id i81-v6mr1723009wma.143.1531841811329; Tue, 17 Jul 2018 08:36:51 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.36.50 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:36:50 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 04/15] ASoC: meson: add axg toddr driver Date: Tue, 17 Jul 2018 17:36:28 +0200 Message-Id: <20180717153643.8806-5-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add the capture memory interface of Amlogic's axg SoCs. TDM, SPDIF or PDM input devices place audio samples inside this FIFO. The FIFO content is then pushed to DDR Signed-off-by: Jerome Brunet --- sound/soc/meson/Kconfig | 7 ++ sound/soc/meson/Makefile | 2 + sound/soc/meson/axg-toddr.c | 199 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 sound/soc/meson/axg-toddr.c -- 2.14.4 diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index cdd78f62e8d7..3916060edcae 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -12,4 +12,11 @@ config SND_MESON_AXG_FRDDR Select Y or M to add support for the frontend playback interfaces embedded in the Amlogic AXG SoC family +config SND_MESON_AXG_TODDR + tristate "Amlogic AXG Capture FIFO support" + select SND_MESON_AXG_FIFO + help + Select Y or M to add support for the frontend capture interfaces + embedded in the Amlogic AXG SoC family + endmenu diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index 9c5d7d4a8e33..12edf2db2a24 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -2,6 +2,8 @@ snd-soc-meson-axg-fifo-objs := axg-fifo.o snd-soc-meson-axg-frddr-objs := axg-frddr.o +snd-soc-meson-axg-toddr-objs := axg-toddr.o obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o obj-$(CONFIG_SND_MESON_AXG_FRDDR) += snd-soc-meson-axg-frddr.o +obj-$(CONFIG_SND_MESON_AXG_TODDR) += snd-soc-meson-axg-toddr.o diff --git a/sound/soc/meson/axg-toddr.c b/sound/soc/meson/axg-toddr.c new file mode 100644 index 000000000000..c2c9bb312586 --- /dev/null +++ b/sound/soc/meson/axg-toddr.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright (c) 2018 BayLibre, SAS. +// Author: Jerome Brunet + +/* This driver implements the frontend capture DAI of AXG based SoCs */ + +#include +#include +#include +#include +#include +#include +#include + +#include "axg-fifo.h" + +#define CTRL0_TODDR_SEL_RESAMPLE BIT(30) +#define CTRL0_TODDR_EXT_SIGNED BIT(29) +#define CTRL0_TODDR_PP_MODE BIT(28) +#define CTRL0_TODDR_TYPE_MASK GENMASK(15, 13) +#define CTRL0_TODDR_TYPE(x) ((x) << 13) +#define CTRL0_TODDR_MSB_POS_MASK GENMASK(12, 8) +#define CTRL0_TODDR_MSB_POS(x) ((x) << 8) +#define CTRL0_TODDR_LSB_POS_MASK GENMASK(7, 3) +#define CTRL0_TODDR_LSB_POS(x) ((x) << 3) + +static int axg_toddr_pcm_new(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai) +{ + return axg_fifo_pcm_new(rtd, SNDRV_PCM_STREAM_CAPTURE); +} + +static int axg_toddr_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); + unsigned int type, width, msb = 31; + + /* + * NOTE: + * Almost all backend will place the MSB at bit 31, except SPDIF Input + * which will put it at index 28. When adding support for the SPDIF + * Input, we'll need to find which type of backend we are connected to. + */ + + switch (params_physical_width(params)) { + case 8: + type = 0; /* 8 samples of 8 bits */ + break; + case 16: + type = 2; /* 4 samples of 16 bits - right justified */ + break; + case 32: + type = 4; /* 2 samples of 32 bits - right justified */ + break; + default: + return -EINVAL; + } + + width = params_width(params); + + regmap_update_bits(fifo->map, FIFO_CTRL0, + CTRL0_TODDR_TYPE_MASK | + CTRL0_TODDR_MSB_POS_MASK | + CTRL0_TODDR_LSB_POS_MASK, + CTRL0_TODDR_TYPE(type) | + CTRL0_TODDR_MSB_POS(msb) | + CTRL0_TODDR_LSB_POS(msb - (width - 1))); + + return 0; +} + +static int axg_toddr_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); + unsigned int fifo_threshold; + int ret; + + /* Enable pclk to access registers and clock the fifo ip */ + ret = clk_prepare_enable(fifo->pclk); + if (ret) + return ret; + + /* Select orginal data - resampling not supported ATM */ + regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_SEL_RESAMPLE, 0); + + /* Only signed format are supported ATM */ + regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_EXT_SIGNED, + CTRL0_TODDR_EXT_SIGNED); + + /* Apply single buffer mode to the interface */ + regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_PP_MODE, 0); + + /* TODDR does not have a configurable fifo depth */ + fifo_threshold = AXG_FIFO_MIN_CNT - 1; + regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_THRESHOLD_MASK, + CTRL1_THRESHOLD(fifo_threshold)); + + return 0; +} + +static void axg_toddr_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); + + clk_disable_unprepare(fifo->pclk); +} + +static const struct snd_soc_dai_ops axg_toddr_ops = { + .hw_params = axg_toddr_dai_hw_params, + .startup = axg_toddr_dai_startup, + .shutdown = axg_toddr_dai_shutdown, +}; + +static struct snd_soc_dai_driver axg_toddr_dai_drv = { + .name = "TODDR", + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = AXG_FIFO_CH_MAX, + .rates = AXG_FIFO_RATES, + .formats = AXG_FIFO_FORMATS, + }, + .ops = &axg_toddr_ops, + .pcm_new = axg_toddr_pcm_new, +}; + +static const char * const axg_toddr_sel_texts[] = { + "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 6" +}; + +static const unsigned int axg_toddr_sel_values[] = { + 0, 1, 2, 3, 4, 6 +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(axg_toddr_sel_enum, FIFO_CTRL0, + CTRL0_SEL_SHIFT, CTRL0_SEL_MASK, + axg_toddr_sel_texts, axg_toddr_sel_values); + +static const struct snd_kcontrol_new axg_toddr_in_mux = + SOC_DAPM_ENUM("Input Source", axg_toddr_sel_enum); + +static const struct snd_soc_dapm_widget axg_toddr_dapm_widgets[] = { + SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &axg_toddr_in_mux), + SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 6", NULL, 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route axg_toddr_dapm_routes[] = { + { "Capture", NULL, "SRC SEL" }, + { "SRC SEL", "IN 0", "IN 0" }, + { "SRC SEL", "IN 1", "IN 1" }, + { "SRC SEL", "IN 2", "IN 2" }, + { "SRC SEL", "IN 3", "IN 3" }, + { "SRC SEL", "IN 4", "IN 4" }, + { "SRC SEL", "IN 6", "IN 6" }, +}; + +static const struct snd_soc_component_driver axg_toddr_component_drv = { + .dapm_widgets = axg_toddr_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(axg_toddr_dapm_widgets), + .dapm_routes = axg_toddr_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(axg_toddr_dapm_routes), + .ops = &axg_fifo_pcm_ops +}; + +static const struct axg_fifo_match_data axg_toddr_match_data = { + .component_drv = &axg_toddr_component_drv, + .dai_drv = &axg_toddr_dai_drv +}; + +static const struct of_device_id axg_toddr_of_match[] = { + { + .compatible = "amlogic,axg-toddr", + .data = &axg_toddr_match_data, + }, {} +}; +MODULE_DEVICE_TABLE(of, axg_toddr_of_match); + +static struct platform_driver axg_toddr_pdrv = { + .probe = axg_fifo_probe, + .driver = { + .name = "axg-toddr", + .of_match_table = axg_toddr_of_match, + }, +}; +module_platform_driver(axg_toddr_pdrv); + +MODULE_DESCRIPTION("Amlogic AXG capture fifo driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); From patchwork Tue Jul 17 15:36:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142165 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3814636ljj; Tue, 17 Jul 2018 08:38:13 -0700 (PDT) X-Google-Smtp-Source: AAOMgpclLTqZb1OlNpxYf6+yYyrxXJJ048Z9qlRi+mJ01VKw8uoJzYkAq/S7YdokCCVB/y4q8VvF X-Received: by 2002:a63:df04:: with SMTP id u4-v6mr2062121pgg.434.1531841893048; Tue, 17 Jul 2018 08:38:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841893; cv=none; d=google.com; s=arc-20160816; b=XxhgRlYXiWJBFbAlGLovxwRcxrqFRZPviQDig6mfkN1v6p9hIf35+6z9ik+CUcBWd7 KtQXU1Ss8xuyjSopvWeUuFmAYsPSJiCSLsEq1IivrvFqPesUK/0nxz1MyvOnVPkSn3pA 6amHZpp+wvEJ2AIKrtfKXdXyqYi2+0oVuOZpLMUoe6CbAfztu1mBKLmjk15T9riO0Zbt TdbncgW/a7FLkceJaZl5RzcwBaIC5VKaP/BeRZ8DeVo6J46gVHxIh+w6Xmn8D/idYOuk 6Ry37oj9HM5/WMyYUDOWlZdWgmgAUzP/VGkxqMadp2WcD9gOsNNb0qA7mLRLW0Qv9Q+3 2E+Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=WvkoiMqmDnjmFxMV3RNppwlvu3ygjgrJXHK5/nGUQQk=; b=BVWiSu3FdCahJjE+u6ZrGu1o9ayzgnOf8sfPJ9fIOWBgn+moNGYGCBXrzJZN0fDMHs b2KspotcY88NHIjy+IUvjJiHOLyIooHGAt0InCHufSV3ILgeM62HDb/se7lIkiw1M0qm t03koUGvMdxr16+uSuFjW1hXL/WqaM+q1DSXL1SovgSTivAwl/Y9WwNarDiiqf1gWzkF fNg6xDNM2d5JROmY50TbplGwU8iYyR2eu/rrJTyf9fecpg0u82LB6e3ZVB0oFfa29Nqw ZFjOVkAZ+QVZkr+WRg3kUpMvxulvZZIK+BtXmAnEcPTatb3xZHxNVkKxbCkvkXd4kwv7 abBw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=WDtN9BIv; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m37-v6si1072366plg.491.2018.07.17.08.38.12; Tue, 17 Jul 2018 08:38:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=WDtN9BIv; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731126AbeGQQKM (ORCPT + 31 others); Tue, 17 Jul 2018 12:10:12 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:55618 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730638AbeGQQKJ (ORCPT ); Tue, 17 Jul 2018 12:10:09 -0400 Received: by mail-wm0-f66.google.com with SMTP id f21-v6so1965582wmc.5 for ; Tue, 17 Jul 2018 08:36:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WvkoiMqmDnjmFxMV3RNppwlvu3ygjgrJXHK5/nGUQQk=; b=WDtN9BIvuz/czz6R4N4vnREckmf3Qx+ZkIItmIH6zCfydSSFIs4jmTIr08CUiugJCW D7Q3PkT/DXjp2FgPhZGyfQn63ehTCtg6Yszo3vUU6KTD87cWNlmIvVOFC7lbLfixedEt rFxWdZiJICFqSBpdkTDrpbtQBqO/YxjRrZXswltOILHTmr2Lkr34JaoakIeVhLeUvChW H66souy8sjhjknX+Qv0qulTtRWaXAWNVoDW52wHqNjjl8EMQLluPR1EdoxHQPaGjkuQs jnJyUP6KDoxtJhmVhgHmTFiEhr26VPT1TITQXiLiJejZ7ZoR7bmZ0rWGFC6HGz/ljZF8 X17w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WvkoiMqmDnjmFxMV3RNppwlvu3ygjgrJXHK5/nGUQQk=; b=XiOccFGcmoWqFX+q8W44iVXAmeiioOX9fneXUeFcO522zUJOXqX4h9DFJIL156un0v xRjh6R01cNU9OIi3I32Rwtq7r0ms7TY5LIyTFRFr2uu42TZ1kL+w+sz8ssUP2RxhGjvx +NL074So8E08/gyP45+lXKAWkS2fJKbDDtselOe/rJodJuJqXm1tVKC7MwQfc9WPLZ1d fq+u/gSg04c3B0HSNO/Sq6ngXybNtPLQulCUaVuYpDXCA1gFUWlRktweUEJbj4Sy9pPT Y04lelibvhKBIN3PN+hT2Diexun6vLp3qheerT/LmYDl3u8QBvqwl8//vF30Qu3+knxA Nybw== X-Gm-Message-State: AOUpUlGMprUJDhJEQBOJCPrAviZ/yn79rY0LqvNHsZkwoDdPQvzjVwJA 6OHQUJzDDT2OkOurkD1yMY5Emg== X-Received: by 2002:a1c:5b88:: with SMTP id p130-v6mr1735419wmb.69.1531841814606; Tue, 17 Jul 2018 08:36:54 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.36.53 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:36:53 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 06/15] ASoC: meson: add axg spdif output Date: Tue, 17 Jul 2018 17:36:31 +0200 Message-Id: <20180717153643.8806-8-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add support for the spdif output serializer of the axg SoC family Signed-off-by: Jerome Brunet --- sound/soc/meson/Kconfig | 7 + sound/soc/meson/Makefile | 2 + sound/soc/meson/axg-spdifout.c | 456 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 465 insertions(+) create mode 100644 sound/soc/meson/axg-spdifout.c -- 2.14.4 diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 3916060edcae..9408214b5854 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -19,4 +19,11 @@ config SND_MESON_AXG_TODDR Select Y or M to add support for the frontend capture interfaces embedded in the Amlogic AXG SoC family +config SND_MESON_AXG_SPDIFOUT + tristate "Amlogic AXG SPDIF Output Support" + imply SND_SOC_SPDIF + help + Select Y or M to add support for SPDIF output serializer embedded + in the Amlogic AXG SoC family + endmenu diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index 12edf2db2a24..d51ae045ef08 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -3,7 +3,9 @@ snd-soc-meson-axg-fifo-objs := axg-fifo.o snd-soc-meson-axg-frddr-objs := axg-frddr.o snd-soc-meson-axg-toddr-objs := axg-toddr.o +snd-soc-meson-axg-spdifout-objs := axg-spdifout.o obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o obj-$(CONFIG_SND_MESON_AXG_FRDDR) += snd-soc-meson-axg-frddr.o obj-$(CONFIG_SND_MESON_AXG_TODDR) += snd-soc-meson-axg-toddr.o +obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o diff --git a/sound/soc/meson/axg-spdifout.c b/sound/soc/meson/axg-spdifout.c new file mode 100644 index 000000000000..9dea528053ad --- /dev/null +++ b/sound/soc/meson/axg-spdifout.c @@ -0,0 +1,456 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright (c) 2018 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * NOTE: + * The meaning of bits SPDIFOUT_CTRL0_XXX_SEL is actually the opposite + * of what the documentation says. Manual control on V, U and C bits is + * applied when the related sel bits are cleared + */ + +#define SPDIFOUT_STAT 0x00 +#define SPDIFOUT_GAIN0 0x04 +#define SPDIFOUT_GAIN1 0x08 +#define SPDIFOUT_CTRL0 0x0c +#define SPDIFOUT_CTRL0_EN BIT(31) +#define SPDIFOUT_CTRL0_RST_OUT BIT(29) +#define SPDIFOUT_CTRL0_RST_IN BIT(28) +#define SPDIFOUT_CTRL0_USEL BIT(26) +#define SPDIFOUT_CTRL0_USET BIT(25) +#define SPDIFOUT_CTRL0_CHSTS_SEL BIT(24) +#define SPDIFOUT_CTRL0_DATA_SEL BIT(20) +#define SPDIFOUT_CTRL0_MSB_FIRST BIT(19) +#define SPDIFOUT_CTRL0_VSEL BIT(18) +#define SPDIFOUT_CTRL0_VSET BIT(17) +#define SPDIFOUT_CTRL0_MASK_MASK GENMASK(11, 4) +#define SPDIFOUT_CTRL0_MASK(x) ((x) << 4) +#define SPDIFOUT_CTRL1 0x10 +#define SPDIFOUT_CTRL1_MSB_POS_MASK GENMASK(12, 8) +#define SPDIFOUT_CTRL1_MSB_POS(x) ((x) << 8) +#define SPDIFOUT_CTRL1_TYPE_MASK GENMASK(6, 4) +#define SPDIFOUT_CTRL1_TYPE(x) ((x) << 4) +#define SPDIFOUT_PREAMB 0x14 +#define SPDIFOUT_SWAP 0x18 +#define SPDIFOUT_CHSTS0 0x1c +#define SPDIFOUT_CHSTS1 0x20 +#define SPDIFOUT_CHSTS2 0x24 +#define SPDIFOUT_CHSTS3 0x28 +#define SPDIFOUT_CHSTS4 0x2c +#define SPDIFOUT_CHSTS5 0x30 +#define SPDIFOUT_CHSTS6 0x34 +#define SPDIFOUT_CHSTS7 0x38 +#define SPDIFOUT_CHSTS8 0x3c +#define SPDIFOUT_CHSTS9 0x40 +#define SPDIFOUT_CHSTSA 0x44 +#define SPDIFOUT_CHSTSB 0x48 +#define SPDIFOUT_MUTE_VAL 0x4c + +struct axg_spdifout { + struct regmap *map; + struct clk *mclk; + struct clk *pclk; +}; + +static void axg_spdifout_enable(struct regmap *map) +{ + /* Apply both reset */ + regmap_update_bits(map, SPDIFOUT_CTRL0, + SPDIFOUT_CTRL0_RST_OUT | SPDIFOUT_CTRL0_RST_IN, + 0); + + /* Clear out reset before in reset */ + regmap_update_bits(map, SPDIFOUT_CTRL0, + SPDIFOUT_CTRL0_RST_OUT, SPDIFOUT_CTRL0_RST_OUT); + regmap_update_bits(map, SPDIFOUT_CTRL0, + SPDIFOUT_CTRL0_RST_IN, SPDIFOUT_CTRL0_RST_IN); + + /* Enable spdifout */ + regmap_update_bits(map, SPDIFOUT_CTRL0, SPDIFOUT_CTRL0_EN, + SPDIFOUT_CTRL0_EN); +} + +static void axg_spdifout_disable(struct regmap *map) +{ + regmap_update_bits(map, SPDIFOUT_CTRL0, SPDIFOUT_CTRL0_EN, 0); +} + +static int axg_spdifout_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + axg_spdifout_enable(priv->map); + return 0; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + axg_spdifout_disable(priv->map); + return 0; + + default: + return -EINVAL; + } +} + +static int axg_spdifout_digital_mute(struct snd_soc_dai *dai, int mute) +{ + struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai); + + /* Use spdif valid bit to perform digital mute */ + regmap_update_bits(priv->map, SPDIFOUT_CTRL0, SPDIFOUT_CTRL0_VSET, + mute ? SPDIFOUT_CTRL0_VSET : 0); + + return 0; +} + +static int axg_spdifout_sample_fmt(struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai); + unsigned int val; + + /* Set the samples spdifout will pull from the FIFO */ + switch (params_channels(params)) { + case 1: + val = SPDIFOUT_CTRL0_MASK(0x1); + break; + case 2: + val = SPDIFOUT_CTRL0_MASK(0x3); + break; + default: + dev_err(dai->dev, "too many channels for spdif dai: %u\n", + params_channels(params)); + return -EINVAL; + } + + regmap_update_bits(priv->map, SPDIFOUT_CTRL0, + SPDIFOUT_CTRL0_MASK_MASK, val); + + /* FIFO data are arranged in chunks of 64bits */ + switch (params_physical_width(params)) { + case 8: + /* 8 samples of 8 bits */ + val = SPDIFOUT_CTRL1_TYPE(0); + break; + case 16: + /* 4 samples of 16 bits - right justified */ + val = SPDIFOUT_CTRL1_TYPE(2); + break; + case 32: + /* 2 samples of 32 bits - right justified */ + val = SPDIFOUT_CTRL1_TYPE(4); + break; + default: + dev_err(dai->dev, "Unsupported physical width: %u\n", + params_physical_width(params)); + return -EINVAL; + } + + /* Position of the MSB in FIFO samples */ + val |= SPDIFOUT_CTRL1_MSB_POS(params_width(params) - 1); + + regmap_update_bits(priv->map, SPDIFOUT_CTRL1, + SPDIFOUT_CTRL1_MSB_POS_MASK | + SPDIFOUT_CTRL1_TYPE_MASK, val); + + regmap_update_bits(priv->map, SPDIFOUT_CTRL0, + SPDIFOUT_CTRL0_MSB_FIRST | SPDIFOUT_CTRL0_DATA_SEL, + 0); + + return 0; +} + +static int axg_spdifout_set_chsts(struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai); + unsigned int offset; + int ret; + u8 cs[4]; + u32 val; + + ret = snd_pcm_create_iec958_consumer_hw_params(params, cs, 4); + if (ret < 0) { + dev_err(dai->dev, "Creating IEC958 channel status failed %d\n", + ret); + return ret; + } + val = cs[0] | cs[1] << 8 | cs[2] << 16 | cs[3] << 24; + + /* Setup channel status A bits [31 - 0]*/ + regmap_write(priv->map, SPDIFOUT_CHSTS0, val); + + /* Clear channel status A bits [191 - 32] */ + for (offset = SPDIFOUT_CHSTS1; offset <= SPDIFOUT_CHSTS5; + offset += regmap_get_reg_stride(priv->map)) + regmap_write(priv->map, offset, 0); + + /* Setup channel status B bits [31 - 0]*/ + regmap_write(priv->map, SPDIFOUT_CHSTS6, val); + + /* Clear channel status B bits [191 - 32] */ + for (offset = SPDIFOUT_CHSTS7; offset <= SPDIFOUT_CHSTSB; + offset += regmap_get_reg_stride(priv->map)) + regmap_write(priv->map, offset, 0); + + return 0; +} + +static int axg_spdifout_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai); + unsigned int rate = params_rate(params); + int ret; + + /* 2 * 32bits per subframe * 2 channels = 128 */ + ret = clk_set_rate(priv->mclk, rate * 128); + if (ret) { + dev_err(dai->dev, "failed to set spdif clock\n"); + return ret; + } + + ret = axg_spdifout_sample_fmt(params, dai); + if (ret) { + dev_err(dai->dev, "failed to setup sample format\n"); + return ret; + } + + ret = axg_spdifout_set_chsts(params, dai); + if (ret) { + dev_err(dai->dev, "failed to setup channel status words\n"); + return ret; + } + + return 0; +} + +static int axg_spdifout_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai); + int ret; + + /* Clock the spdif output block */ + ret = clk_prepare_enable(priv->pclk); + if (ret) { + dev_err(dai->dev, "failed to enable pclk\n"); + return ret; + } + + /* Make sure the block is initially stopped */ + axg_spdifout_disable(priv->map); + + /* Insert data from bit 27 lsb first */ + regmap_update_bits(priv->map, SPDIFOUT_CTRL0, + SPDIFOUT_CTRL0_MSB_FIRST | SPDIFOUT_CTRL0_DATA_SEL, + 0); + + /* Manual control of V, C and U, U = 0 */ + regmap_update_bits(priv->map, SPDIFOUT_CTRL0, + SPDIFOUT_CTRL0_CHSTS_SEL | SPDIFOUT_CTRL0_VSEL | + SPDIFOUT_CTRL0_USEL | SPDIFOUT_CTRL0_USET, + 0); + + /* Static SWAP configuration ATM */ + regmap_write(priv->map, SPDIFOUT_SWAP, 0x10); + + return 0; +} + +static void axg_spdifout_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai); + + clk_disable_unprepare(priv->pclk); +} + +static const struct snd_soc_dai_ops axg_spdifout_ops = { + .trigger = axg_spdifout_trigger, + .digital_mute = axg_spdifout_digital_mute, + .hw_params = axg_spdifout_hw_params, + .startup = axg_spdifout_startup, + .shutdown = axg_spdifout_shutdown, +}; + +static struct snd_soc_dai_driver axg_spdifout_dai_drv[] = { + { + .name = "SPDIF Output", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = (SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_176400 | + SNDRV_PCM_RATE_192000), + .formats = (SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_LE | + SNDRV_PCM_FMTBIT_S24_LE), + }, + .ops = &axg_spdifout_ops, + }, +}; + +static const char * const spdifout_sel_texts[] = { + "IN 0", "IN 1", "IN 2", +}; + +static SOC_ENUM_SINGLE_DECL(axg_spdifout_sel_enum, SPDIFOUT_CTRL1, 24, + spdifout_sel_texts); + +static const struct snd_kcontrol_new axg_spdifout_in_mux = + SOC_DAPM_ENUM("Input Source", axg_spdifout_sel_enum); + +static const struct snd_soc_dapm_widget axg_spdifout_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &axg_spdifout_in_mux), +}; + +static const struct snd_soc_dapm_route axg_spdifout_dapm_routes[] = { + { "SRC SEL", "IN 0", "IN 0" }, + { "SRC SEL", "IN 1", "IN 1" }, + { "SRC SEL", "IN 2", "IN 2" }, + { "Playback", NULL, "SRC SEL" }, +}; + +static const struct snd_kcontrol_new axg_spdifout_controls[] = { + SOC_DOUBLE("Playback Volume", SPDIFOUT_GAIN0, 0, 8, 255, 0), + SOC_DOUBLE("Playback Switch", SPDIFOUT_CTRL0, 22, 21, 1, 1), + SOC_SINGLE("Playback Gain Enable Switch", + SPDIFOUT_CTRL1, 26, 1, 0), + SOC_SINGLE("Playback Channels Mix Switch", + SPDIFOUT_CTRL0, 23, 1, 0), +}; + +static int axg_spdifout_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + struct axg_spdifout *priv = snd_soc_component_get_drvdata(component); + enum snd_soc_bias_level now = + snd_soc_component_get_bias_level(component); + int ret = 0; + + switch (level) { + case SND_SOC_BIAS_PREPARE: + if (now == SND_SOC_BIAS_STANDBY) + ret = clk_prepare_enable(priv->mclk); + break; + + case SND_SOC_BIAS_STANDBY: + if (now == SND_SOC_BIAS_PREPARE) + clk_disable_unprepare(priv->mclk); + break; + + case SND_SOC_BIAS_OFF: + case SND_SOC_BIAS_ON: + break; + } + + return ret; +} + +static const struct snd_soc_component_driver axg_spdifout_component_drv = { + .controls = axg_spdifout_controls, + .num_controls = ARRAY_SIZE(axg_spdifout_controls), + .dapm_widgets = axg_spdifout_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(axg_spdifout_dapm_widgets), + .dapm_routes = axg_spdifout_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(axg_spdifout_dapm_routes), + .set_bias_level = axg_spdifout_set_bias_level, +}; + +static const struct regmap_config axg_spdifout_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = SPDIFOUT_MUTE_VAL, +}; + +static const struct of_device_id axg_spdifout_of_match[] = { + { .compatible = "amlogic,axg-spdifout", }, + {} +}; +MODULE_DEVICE_TABLE(of, axg_spdifout_of_match); + +static int axg_spdifout_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct axg_spdifout *priv; + struct resource *res; + void __iomem *regs; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + platform_set_drvdata(pdev, priv); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + priv->map = devm_regmap_init_mmio(dev, regs, &axg_spdifout_regmap_cfg); + if (IS_ERR(priv->map)) { + dev_err(dev, "failed to init regmap: %ld\n", + PTR_ERR(priv->map)); + return PTR_ERR(priv->map); + } + + priv->pclk = devm_clk_get(dev, "pclk"); + if (IS_ERR(priv->pclk)) { + ret = PTR_ERR(priv->pclk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get pclk: %d\n", ret); + return ret; + } + + priv->mclk = devm_clk_get(dev, "mclk"); + if (IS_ERR(priv->mclk)) { + ret = PTR_ERR(priv->mclk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get mclk: %d\n", ret); + return ret; + } + + return devm_snd_soc_register_component(dev, &axg_spdifout_component_drv, + axg_spdifout_dai_drv, ARRAY_SIZE(axg_spdifout_dai_drv)); +} + +static struct platform_driver axg_spdifout_pdrv = { + .probe = axg_spdifout_probe, + .driver = { + .name = "axg-spdifout", + .of_match_table = axg_spdifout_of_match, + }, +}; +module_platform_driver(axg_spdifout_pdrv); + +MODULE_DESCRIPTION("Amlogic AXG SPDIF Output driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); From patchwork Tue Jul 17 15:36:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142168 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3815068ljj; Tue, 17 Jul 2018 08:38:32 -0700 (PDT) X-Google-Smtp-Source: AAOMgpf4IxqIDgcJ5a9vMNQkl0dc7JHhKtaZGERsv9s6wrxBBKznHDtProKMwK3l+zPONajP8k3E X-Received: by 2002:a62:1815:: with SMTP id 21-v6mr1171245pfy.227.1531841911913; Tue, 17 Jul 2018 08:38:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841911; cv=none; d=google.com; s=arc-20160816; b=p1i2f3/DyYwNjs09BZiQthH09JMxPMhMRSYlvhjHR1iF0rkYbEhElCuQCUeTkzgsPI Y5ub1YCJMSD8FtpvprP1IN/jZkIk7baHaqe51QI9G3H8v3C+f8fcUE4aSN3KmWyuYoW+ D/f1w20h7UeikOcRol8NoOXsSOjV6N6wjN6WYdSFBAK6GvZ0bWO9kxOTGa20zPpEJaFu 6YvG7ULaoQjrii/xSu06rQyoWa9IJxMd8riT23P1GFyaoiKpsiEOgiEan2EsyJbtLKDa X2oiSdK6J+55yMqqneWx13QCaRU4Tc6z0m2BOQr2LSZp8RBkvj2EXD11e0uZ0cFGRAj8 Xjyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=12Tv3Q/nsmVkP07JHXVAe92gfJ5PlgKfbwQM/5tbbp8=; b=oDogqwynTR/BRIX72T90vLNo0CUk3I98UYLMkaMaMxs32C4MlD8ybqPY3KzJMF6bnt Y3fNX2ZNg43DcDj9wa1wZb0W7Nv9jSKVWglA3yYEC+aGPTRKQTh7q7gnf7wx8O8B9YKe GpOHq8UcdO8rZhTvvhSSSTAsH+VXorpSO+0lNvHm+pbQp4OExagHGxb5HUKY2i6KoCLD fbTj/QROoW6Ei/lDIE0Up7dlkVPIY8mQCK32HSR4qIpyvlT6ciQjge+eSxPtesLhFpSm 48vIAf/OqDZ9Tfpio3kEdCXeG0dvgHNl54VvPEnkODAqPSN57msJW5JipuY2JLvo26vl 5otg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=rsuc+sQ8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g10-v6si1131585pge.694.2018.07.17.08.38.31; Tue, 17 Jul 2018 08:38:31 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=rsuc+sQ8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730919AbeGQQKL (ORCPT + 31 others); Tue, 17 Jul 2018 12:10:11 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:51782 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730795AbeGQQKK (ORCPT ); Tue, 17 Jul 2018 12:10:10 -0400 Received: by mail-wm0-f67.google.com with SMTP id s12-v6so1983984wmc.1 for ; Tue, 17 Jul 2018 08:36:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=12Tv3Q/nsmVkP07JHXVAe92gfJ5PlgKfbwQM/5tbbp8=; b=rsuc+sQ83N22uVOXm9o82UWN+urZarzQaFN9YtveJGElinZNbKrPMIdHAd6eCq/mJh 9oFTufug4w2RwIca4znrsn0N7puObnEfeAnkXhUZyDA/dteU0SFEAjeGjR4ZHuLuTXPs HeqS1o3XPPBzSNXIiy+oI9DlzFgp6eq5y4Ny4ObjijCox9ViuWM6Vm9j8iSYouSlMvRD BSHTHUVChGw7wKrEWqs2l4at72gEIYhHmP2Jljm6lcgwgA65YgfLH7i7JtQFjNVvaf0o wsTPYAvBi36fTdG/r7RlgxxK1FSJbZ9Irje6Nxuy65w+tSVQwxBzIhFXuuMGaFu5kcN7 Ph3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=12Tv3Q/nsmVkP07JHXVAe92gfJ5PlgKfbwQM/5tbbp8=; b=fLZ8shPkJSQnxt0HZJW1cUcxIHLSUKiZ1WEAB/o7gHG0Zqr6yRF4aksaRIrMNccBev fHUtcXwBAeS7YrOvONHMrt6MAnGekzPWExUMquni8peyMAckwO6ImZ4V+dk5shjHBY+0 sZbGh9xxs3suN5K3Al0Y4cQ+z2X//W+9DJg56Y7VH191TwdxbI5Xj4zdW7usMQbXGjAp t/SowBY4r8DqFCXh6bJD6EpXaayoJ7W8rDrcjpiZslBYiVKa7lo6hS2NeFQn+VXQCq0J HI313TOi+R6qdWjl9MuajqPX0wEzgTO8tW1Uhba2aJ7a4Hnz0tdY48JTQU66tPTwujP+ VgFA== X-Gm-Message-State: AOUpUlFy9ETISU8/CYezf1WBn1zgXkE+5efBga05zKXVVUSpd9A6Ytmu sMS3Y9x8PYG/csJqy2S4/1Jgew== X-Received: by 2002:a1c:ee5d:: with SMTP id m90-v6mr1717434wmh.107.1531841816545; Tue, 17 Jul 2018 08:36:56 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.36.55 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:36:56 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 07/15] ASoC: meson: add axg tdm formatters DT bindings documentation Date: Tue, 17 Jul 2018 17:36:33 +0200 Message-Id: <20180717153643.8806-10-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add the DT bindings documentation for axg's TDM formatters: TDMIN and TDMOUT. Signed-off-by: Jerome Brunet --- .../bindings/sound/amlogic,axg-tdm-formatters.txt | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt -- 2.14.4 diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt new file mode 100644 index 000000000000..1c1b7490554e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt @@ -0,0 +1,28 @@ +* Amlogic Audio TDM formatters + +Required properties: +- compatible: 'amlogic,axg-tdmin' or + 'amlogic,axg-tdmout' +- reg: physical base address of the controller and length of memory + mapped region. +- clocks: list of clock phandle, one for each entry clock-names. +- clock-names: should contain the following: + * "pclk" : peripheral clock. + * "sclk" : bit clock. + * "sclk_sel" : bit clock input multiplexer. + * "lrclk" : sample clock + * "lrclk_sel": sample clock input multiplexer + +Example of TDMOUT_A on the A113 SoC: + +tdmout_a: audio-controller@500 { + compatible = "amlogic,axg-tdmout"; + reg = <0x0 0x500 0x0 0x40>; + clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>, + <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; +}; From patchwork Tue Jul 17 15:36:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142155 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3813345ljj; Tue, 17 Jul 2018 08:37:03 -0700 (PDT) X-Google-Smtp-Source: AAOMgpchPDgd/3iZ0QBMO+JE64FD8WPtm9lPqzxgC3OTW8G4H/Jkk/uhBnzUivbjR7ExyVS3Wflh X-Received: by 2002:a62:ec41:: with SMTP id k62-v6mr1186261pfh.206.1531841823643; Tue, 17 Jul 2018 08:37:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841823; cv=none; d=google.com; s=arc-20160816; b=wOHsoA3yEnUm8oMyHgWjc7+JwSmDGRH5meF8sefm0OVDvBSNgoEi9lX9kD+oizw42u sWVrx3F9PE4CbIRv1aIyUyYz79QNazzyEeoerMxPFtewsJxeotv74whr1QiA2kW3qS6o VMpVEdxoFTzt5ufDiRr8udHvTN1Jt79hFlboSY90EsifnN9FGyGa2uUgOWe8g8vvxnFR 0Hbz1SXXHmTdBWX7461DCy3QAP6ZljQDOjfME03fTAg5pdnT8kyeGLLQcq1A3PG0Z59M MQzObMKl9nBPAV6lLAT6Lj4/u/iuDNnu9XRGL5p+6qsn0ysM4ZPxDU3j3EKmcu9C/G7k AFNQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=2aX4y48Nr4mxrNaEm41GH+dJkSDI+nV532cD2B8cBj8=; b=obCcnRyTeuTmg5qgqkbscCA0z5aiN/QjoSlLNe1KGl1objrSqQAIbc8c2QmSVrOqiN iuWuk2hQmCS8uuCcqjCddXtlrhWXLgQi/gBZ7tgebP/WvSZK4uBYhuJfcGQ3zn0E5UO3 dOFl5LI75GYl4uv9HvINBshn+uBojXM8CE1wJawJcn9cLvBikOuDsl/oBuPp+XYzwoZQ abfmvfIRMYthGy6L/ippXbvZJWfRSyvvyHO8qkw4wMwD/Q0lQs9GVnkWu4MIBYOCMg7V vo+PVtN9Optu0K+WApOnsNn7zST6P8W5N/QlIYK6g3gWxrvm48jAInpsLAxzYeM+K8Kn yX+g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=icSkR1+V; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l128-v6si1209328pfc.129.2018.07.17.08.37.03; Tue, 17 Jul 2018 08:37:03 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=icSkR1+V; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731193AbeGQQKM (ORCPT + 31 others); Tue, 17 Jul 2018 12:10:12 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:34288 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730811AbeGQQKM (ORCPT ); Tue, 17 Jul 2018 12:10:12 -0400 Received: by mail-wr1-f67.google.com with SMTP id c13-v6so1726882wrt.1 for ; Tue, 17 Jul 2018 08:36:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=2aX4y48Nr4mxrNaEm41GH+dJkSDI+nV532cD2B8cBj8=; b=icSkR1+VKHX+RZrGD5HIdKOa4QbHYysYIQVdHihx1ZBWcyHXBwfRSKUEqnQAab6F3p sl3pUl3of/QCUkO9KxmsL6qPEWgKI2vijvrg5XrjJVNhdF3uT98YOEiytjcGpe6G3Jj2 tNWPRS8jYTuGNsRcIPcQ5i3wcu/vZKznCjnyapGqSpDAlCUvRx/Sc8Sf239Td56GUQxk VFI2yJQLPVfHjhtyE2a/TizDNg3Y+Ce8u4YQOLd4kgfm1ws1K9ZeKGPL+ygudz5gCv2Q QFAjGQXTzvuQbc6MvKIjXBHrIOo/n2VhoEEvrJYtz8LIyOwSuO8V2z9VNCNGKhtTIGBO CpTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2aX4y48Nr4mxrNaEm41GH+dJkSDI+nV532cD2B8cBj8=; b=QPLEOX07fSHMcSOhv9kEPnCXTlSHJqRwPBvI3tCixCdANsts8pLe14wpouLGRuwbxb hcaTh5zO6F9WAyQh+NK+rQAL+4Ti0eKMjeD8pqPLbMx+jViHeJt9A40cilEPt7ZyGu79 xd9km5oQTRzFr2ieZ2P/Xd9uRNJdVX+RtIAspKoFDENgIbZX4v9YVTmQ5OgfjiXpTLWT BK+yOznI97b8H02DyB/HSQWFQDj6URKRo4xYoeuzl01ka/GDSY2hr6fsTZZewFRbH7go EQb0IfloyXwjrKXwcNloSQtgw8EbsCOrvAU/t2NWnAAXDwNU/BhdybsTOUtrYtZOql2n t43g== X-Gm-Message-State: AOUpUlGEz04hCv8DXhPtbCu82dgax5PbXVczy4TzHT6FqkK1A5sA+91e 6zZ+iJdVSa2dFEmZcYDBpXzOdw== X-Received: by 2002:a5d:6103:: with SMTP id v3-v6mr1828270wrt.265.1531841818513; Tue, 17 Jul 2018 08:36:58 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.36.57 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:36:58 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 08/15] ASoC: meson: add axg tdm interface DT bindings documentation Date: Tue, 17 Jul 2018 17:36:35 +0200 Message-Id: <20180717153643.8806-12-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add the DT bindings documentation for axg's TDM interfaces Signed-off-by: Jerome Brunet --- .../bindings/sound/amlogic,axg-tdm-iface.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,axg-tdm-iface.txt -- 2.14.4 diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-iface.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-iface.txt new file mode 100644 index 000000000000..cabfb26a5f22 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-iface.txt @@ -0,0 +1,22 @@ +* Amlogic Audio TDM Interfaces + +Required properties: +- compatible: 'amlogic,axg-tdm-iface' +- clocks: list of clock phandle, one for each entry clock-names. +- clock-names: should contain the following: + * "sclk" : bit clock. + * "lrclk": sample clock + * "mclk" : master clock + -> optional if the interface is in clock slave mode. +- #sound-dai-cells: must be 0. + +Example of TDM_A on the A113 SoC: + +tdmif_a: audio-controller@0 { + compatible = "amlogic,axg-tdm-iface"; + #sound-dai-cells = <0>; + clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>, + <&clkc_audio AUD_CLKID_MST_A_SCLK>, + <&clkc_audio AUD_CLKID_MST_A_LRCLK>; + clock-names = "mclk", "sclk", "lrclk"; +}; From patchwork Tue Jul 17 15:36:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142161 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3814208ljj; Tue, 17 Jul 2018 08:37:49 -0700 (PDT) X-Google-Smtp-Source: AAOMgpcKnMZJDZUPUScz6LdQGVun2y1zh2YLBAruWmKAtBvdJHDPSyblR7v/OWHg3cBAdr2mBjUs X-Received: by 2002:a62:fb05:: with SMTP id x5-v6mr1204205pfm.210.1531841869280; Tue, 17 Jul 2018 08:37:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841869; cv=none; d=google.com; s=arc-20160816; b=Okh1zqMvvg00+YR0IIlAUsh15a973Z5fx/vc77fQjhcMZvNfbItd+XYCIrxjGPrWfw I+WC85CyjLAXKwILmU3LSuJ5LMSDRhWlfYP0CTH+k3ttsVmZLfLNW9YNJq1PnMU75/xV g7j7QoGSwhkYADGjj97nD6dKjrq1lnh4yxv1anoes6T5IWbokZmzAUQ8+Uknlri/T0y6 ZDA1+c+wbSbflIpnD0RmetBDeChDD1T5f9BLEZ3E2OH57bACEQjAcnJYOY9TPjVu6unR aKpBkqdFo89rlwPorIOcdUF9t5XNEMkqQpgCPCXpl8nVdgpKTNxWq6PgF6uPOIUdGCNi /9dw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=YWzx6WQNW9Bzj3tVg8EpFPsjv6MBgDW2jvjTa29j8eg=; b=H3nw7fbyMeZ742GPVzNHbfh7/5DYq4kblTFxy5zYV9vv+zPG3NCg3mm9JgHlkRB2Ew ZSw2l032s5P+IC8NmMYUar14RKFzn/aBh/8DZgMRj/gjDZdRWfMbGEMsQq3hgfjj3ZvF Y4Acb99id6D2yxhjxWTJjfkAZFEsxNV/lRKasSCF42T02gnfGnhb8dYPOpxwxVIqj+TN tLXwlcmOBdo8RSC40dACdaganmtbU6DAOQhaMBukANqgC2ohXewXvsSb7tcw+uNRMf0l x6zmPo2iJfNbg3h2zidUMCE1lKQoQC1ciz68mA+2v4iX5tBD0F9pbrznWG8k7Au9h2jd /eLQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=sJg72sW4; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l71-v6si1240464pfb.69.2018.07.17.08.37.48; Tue, 17 Jul 2018 08:37:49 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=sJg72sW4; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731336AbeGQQKR (ORCPT + 31 others); Tue, 17 Jul 2018 12:10:17 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:35190 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730811AbeGQQKQ (ORCPT ); Tue, 17 Jul 2018 12:10:16 -0400 Received: by mail-wm0-f65.google.com with SMTP id y22-v6so2009838wma.0 for ; Tue, 17 Jul 2018 08:37:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=YWzx6WQNW9Bzj3tVg8EpFPsjv6MBgDW2jvjTa29j8eg=; b=sJg72sW4T1TEQwtVDgkDy0e+lynNHMX6ayN/quvqW65agBYDqAwrPo46JfqktoUitR fcs5A3+dj2hPOlqM592u1FYx4TAGGqYNl8lCsd8m4RpUtu9CNbUVj54ZLpnaagxYT1he AOrqO/p0XcOwl+S5/StUdT0CPPNLFGhZMwpzToxqObrjemj56CNUBfR5XtfvJaLc3ru/ kNBBXe9QnlHdiE2p3KzDV7xkwMTfZcb8AwnZkNFEwCnYTgfVkS25wTA+GeMjSSv+cR2D pSK4DbJO64sspcDQtzhdSZcS9N0Oy+UgvtxevfTMC1mLI3ptkRWYCjCjI17DsXGEoKmx /djw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=YWzx6WQNW9Bzj3tVg8EpFPsjv6MBgDW2jvjTa29j8eg=; b=V1taxemh2W5qvFLFrXy8GZf7WfN2/9vBnIxkDQ+7Z9JNmHayrDA4jXsstuEemTweYs xyDSe3nWT91tUskoYXg++4UMe9ekCqrcunibfGKaCmNNh5SYWMyZt5Wt3lkFH1bUCJbQ NnilScl45Bg14rAklaUDHFSM+g6TjnizZs4LdSr1pG/SZxJmsiETBlCThj5IH1ZFHkR2 dAFRLAeFqtsR9JQizkdf5nnFHSJ4vzlceCktsPElYBDHwsgiwGJWFU+915+5YWaefvNH ec5IYBDsRTYyNfV82PgXhlUhM1PS5wp61/wLD8/30GBgaPXsE07W9S94zzHxyYRkC2ZM KJTw== X-Gm-Message-State: AOUpUlEyXKI8fgj4ROFyGzkOE4fYLW3hFfvTLURSfNoYmpkmh+65nogI +/IuQejgstDdzyGO3V8VRBxDWw== X-Received: by 2002:a1c:180e:: with SMTP id 14-v6mr1735531wmy.120.1531841820760; Tue, 17 Jul 2018 08:37:00 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.36.59 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:37:00 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 10/15] ASoC: meson: add tdm interface driver Date: Tue, 17 Jul 2018 17:36:37 +0200 Message-Id: <20180717153643.8806-14-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add Amlogic's axg TDM interface driver. This driver manages the format and clocks provided on the pads. On this SoC, each stream direction provides 4 serial lanes. This makes a maximum of 8 channels in i2s modes and 128 channels in DSP modes. While each lanes operate on the same slot number (same bit clock), they may have different TDM masks. This requires to provide a function to let the card set the 4 masks, in lieu of the usual set_tdm_slots() callback of the dai driver. Signed-off-by: Jerome Brunet --- sound/soc/meson/Kconfig | 4 + sound/soc/meson/Makefile | 2 + sound/soc/meson/axg-tdm-interface.c | 542 ++++++++++++++++++++++++++++++++++++ sound/soc/meson/axg-tdm.h | 4 + 4 files changed, 552 insertions(+) create mode 100644 sound/soc/meson/axg-tdm-interface.c -- 2.14.4 diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 80a88689491f..869b359c2ce7 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -23,6 +23,10 @@ config SND_MESON_AXG_TDM_FORMATTER tristate select REGMAP_MMIO +config SND_MESON_AXG_TDM_INTERFACE + tristate + select SND_MESON_AXG_TDM_FORMATTER + config SND_MESON_AXG_SPDIFOUT tristate "Amlogic AXG SPDIF Output Support" imply SND_SOC_SPDIF diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index a06b56a1c995..1a8eb77402e3 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -4,10 +4,12 @@ snd-soc-meson-axg-fifo-objs := axg-fifo.o snd-soc-meson-axg-frddr-objs := axg-frddr.o snd-soc-meson-axg-toddr-objs := axg-toddr.o snd-soc-meson-axg-tdm-formatter-objs := axg-tdm-formatter.o +snd-soc-meson-axg-tdm-interface-objs := axg-tdm-interface.o snd-soc-meson-axg-spdifout-objs := axg-spdifout.o obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o obj-$(CONFIG_SND_MESON_AXG_FRDDR) += snd-soc-meson-axg-frddr.o obj-$(CONFIG_SND_MESON_AXG_TODDR) += snd-soc-meson-axg-toddr.o obj-$(CONFIG_SND_MESON_AXG_TDM_FORMATTER) += snd-soc-meson-axg-tdm-formatter.o +obj-$(CONFIG_SND_MESON_AXG_TDM_INTERFACE) += snd-soc-meson-axg-tdm-interface.o obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c new file mode 100644 index 000000000000..7b8baf46d968 --- /dev/null +++ b/sound/soc/meson/axg-tdm-interface.c @@ -0,0 +1,542 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright (c) 2018 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include +#include + +#include "axg-tdm.h" + +enum { + TDM_IFACE_PAD, + TDM_IFACE_LOOPBACK, +}; + +static unsigned int axg_tdm_slots_total(u32 *mask) +{ + unsigned int slots = 0; + int i; + + if (!mask) + return 0; + + /* Count the total number of slots provided by all 4 lanes */ + for (i = 0; i < AXG_TDM_NUM_LANES; i++) + slots += hweight32(mask[i]); + + return slots; +} + +int axg_tdm_set_tdm_slots(struct snd_soc_dai *dai, u32 *tx_mask, + u32 *rx_mask, unsigned int slots, + unsigned int slot_width) +{ + struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); + struct axg_tdm_stream *tx = (struct axg_tdm_stream *) + dai->playback_dma_data; + struct axg_tdm_stream *rx = (struct axg_tdm_stream *) + dai->capture_dma_data; + unsigned int tx_slots, rx_slots; + + tx_slots = axg_tdm_slots_total(tx_mask); + rx_slots = axg_tdm_slots_total(rx_mask); + + /* We should at least have a slot for a valid interface */ + if (!tx_slots && !rx_slots) { + dev_err(dai->dev, "interface has no slot\n"); + return -EINVAL; + } + + /* + * Amend the dai driver channel number and let dpcm channel merge do + * its job + */ + if (tx) { + tx->mask = tx_mask; + dai->driver->playback.channels_max = tx_slots; + } + + if (rx) { + rx->mask = rx_mask; + dai->driver->capture.channels_max = rx_slots; + } + + iface->slots = slots; + + switch (slot_width) { + case 0: + /* defaults width to 32 if not provided */ + iface->slot_width = 32; + break; + case 8: + case 16: + case 24: + case 32: + iface->slot_width = slot_width; + break; + default: + dev_err(dai->dev, "unsupported slot width: %d\n", slot_width); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(axg_tdm_set_tdm_slots); + +static int axg_tdm_iface_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); + int ret = -ENOTSUPP; + + if (dir == SND_SOC_CLOCK_OUT && clk_id == 0) { + if (!iface->mclk) { + dev_warn(dai->dev, "master clock not provided\n"); + } else { + ret = clk_set_rate(iface->mclk, freq); + if (!ret) + iface->mclk_rate = freq; + } + } + + return ret; +} + +static int axg_tdm_iface_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); + + /* These modes are not supported */ + if (fmt & (SND_SOC_DAIFMT_CBS_CFM | SND_SOC_DAIFMT_CBM_CFS)) { + dev_err(dai->dev, "only CBS_CFS and CBM_CFM are supported\n"); + return -EINVAL; + } + + /* If the TDM interface is the clock master, it requires mclk */ + if (!iface->mclk && (fmt & SND_SOC_DAIFMT_CBS_CFS)) { + dev_err(dai->dev, "cpu clock master: mclk missing\n"); + return -ENODEV; + } + + iface->fmt = fmt; + return 0; +} + +static int axg_tdm_iface_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); + struct axg_tdm_stream *ts = + snd_soc_dai_get_dma_data(dai, substream); + int ret; + + if (!axg_tdm_slots_total(ts->mask)) { + dev_err(dai->dev, "interface has not slots\n"); + return -EINVAL; + } + + /* Apply component wide rate symmetry */ + if (dai->component->active) { + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, + iface->rate); + if (ret < 0) { + dev_err(dai->dev, + "can't set iface rate constraint\n"); + return ret; + } + } + + return 0; +} + +static int axg_tdm_iface_set_stream(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); + struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream); + unsigned int channels = params_channels(params); + unsigned int width = params_width(params); + + /* Save rate and sample_bits for component symmetry */ + iface->rate = params_rate(params); + + /* Make sure this interface can cope with the stream */ + if (axg_tdm_slots_total(ts->mask) < channels) { + dev_err(dai->dev, "not enough slots for channels\n"); + return -EINVAL; + } + + if (iface->slot_width < width) { + dev_err(dai->dev, "incompatible slots width for stream\n"); + return -EINVAL; + } + + /* Save the parameter for tdmout/tdmin widgets */ + ts->physical_width = params_physical_width(params); + ts->width = params_width(params); + ts->channels = params_channels(params); + + return 0; +} + +static int axg_tdm_iface_set_lrclk(struct snd_soc_dai *dai, + struct snd_pcm_hw_params *params) +{ + struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); + unsigned int ratio_num; + int ret; + + ret = clk_set_rate(iface->lrclk, params_rate(params)); + if (ret) { + dev_err(dai->dev, "setting sample clock failed: %d\n", ret); + return ret; + } + + switch (iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_RIGHT_J: + /* 50% duty cycle ratio */ + ratio_num = 1; + break; + + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + /* + * A zero duty cycle ratio will result in setting the mininum + * ratio possible which, for this clock, is 1 cycle of the + * parent bclk clock high and the rest low, This is exactly + * what we want here. + */ + ratio_num = 0; + break; + + default: + return -EINVAL; + } + + ret = clk_set_duty_cycle(iface->lrclk, ratio_num, 2); + if (ret) { + dev_err(dai->dev, + "setting sample clock duty cycle failed: %d\n", ret); + return ret; + } + + /* Set sample clock inversion */ + ret = clk_set_phase(iface->lrclk, + axg_tdm_lrclk_invert(iface->fmt) ? 180 : 0); + if (ret) { + dev_err(dai->dev, + "setting sample clock phase failed: %d\n", ret); + return ret; + } + + return 0; +} + +static int axg_tdm_iface_set_sclk(struct snd_soc_dai *dai, + struct snd_pcm_hw_params *params) +{ + struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); + unsigned long srate; + int ret; + + srate = iface->slots * iface->slot_width * params_rate(params); + + if (!iface->mclk_rate) { + /* If no specific mclk is requested, default to bit clock * 4 */ + clk_set_rate(iface->mclk, 4 * srate); + } else { + /* Check if we can actually get the bit clock from mclk */ + if (iface->mclk_rate % srate) { + dev_err(dai->dev, + "can't derive sclk %lu from mclk %lu\n", + srate, iface->mclk_rate); + return -EINVAL; + } + } + + ret = clk_set_rate(iface->sclk, srate); + if (ret) { + dev_err(dai->dev, "setting bit clock failed: %d\n", ret); + return ret; + } + + /* Set the bit clock inversion */ + ret = clk_set_phase(iface->sclk, + axg_tdm_sclk_invert(iface->fmt) ? 0 : 180); + if (ret) { + dev_err(dai->dev, "setting bit clock phase failed: %d\n", ret); + return ret; + } + + return ret; +} + +static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); + int ret; + + switch (iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_RIGHT_J: + if (iface->slots > 2) { + dev_err(dai->dev, "bad slot number for format: %d\n", + iface->slots); + return -EINVAL; + } + break; + + case SND_SOC_DAI_FORMAT_DSP_A: + case SND_SOC_DAI_FORMAT_DSP_B: + break; + + default: + dev_err(dai->dev, "unsupported dai format\n"); + return -EINVAL; + } + + ret = axg_tdm_iface_set_stream(substream, params, dai); + if (ret) + return ret; + + if (iface->fmt & SND_SOC_DAIFMT_CBS_CFS) { + ret = axg_tdm_iface_set_sclk(dai, params); + if (ret) + return ret; + + ret = axg_tdm_iface_set_lrclk(dai, params); + if (ret) + return ret; + } + + return 0; +} + +static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream); + + /* Stop all attached formatters */ + axg_tdm_stream_stop(ts); + + return 0; +} + +static int axg_tdm_iface_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream); + + /* Force all attached formatters to update */ + return axg_tdm_stream_reset(ts); +} + +static int axg_tdm_iface_remove_dai(struct snd_soc_dai *dai) +{ + if (dai->capture_dma_data) + axg_tdm_stream_free(dai->capture_dma_data); + + if (dai->playback_dma_data) + axg_tdm_stream_free(dai->playback_dma_data); + + return 0; +} + +static int axg_tdm_iface_probe_dai(struct snd_soc_dai *dai) +{ + struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); + + if (dai->capture_widget) { + dai->capture_dma_data = axg_tdm_stream_alloc(iface); + if (!dai->capture_dma_data) + return -ENOMEM; + } + + if (dai->playback_widget) { + dai->playback_dma_data = axg_tdm_stream_alloc(iface); + if (!dai->playback_dma_data) { + axg_tdm_iface_remove_dai(dai); + return -ENOMEM; + } + } + + return 0; +} + +static const struct snd_soc_dai_ops axg_tdm_iface_ops = { + .set_sysclk = axg_tdm_iface_set_sysclk, + .set_fmt = axg_tdm_iface_set_fmt, + .startup = axg_tdm_iface_startup, + .hw_params = axg_tdm_iface_hw_params, + .prepare = axg_tdm_iface_prepare, + .hw_free = axg_tdm_iface_hw_free, +}; + +/* TDM Backend DAIs */ +static const struct snd_soc_dai_driver axg_tdm_iface_dai_drv[] = { + [TDM_IFACE_PAD] = { + .name = "TDM Pad", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = AXG_TDM_CHANNEL_MAX, + .rates = AXG_TDM_RATES, + .formats = AXG_TDM_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = AXG_TDM_CHANNEL_MAX, + .rates = AXG_TDM_RATES, + .formats = AXG_TDM_FORMATS, + }, + .id = TDM_IFACE_PAD, + .ops = &axg_tdm_iface_ops, + .probe = axg_tdm_iface_probe_dai, + .remove = axg_tdm_iface_remove_dai, + }, + [TDM_IFACE_LOOPBACK] = { + .name = "TDM Loopback", + .capture = { + .stream_name = "Loopback", + .channels_min = 1, + .channels_max = AXG_TDM_CHANNEL_MAX, + .rates = AXG_TDM_RATES, + .formats = AXG_TDM_FORMATS, + }, + .id = TDM_IFACE_LOOPBACK, + .ops = &axg_tdm_iface_ops, + .probe = axg_tdm_iface_probe_dai, + .remove = axg_tdm_iface_remove_dai, + }, +}; + +static int axg_tdm_iface_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + struct axg_tdm_iface *iface = snd_soc_component_get_drvdata(component); + enum snd_soc_bias_level now = + snd_soc_component_get_bias_level(component); + int ret = 0; + + switch (level) { + case SND_SOC_BIAS_PREPARE: + if (now == SND_SOC_BIAS_STANDBY) + ret = clk_prepare_enable(iface->mclk); + break; + + case SND_SOC_BIAS_STANDBY: + if (now == SND_SOC_BIAS_PREPARE) + clk_disable_unprepare(iface->mclk); + break; + + case SND_SOC_BIAS_OFF: + case SND_SOC_BIAS_ON: + break; + } + + return ret; +} + +static const struct snd_soc_component_driver axg_tdm_iface_component_drv = { + .set_bias_level = axg_tdm_iface_set_bias_level, +}; + +static const struct of_device_id axg_tdm_iface_of_match[] = { + { .compatible = "amlogic,axg-tdm-iface", }, + {} +}; +MODULE_DEVICE_TABLE(of, axg_tdm_iface_of_match); + +static int axg_tdm_iface_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct snd_soc_dai_driver *dai_drv; + struct axg_tdm_iface *iface; + int ret, i; + + iface = devm_kzalloc(dev, sizeof(*iface), GFP_KERNEL); + if (!iface) + return -ENOMEM; + platform_set_drvdata(pdev, iface); + + /* + * Duplicate dai driver: depending on the slot masks configuration + * We'll change the number of channel provided by DAI stream, so dpcm + * channel merge can be done properly + */ + dai_drv = devm_kcalloc(dev, ARRAY_SIZE(axg_tdm_iface_dai_drv), + sizeof(*dai_drv), GFP_KERNEL); + if (!dai_drv) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(axg_tdm_iface_dai_drv); i++) + memcpy(&dai_drv[i], &axg_tdm_iface_dai_drv[i], + sizeof(*dai_drv)); + + /* Bit clock provided on the pad */ + iface->sclk = devm_clk_get(dev, "sclk"); + if (IS_ERR(iface->sclk)) { + ret = PTR_ERR(iface->sclk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get sclk: %d\n", ret); + return ret; + } + + /* Sample clock provided on the pad */ + iface->lrclk = devm_clk_get(dev, "lrclk"); + if (IS_ERR(iface->lrclk)) { + ret = PTR_ERR(iface->lrclk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get lrclk: %d\n", ret); + return ret; + } + + /* + * mclk maybe be missing when the cpu dai is in slave mode and + * the codec does not require it to provide a master clock. + * At this point, ignore the error if mclk is missing. We'll + * throw an error if the cpu dai is master and mclk is missing + */ + iface->mclk = devm_clk_get(dev, "mclk"); + if (IS_ERR(iface->mclk)) { + ret = PTR_ERR(iface->mclk); + if (ret == -ENOENT) { + iface->mclk = NULL; + } else { + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get mclk: %d\n", ret); + return ret; + } + } + + return devm_snd_soc_register_component(dev, + &axg_tdm_iface_component_drv, dai_drv, + ARRAY_SIZE(axg_tdm_iface_dai_drv)); +} + +static struct platform_driver axg_tdm_iface_pdrv = { + .probe = axg_tdm_iface_probe, + .driver = { + .name = "axg-tdm-iface", + .of_match_table = axg_tdm_iface_of_match, + }, +}; +module_platform_driver(axg_tdm_iface_pdrv); + +MODULE_DESCRIPTION("Amlogic AXG TDM interface driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/meson/axg-tdm.h b/sound/soc/meson/axg-tdm.h index 435d95b86457..e578b6f40a07 100644 --- a/sound/soc/meson/axg-tdm.h +++ b/sound/soc/meson/axg-tdm.h @@ -71,4 +71,8 @@ static inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts) return axg_tdm_stream_start(ts); } +int axg_tdm_set_tdm_slots(struct snd_soc_dai *dai, u32 *tx_mask, + u32 *rx_mask, unsigned int slots, + unsigned int slot_width); + #endif /* _MESON_AXG_TDM_H */ From patchwork Tue Jul 17 15:36:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142162 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3814319ljj; Tue, 17 Jul 2018 08:37:55 -0700 (PDT) X-Google-Smtp-Source: AAOMgpe3NMbUR2Vm/PC2pwfFOpD0za/YYSdnwOb/U+/VOxO5tJcVoCV1NCrtah9+Rzo3WKAuswvn X-Received: by 2002:a17:902:26c:: with SMTP id 99-v6mr2057380plc.341.1531841875623; Tue, 17 Jul 2018 08:37:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841875; cv=none; d=google.com; s=arc-20160816; b=k+1kiSgeirIJBObuTQoc8xI902b/yy7oe9NCnx8oPS0wiV/ka9Ug6IqnpTLa2+Dgz4 tFDBUVkHqZJHMSk/UFsVFCE/gu08gXN4iTe4GwGkfkcEp7/y7n13EUq/U3YZ4vI1oJ+r qQrX2LP9QoY+8XlbQrBiNPxzc47b62wtaomgYQqQkazCh5fynHiAYBfjWmlRfNiN0qco LVEVljn7E3gyVNXwvC9lw5z2qWbHqpn56JfAXOTRd9mhu4l8lJjVyZ3SF6Jq97X8DwKu kSrFmmvm9WptAUgTZGm/1MXeLSuy1vmx51J9WlN3yxmOR0RdnbVqBy0UzeEfQFSoSB8I gzUw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=6UPj3vQ1j6gvmWEeow3CO4NAh+lq/iftjdbDyD/f8s4=; b=kDwZpf3nvr/MCAcKFYgw8yjS/ZOEVYYswY4C0EnRgWZyN+3ulC3gMW5DI516P11T7Q vvZL1xKIbiwGtWXzYUqjNZttYcljya8G8oBSSKhrK92VZNr/O4htRUY9y6FZSv9Fv71W P1aPUHzIZZ5t5fQtnqupts450Z0qIfhhS0ghrcwHrCIuYcJkVtmB+BSe4mqEf7dwxFIX h+FXJodgLRsMoaN0C/RaBAq81U/CaHDRKn9lAlzKd0betFMqkTC7000EheLsn/QtJXjL G/GLr3U/CyW4nmIbEWMYcE6wgKXsw7+z5M1+kkDSk633Hc7sqE49eR82y1/90U8yIV8N 4z4Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=PGpMQsDL; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m37-v6si1072366plg.491.2018.07.17.08.37.54; Tue, 17 Jul 2018 08:37:55 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=PGpMQsDL; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731635AbeGQQLE (ORCPT + 31 others); Tue, 17 Jul 2018 12:11:04 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:36372 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731133AbeGQQKR (ORCPT ); Tue, 17 Jul 2018 12:10:17 -0400 Received: by mail-wm0-f66.google.com with SMTP id s14-v6so2007532wmc.1 for ; Tue, 17 Jul 2018 08:37:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6UPj3vQ1j6gvmWEeow3CO4NAh+lq/iftjdbDyD/f8s4=; b=PGpMQsDLKLZ9D0zCyS2+TTf3OoRUuPIAStVjPMUgdseMjK0grhPKcJQCl43LHwdvAn 32BMQZqsEFsjMSJDUH+Q5s3g87Fh5UB+OMDGvrg7QJiytwXROmlAKtnbTFa37v+ArqGw oVyK9IiN6e2NQ6Qbgr7uOIyPtCSuwSUWfC3KuD2lRuhRXCNGHQZyvA/k0lf9Q4tlZ/tT +0FlCmDVLOn9bAnKDZ9kPYHYWkIfrq2K+nbxZyUrDh/1ZmV8PXGk9ZYfQcDGZv5xPei4 qQ0Pg8fDNWxoMfjW60LtjmIOAadisyHdQjt5EMKxbgMEw9TFvvh7v55A5yI+EtpfUeZG c7aQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6UPj3vQ1j6gvmWEeow3CO4NAh+lq/iftjdbDyD/f8s4=; b=FGsLXcydDZdFvZHcFS+q6ZjDNRwcGPLUx848oy1X9rn8XIpSfw9+mjwpCiBY8g4Csb OJhSGutATBghPwm/EIekTlTfgJARRM67/BYEEf4iszn118jRqnDuTlHpXyC0MbyTWgYU KTanJpzHuBdU6BhLfi/0yIstQCVduSrfpBX/jJEIVOfaLwd3UIcUEZoKrnijqN25kOpT xgAY8Mbjz7zhb29xz5BFz6/XxaQS7I20N36Q8gNzYO0X8hIUvHPu+VyaqwqkM7hwadqg +w3F77F6ZVy3gm9eyYCnYjqavF4CU8R9CNED+N08Br/DeM7p6J2w41aCDMASZOAsnjNz n2Pg== X-Gm-Message-State: AOUpUlEXYkRbq3SBX2p3EJlb8bGr/iuHgPxj8GPCRQQ1GBm51ucqi1zt ehc+IuZU+47fidHWclXXxz4q+g== X-Received: by 2002:a1c:9616:: with SMTP id y22-v6mr1733500wmd.72.1531841822886; Tue, 17 Jul 2018 08:37:02 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.37.01 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:37:02 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 12/15] ASoC: meson: add tdm input driver Date: Tue, 17 Jul 2018 17:36:39 +0200 Message-Id: <20180717153643.8806-16-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add Amlogic's axg TDM input driver which take the TDM signal of 4 input lanes and push the decoded audio samples to TODDR fifo Signed-off-by: Jerome Brunet --- sound/soc/meson/Kconfig | 8 ++ sound/soc/meson/Makefile | 2 + sound/soc/meson/axg-tdmin.c | 229 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 sound/soc/meson/axg-tdmin.c -- 2.14.4 diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 08a522b77749..00d05df67b52 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -27,6 +27,14 @@ config SND_MESON_AXG_TDM_INTERFACE tristate select SND_MESON_AXG_TDM_FORMATTER +config SND_MESON_AXG_TDMIN + tristate "Amlogic AXG TDM Input Support" + select SND_MESON_AXG_TDM_FORMATTER + select SND_MESON_AXG_TDM_INTERFACE + help + Select Y or M to add support for TDM input formatter embedded + in the Amlogic AXG SoC family + config SND_MESON_AXG_TDMOUT tristate "Amlogic AXG TDM Output Support" select SND_MESON_AXG_TDM_FORMATTER diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index a665c6b76a95..f62833fb44d8 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -5,6 +5,7 @@ snd-soc-meson-axg-frddr-objs := axg-frddr.o snd-soc-meson-axg-toddr-objs := axg-toddr.o snd-soc-meson-axg-tdm-formatter-objs := axg-tdm-formatter.o snd-soc-meson-axg-tdm-interface-objs := axg-tdm-interface.o +snd-soc-meson-axg-tdmin-objs := axg-tdmin.o snd-soc-meson-axg-tdmout-objs := axg-tdmout.o snd-soc-meson-axg-spdifout-objs := axg-spdifout.o @@ -13,5 +14,6 @@ obj-$(CONFIG_SND_MESON_AXG_FRDDR) += snd-soc-meson-axg-frddr.o obj-$(CONFIG_SND_MESON_AXG_TODDR) += snd-soc-meson-axg-toddr.o obj-$(CONFIG_SND_MESON_AXG_TDM_FORMATTER) += snd-soc-meson-axg-tdm-formatter.o obj-$(CONFIG_SND_MESON_AXG_TDM_INTERFACE) += snd-soc-meson-axg-tdm-interface.o +obj-$(CONFIG_SND_MESON_AXG_TDMIN) += snd-soc-meson-axg-tdmin.o obj-$(CONFIG_SND_MESON_AXG_TDMOUT) += snd-soc-meson-axg-tdmout.o obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o diff --git a/sound/soc/meson/axg-tdmin.c b/sound/soc/meson/axg-tdmin.c new file mode 100644 index 000000000000..bbac44c81688 --- /dev/null +++ b/sound/soc/meson/axg-tdmin.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright (c) 2018 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include + +#include "axg-tdm-formatter.h" + +#define TDMIN_CTRL 0x00 +#define TDMIN_CTRL_ENABLE BIT(31) +#define TDMIN_CTRL_I2S_MODE BIT(30) +#define TDMIN_CTRL_RST_OUT BIT(29) +#define TDMIN_CTRL_RST_IN BIT(28) +#define TDMIN_CTRL_WS_INV BIT(25) +#define TDMIN_CTRL_SEL_SHIFT 20 +#define TDMIN_CTRL_IN_BIT_SKEW_MASK GENMASK(18, 16) +#define TDMIN_CTRL_IN_BIT_SKEW(x) ((x) << 16) +#define TDMIN_CTRL_LSB_FIRST BIT(5) +#define TDMIN_CTRL_BITNUM_MASK GENMASK(4, 0) +#define TDMIN_CTRL_BITNUM(x) ((x) << 0) +#define TDMIN_SWAP 0x04 +#define TDMIN_MASK0 0x08 +#define TDMIN_MASK1 0x0c +#define TDMIN_MASK2 0x10 +#define TDMIN_MASK3 0x14 +#define TDMIN_STAT 0x18 +#define TDMIN_MUTE_VAL 0x1c +#define TDMIN_MUTE0 0x20 +#define TDMIN_MUTE1 0x24 +#define TDMIN_MUTE2 0x28 +#define TDMIN_MUTE3 0x2c + +static const struct regmap_config axg_tdmin_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = TDMIN_MUTE3, +}; + +static const char * const axg_tdmin_sel_texts[] = { + "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 5", +}; + +/* Change to special mux control to reset dapm */ +static SOC_ENUM_SINGLE_DECL(axg_tdmin_sel_enum, TDMIN_CTRL, + TDMIN_CTRL_SEL_SHIFT, axg_tdmin_sel_texts); + +static const struct snd_kcontrol_new axg_tdmin_in_mux = + SOC_DAPM_ENUM("Input Source", axg_tdmin_sel_enum); + +static struct snd_soc_dai * +axg_tdmin_get_be(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_path *p = NULL; + struct snd_soc_dai *be; + + snd_soc_dapm_widget_for_each_source_path(w, p) { + if (!p->connect) + continue; + + if (p->source->id == snd_soc_dapm_dai_out) + return (struct snd_soc_dai *)p->source->priv; + + be = axg_tdmin_get_be(p->source); + if (be) + return be; + } + + return NULL; +} + +static struct axg_tdm_stream * +axg_tdmin_get_tdm_stream(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dai *be = axg_tdmin_get_be(w); + + if (!be) + return NULL; + + return be->capture_dma_data; +} + +static void axg_tdmin_enable(struct regmap *map) +{ + /* Apply both reset */ + regmap_update_bits(map, TDMIN_CTRL, + TDMIN_CTRL_RST_OUT | TDMIN_CTRL_RST_IN, 0); + + /* Clear out reset before in reset */ + regmap_update_bits(map, TDMIN_CTRL, + TDMIN_CTRL_RST_OUT, TDMIN_CTRL_RST_OUT); + regmap_update_bits(map, TDMIN_CTRL, + TDMIN_CTRL_RST_IN, TDMIN_CTRL_RST_IN); + + /* Actually enable tdmin */ + regmap_update_bits(map, TDMIN_CTRL, + TDMIN_CTRL_ENABLE, TDMIN_CTRL_ENABLE); +} + +static void axg_tdmin_disable(struct regmap *map) +{ + regmap_update_bits(map, TDMIN_CTRL, TDMIN_CTRL_ENABLE, 0); +} + +static int axg_tdmin_prepare(struct regmap *map, struct axg_tdm_stream *ts) +{ + unsigned int val = 0; + + /* Set stream skew */ + switch (ts->iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_DSP_A: + val |= TDMIN_CTRL_IN_BIT_SKEW(3); + break; + + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_DSP_B: + val = TDMIN_CTRL_IN_BIT_SKEW(2); + break; + + default: + pr_err("Unsupported format: %u\n", + ts->iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK); + return -EINVAL; + } + + /* Set stream format mode */ + switch (ts->iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_RIGHT_J: + val |= TDMIN_CTRL_I2S_MODE; + break; + } + + /* If the sample clock is inverted, invert it back for the formatter */ + if (axg_tdm_lrclk_invert(ts->iface->fmt)) + val |= TDMIN_CTRL_WS_INV; + + /* Set the slot width */ + val |= TDMIN_CTRL_BITNUM(ts->iface->slot_width - 1); + + /* + * The following also reset LSB_FIRST which result in the formatter + * placing the first bit received at bit 31 + */ + regmap_update_bits(map, TDMIN_CTRL, + (TDMIN_CTRL_IN_BIT_SKEW_MASK | TDMIN_CTRL_WS_INV | + TDMIN_CTRL_I2S_MODE | TDMIN_CTRL_LSB_FIRST | + TDMIN_CTRL_BITNUM_MASK), val); + + /* Set static swap mask configuration */ + regmap_write(map, TDMIN_SWAP, 0x76543210); + + return axg_tdm_formatter_set_channel_masks(map, ts, TDMIN_MASK0); +} + +static const struct snd_soc_dapm_widget axg_tdmin_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("IN 5", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &axg_tdmin_in_mux), + SND_SOC_DAPM_PGA_E("DEC", SND_SOC_NOPM, 0, 0, NULL, 0, + axg_tdm_formatter_event, + (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD)), + SND_SOC_DAPM_AIF_OUT("OUT", NULL, 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route axg_tdmin_dapm_routes[] = { + { "SRC SEL", "IN 0", "IN 0" }, + { "SRC SEL", "IN 1", "IN 1" }, + { "SRC SEL", "IN 2", "IN 2" }, + { "SRC SEL", "IN 3", "IN 3" }, + { "SRC SEL", "IN 4", "IN 4" }, + { "SRC SEL", "IN 5", "IN 5" }, + { "DEC", NULL, "SRC SEL" }, + { "OUT", NULL, "DEC" }, +}; + +static const struct snd_soc_component_driver axg_tdmin_component_drv = { + .dapm_widgets = axg_tdmin_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(axg_tdmin_dapm_widgets), + .dapm_routes = axg_tdmin_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(axg_tdmin_dapm_routes), +}; + +static const struct axg_tdm_formatter_ops axg_tdmin_ops = { + .get_stream = axg_tdmin_get_tdm_stream, + .prepare = axg_tdmin_prepare, + .enable = axg_tdmin_enable, + .disable = axg_tdmin_disable, +}; + +static const struct axg_tdm_formatter_driver axg_tdmin_drv = { + .component_drv = &axg_tdmin_component_drv, + .regmap_cfg = &axg_tdmin_regmap_cfg, + .ops = &axg_tdmin_ops, + .invert_sclk = false, +}; + +static const struct of_device_id axg_tdmin_of_match[] = { + { + .compatible = "amlogic,axg-tdmin", + .data = &axg_tdmin_drv, + }, {} +}; +MODULE_DEVICE_TABLE(of, axg_tdmin_of_match); + +static struct platform_driver axg_tdmin_pdrv = { + .probe = axg_tdm_formatter_probe, + .driver = { + .name = "axg-tdmin", + .of_match_table = axg_tdmin_of_match, + }, +}; +module_platform_driver(axg_tdmin_pdrv); + +MODULE_DESCRIPTION("Amlogic AXG TDM input formatter driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); From patchwork Tue Jul 17 15:36:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142157 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3813431ljj; Tue, 17 Jul 2018 08:37:08 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfge3n5sNIUx5LpPkyhbjTS0Dx0VkryqNmWfZCXpfa3B+Kgft6Y4dufMd0Q6Z75/EJP/OnL X-Received: by 2002:a62:2f84:: with SMTP id v126-v6mr1171679pfv.115.1531841828648; Tue, 17 Jul 2018 08:37:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841828; cv=none; d=google.com; s=arc-20160816; b=jGYNdWczkd7ila7GdrSi1Zph3chSfuNUaxaam1PiepL+GdHa43Ew/KCRJ34cys6dbP ByYAqQ66q3mPJJXuat0kpPkYSswvWPX9dHwIciryCCvFs4iJ3zxr7whbbEp+v08kFYrh AtgwK8t2x9ICOZRAz0uFIU5QdbfqZ2Or740B8NByfwc6lAGhLYMjBax+2yGbgdwbYGH2 BC6FdaV5kycGx9Ylszq1olriHpcTjvzC4XVDutlipCvqWkd1uWLmtcqVbbnJ92vG8ysN sbyFF2oAN74KD5MSWQF+6pvY4889Ya+p5WOXhG0EVRopLqcEmhWej17EXwfwy6Epx8mq xP+Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=yoo5n4dhpulCSFNRPHfsRmRUHZHqOi5jkgvB0Euf0Sg=; b=nb4XH+ZamGDcuWXxyM1SIb/fsbLeRazAvlD0O1USQQAVQjsYPd4tMx6g0kf9vf8/e6 m5blmjUa8OGtKRot/6lcpUEZnNL1UKE7D7XNMk5A0kuEdZ1+r0d+7v/729Lo5e8qtbsd o2uWXymkweI4MKA9mIyCA9M4rHQbayXVUPHhbLPDpZELZxOWcQp4dIxNL4Ia8TyLXBkm +7qjVMR99mKDhtWXkI82l2zAl7UTupPyE8KgPyMXDNBmkSBOl0IbP+nWM9D5Mk5EmAnI iG6NiMRQdAeLTcEyGpeXS46JepLKRSzvfrcJ2rpbekv4W9qkEXLpEF3nyKAZd1UAY67H BdcQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=mkPDfy2T; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l26-v6si1115945pfo.325.2018.07.17.08.37.08; Tue, 17 Jul 2018 08:37:08 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=mkPDfy2T; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731404AbeGQQKS (ORCPT + 31 others); Tue, 17 Jul 2018 12:10:18 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:36376 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731296AbeGQQKR (ORCPT ); Tue, 17 Jul 2018 12:10:17 -0400 Received: by mail-wm0-f68.google.com with SMTP id s14-v6so2007594wmc.1 for ; Tue, 17 Jul 2018 08:37:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=yoo5n4dhpulCSFNRPHfsRmRUHZHqOi5jkgvB0Euf0Sg=; b=mkPDfy2TrU9TpaAJ+aww5QTfB8F/rkYM23QejFTw1hkEqPzKDy2lg+uMve0YbQLe70 2k50Kd7GEPbHwdcf7Um8zihA/PArsgs7C8ivn6fY3QS5OTYSiaxZW+HuzJVD4lfupreS pajhG0hujS2nM4tQnKDLMljis0W75cLDttcGM0QEtnkqG149/7W2/3PKkYPW0tUlO7ja 39VjtWuylPqVB+Zu8nq9aGSXWU3wDAxG3dXj5Bcv1miGzWOPuGApSu8QiLUPq6H4xmlp 1M3TypZxs3buLDg9pThLuXO+vDfTWO5Mmcj0yQBotrdyLjCR1fb9AwSsdO3Zu6CqRlcc 93+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=yoo5n4dhpulCSFNRPHfsRmRUHZHqOi5jkgvB0Euf0Sg=; b=CpaxKjYyujwaqZMisYqlmncJ/u0N+gSEm9hdaYv1HMON8iCUx8iZ87lFDwyE9TL+u5 vJEVjP1DGZBHziOLZkx3Kkg5NKektLkBddyL3gAS/gegPyZ7h7Jcz8DHqRcdufud28mY /hsnx6dVtERJQeWurpLVitEVttYVZ/yesgh3ikirG14cx/b3NkUIYarsRrSChBHAjvqP hJqDyNuJ/L9AS+e5q7ArtPT9w2J2lA2v3T+W8W71RnRgojx+UUBMimLCyMW6Lh5Zk9ta 7zKn0c4IGu2J4wD+26GI3i5N3qT9a6KTZjeoQM2uYWVjfn8SnDvtj8ufHvpkTmKdKBXq IuNQ== X-Gm-Message-State: AOUpUlEhfqGM18cN8ZCaSTxQgyAcAwuL/ro23Bp0gyrWZjpj7YOntogl Dts63A/rPoeZFKPghFFNZwnpIA== X-Received: by 2002:a1c:3f08:: with SMTP id m8-v6mr1826562wma.88.1531841823914; Tue, 17 Jul 2018 08:37:03 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.37.02 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:37:03 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 13/15] ASoC: export snd_soc_of_get_slot_mask Date: Tue, 17 Jul 2018 17:36:40 +0200 Message-Id: <20180717153643.8806-17-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Amlogic's axg card driver can't use snd_soc_of_parse_tdm_slot() directly because it needs to handle 4 mask for each direction. Yet the parsing of each mask is the same, so export snd_soc_of_get_slot_mask() to reuse the the existing code. Signed-off-by: Jerome Brunet --- include/sound/soc.h | 3 +++ sound/soc/soc-core.c | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) -- 2.14.4 diff --git a/include/sound/soc.h b/include/sound/soc.h index a4915148f739..41cec42fb456 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1426,6 +1426,9 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, const char *propname); +int snd_soc_of_get_slot_mask(struct device_node *np, + const char *prop_name, + unsigned int *mask); int snd_soc_of_parse_tdm_slot(struct device_node *np, unsigned int *tx_mask, unsigned int *rx_mask, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3be0310d5c81..1344e8e602fd 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3366,9 +3366,9 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); -static int snd_soc_of_get_slot_mask(struct device_node *np, - const char *prop_name, - unsigned int *mask) +int snd_soc_of_get_slot_mask(struct device_node *np, + const char *prop_name, + unsigned int *mask) { u32 val; const __be32 *of_slot_mask = of_get_property(np, prop_name, &val); @@ -3383,6 +3383,7 @@ static int snd_soc_of_get_slot_mask(struct device_node *np, return val; } +EXPORT_SYMBOL_GPL(snd_soc_of_get_slot_mask); int snd_soc_of_parse_tdm_slot(struct device_node *np, unsigned int *tx_mask, From patchwork Tue Jul 17 15:36:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142158 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3813467ljj; Tue, 17 Jul 2018 08:37:10 -0700 (PDT) X-Google-Smtp-Source: AAOMgpe77+Pn1HvoFG9wYGzm4NcUv8EjCrL2hQaivPJGzLwRGNNrYFqO2AJDVOgcvE8fTgJw/qY1 X-Received: by 2002:a63:8341:: with SMTP id h62-v6mr2008868pge.298.1531841830490; Tue, 17 Jul 2018 08:37:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841830; cv=none; d=google.com; s=arc-20160816; b=UQjORByL8tM7WWjc8e/24E9hYFOMExmR2pTZP+A8x9niOYn5P6aBfo24+rb9IP+wVB 1vcQw6kYPw0hxwNCBDka4I/JD+poTlf8+SUXj4IHEE+OXc4tzfr1HnEg7+j3wIpRny7/ wRC5F9RJ+zLxVrgRyVU6l75xMinJTPmNL+KvzzLhJVBILeh1tu2gUMYEsJ8edXjcCSWV GDhRQZpHAkkRPHrqZwX56FuEMcA5jX2mj0kBFZdhNfk7bPw3jQBhEQx5PT/S4wxe+1iD VsWe+eavjHeU0RxsXgyW7PsDcnuJFFAUwXJ5T9TceF7knv0K5dSLEwjevUM2c98GrO+H NenA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=Gf0R91kG2d7lDzaIoH7oyEyl99OABalSiO8tr5ySzv0=; b=aCGUh9PFbJ+Wp75apDKDq5hwikq6zpRJ3q/yOH1854e+xKBgA5xcAysoaCoOXkrZ4d Mwb8MhVNo851o+Ic9XK5PHmPUR9GmH6ygdFW2cvWbOg3LO+DRzDyW9Q9hmSm1in1ePmd iGU+CuaJJ5boel7rKzC6H8EXLV0TXxAqAkNsLBzlWsj29AkHf8TRS0qgWrdaOph8W+zT HiSfxq2hYIfEJKn07MY2UYD6eJbe1+PSrpBCgOJXR8oxzuNW0n/Ow47COqJRC9nD3Lx2 qqRZP1ztynNmoDsSZNu54Z+nEcArR6sTyOgGHjR4L8p9RyuP23AdAteE9/QmNDnTtzQr 94QA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=fEIMBEKO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z13-v6si1172763pfc.118.2018.07.17.08.37.10; Tue, 17 Jul 2018 08:37:10 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=fEIMBEKO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731446AbeGQQKT (ORCPT + 31 others); Tue, 17 Jul 2018 12:10:19 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:52822 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730811AbeGQQKT (ORCPT ); Tue, 17 Jul 2018 12:10:19 -0400 Received: by mail-wm0-f67.google.com with SMTP id o11-v6so1960812wmh.2 for ; Tue, 17 Jul 2018 08:37:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Gf0R91kG2d7lDzaIoH7oyEyl99OABalSiO8tr5ySzv0=; b=fEIMBEKO2NmQ+VzmN6lPPq6zgOaL8BDCq0t7FKR550zQSX/s1c1B9HdXQyXL6gXBsz vwczuUhVVvq1Q74r7hGfbUV6f6/j3Kwj4kMnjTYyBIvS5VOVvG8Et/1CpukU2f3pT4BR FIe/2M314l2Tewx8QRpC4qi1vt4I/TJfO2m/qk1VTk0JDaqB6jQAb/U5ybnNeA18ra2U Lrq5AxOs9ijPKaUekbwqlWmWd8xQNDj7ioS6ElSFx241YI0GfAxtUNl/0qobmozI+llb LZ7cRq60UtHDwTqZfRBBicDwaOlxL3Ppf9IRjAsI26CRyLnVklSvWQtzA3kO67U8/OdR e/tg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Gf0R91kG2d7lDzaIoH7oyEyl99OABalSiO8tr5ySzv0=; b=XbV4OoZlFS4QU0jMWFPic/bllhz/BJt8v1g3MMl9UmHSXJ1zMik0dJl7eIDE5MBJP4 2k03HAgLvmhWSRu68Lmif6IcQezIhkarSwGmjwkgERQtg46iwtovLn2/gNHJHPxXOFmZ dXfZdgopfnVUVv6ihJhYACIFwCH9FiSWSC3xFH3/YH0Od0oqzpWRkEFRiWvi3dHn4Gqt Z86PWtagpogxg73idQxoBOsWjucH9F/wLSMtg4T8R2SktxDyZ9X+pXu8BKvlWHLmd3iW NFnUPifiYyAgG6ErWxan5Cm2/6A3F8ZJ1/revj6zOvdtJiBf7M1QRnmmSSR+Vf2l1GFO 57QA== X-Gm-Message-State: AOUpUlFZ9Zr1LwnZL3mCTANtVaehS/Kh9r0B7RSIN+rEYeV0AOy+Bpuc 0m2tWn59HajexHNTTScO1+lb/Q== X-Received: by 2002:a1c:ea53:: with SMTP id i80-v6mr1830568wmh.113.1531841825082; Tue, 17 Jul 2018 08:37:05 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.37.03 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:37:04 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 14/15] ASoC: meson: add axg sound card DT binding documentation Date: Tue, 17 Jul 2018 17:36:41 +0200 Message-Id: <20180717153643.8806-18-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add the DT binding documentation for axg sound card Signed-off-by: Jerome Brunet --- .../bindings/sound/amlogic,axg-sound-card.txt | 124 +++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,axg-sound-card.txt -- 2.14.4 diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-sound-card.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-sound-card.txt new file mode 100644 index 000000000000..39e005da0407 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-sound-card.txt @@ -0,0 +1,124 @@ +Amlogic AXG sound card: + +Required properties: + +- compatible: "amlogic,axg-sound-card" +- amlogic,name : User specified audio sound card name, one string + +Optional properties: + +- amlogic,aux-devs : List of phandles pointing to auxiliary devices +- amlogic,widgets : Please refer to widgets.txt. +- amlogic,routing : A list of the connections between audio components. + +Subnodes: + +- amlogic,dai-link: Container for dai-link level properties and the + CODEC sub-nodes. There should be at least one (and + probably) subnode of this type. + +Required dai-link properties: + +- sound-dai: phandle and port of the CPU DAI. + +Required TDM Backend dai-link properties: +- dai-format : CPU/CODEC common audio format + +Optional TDM Backend dai-link properties: +- dai-tdm-slot-rx-mask-{0,1,2,3}: Receive direction slot masks +- dai-tdm-slot-tx-mask-{0,1,2,3}: Transmit direction slot masks + When omitted, mask is assumed to have to no + slots. A valid must have at one slot, so at + least one these mask should be provided with + an enabled slot. +- dai-tdm-slot-num : Please refer to tdm-slot.txt. + If omitted, slot number is set to accommodate the largest + mask provided. +- dai-tdm-slot-width : Please refer to tdm-slot.txt. default to 32 if omitted. +- mclk-fs : Multiplication factor between stream rate and mclk + +Backend dai-link subnodes: + +- codec: dai-link representing backend links should have at least one subnode. + One subnode for each codec of the dai-link. + dai-link representing frontend links have no codec, therefore have no + subnodes + +Required codec subnodes properties: + +- sound-dai: phandle and port of the CODEC DAI. + +Optional codec subnodes properties: + +- dai-tdm-slot-tx-mask : Please refer to tdm-slot.txt. +- dai-tdm-slot-rx-mask : Please refer to tdm-slot.txt. + +Example: + +sound { + compatible = "amlogic,axg-sound-card"; + amlogic,name = "AXG-S420"; + amlogic,aux-devs = <&tdmin_a>, <&tdmout_c>; + amlogic,widgets = "Line", "Lineout", + "Line", "Linein", + "Speaker", "Speaker1 Left", + "Speaker", "Speaker1 Right"; + "Speaker", "Speaker2 Left", + "Speaker", "Speaker2 Right"; + amlogic,routing = "TDMOUT_C IN 0", "FRDDR_A OUT 2", + "SPDIFOUT IN 0", "FRDDR_A OUT 3", + "TDM_C Playback", "TDMOUT_C OUT", + "TDMIN_A IN 2", "TDM_C Capture", + "TDMIN_A IN 5", "TDM_C Loopback", + "TODDR_A IN 0", "TDMIN_A OUT", + "Lineout", "Lineout AOUTL", + "Lineout", "Lineout AOUTR", + "Speaker1 Left", "SPK1 OUT_A", + "Speaker2 Left", "SPK2 OUT_A", + "Speaker1 Right", "SPK1 OUT_B", + "Speaker2 Right", "SPK2 OUT_B", + "Linein AINL", "Linein", + "Linein AINR", "Linein"; + + amlogic,dai-link@0 { + sound-dai = <&frddr_a>; + }; + + amlogic,dai-link@1 { + sound-dai = <&toddr_a>; + }; + + amlogic,dai-link@2 { + sound-dai = <&tdmif_c>; + dai-format = "i2s"; + dai-tdm-slot-tx-mask-2 = <1 1>; + dai-tdm-slot-tx-mask-3 = <1 1>; + dai-tdm-slot-rx-mask-1 = <1 1>; + mclk-fs = <256>; + + codec@0 { + sound-dai = <&lineout>; + }; + + codec@1 { + sound-dai = <&speaker_amp1>; + }; + + codec@2 { + sound-dai = <&speaker_amp2>; + }; + + codec@3 { + sound-dai = <&linein>; + }; + + }; + + amlogic,dai-link@4 { + sound-dai = <&spdifout>; + + codec { + sound-dai = <&spdif_dit>; + }; + }; +};