From patchwork Tue Jul 17 15:42:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142171 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3820604ljj; Tue, 17 Jul 2018 08:43:18 -0700 (PDT) X-Google-Smtp-Source: AAOMgpc4DqrDwptqra9N8ooXZuaAs0dje24pJl9DDFIdP5cEIG/l6k6n3IChjgpRy6WQNtSA6XN5 X-Received: by 2002:a63:4f63:: with SMTP id p35-v6mr2089690pgl.167.1531842198719; Tue, 17 Jul 2018 08:43:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842198; cv=none; d=google.com; s=arc-20160816; b=Jdo+Xdfi5r2xdnBZh6OMpwcwUQwGWCy5OpeiRCBF+2JlW1RQIl88lUBCh/6ZOD1IUN tx2ajT6Gqi7Shfw5gaNqJvMfMALOKtrTwMrPxu7vEsuB65/SF8ymN/7E9kWX53UaZyI1 Aysy9pYF2JXDk6rMpuTcEqbtzXZKGITwkg5xVDSHHTd+M8dZBM+jZX/ZU2+K2a5SbPCu waC/rNAgQC2CephAzFYipTsvVBbTCbYNfiHE7yARaW8t4V1HdNv8UI/J1qyamA+wqJNw RIN9CV/2+c3xMr1t9vpbxgWsE6KHUU3q2BXXHY9iKlWFQvt3KbWiJQkyTa931BFo1cjs AZ5A== 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=fpyojqqEXxBMVGQ9gOj0nSaGphKtXorSOcTurNY/3cc=; b=vqjXOPfdequAYPTtg8BuyF6M+6obcAJW/ThnqGmeV/ImYvhGsNXN/8v1QVHSZNbt2z U7OTi1rV0xQWpU0RpkfD/+80rpPmnSwKiYJb9ctZbMySyi9H70qbkwOXKgu7LRnOt3io +MLSLcrwcRJh5AgjGkTjE9HKP2EdSlEH1K6tg7mXyb3hgVG6TWZY7LDtpT/dO4tEWYl3 rX2PKRoOj/SunN4+EfjmKMs/YOQjA/jRoJI6MCYG6iZhD6t8vnrWHP6LYBnxQhkSfnLF fxUqDqAQAL/zaB/eNGWCxZzh7PzN7fyFcWWj4xemPLgbFxXJolByaS6/QUyqrjO1BpXd wNHg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=h7cFQ0E9; 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 bf10-v6si1073558plb.69.2018.07.17.08.43.18; Tue, 17 Jul 2018 08:43:18 -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=h7cFQ0E9; 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 S1731151AbeGQQQa (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:30 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:42473 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730811AbeGQQQ3 (ORCPT ); Tue, 17 Jul 2018 12:16:29 -0400 Received: by mail-wr1-f66.google.com with SMTP id e7-v6so1725950wrs.9 for ; Tue, 17 Jul 2018 08:43:14 -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=fpyojqqEXxBMVGQ9gOj0nSaGphKtXorSOcTurNY/3cc=; b=h7cFQ0E99C5He0aTuGhI2oM1xKwg9NbZH1e3UuDi2GEq8v10llg/46wOTJ5WL69eRF OYilMmDCWm8M03ECCgb47vmGVbSOGhCe+nK94TV33unOHxE9lYX2cfPGzEM1XImUz4Do ZiG4UQ2y79jihzwFkGbT0Mq2D8hN7tt7A2g7W9KiWT6gkXvQBjpnTkjcXnX5oDUjhgIK Cj7+/QSkyOrl1ZVt782QeCc7kSWgx9QEa3Uz+J9Xden6RYB3wZZEG+c51PvsG/lec/Lf K/ImscxuiNnolRidsFSTP5kShoiZIhhEVLGm31IdwVhGPigZe6qaOtVVAwGLSWnPLNi+ Xs0Q== 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=fpyojqqEXxBMVGQ9gOj0nSaGphKtXorSOcTurNY/3cc=; b=nUPDdypnH+rxLX2RYk9GrqjzBZ6jsdD1qy5RMtw1yiod/K86PTGZ2LYf5IZS9+z7/L R9rs1/WMuQMThLsoE/DlmYWmSkpiZ0ffUDwL8Yu7B2xKq5pLWwxfC3aso3McmyszIKYX lOQc+r+e7wHyoum7HhDS65SVcNz+xKrZ65mJGFcAtNa8G6hlYSZcRWC4iZ4Mj1eJmQY/ Kyvxv3NmGFQjytyHS45ZYwwpzCfJoq83VRBbqWWXfj09rBirAXOcAH8rV3L16BZ34IeN lAkn5b+ml2p4JxLdJEs8wmJRNxxlkjvRZ6xjxYwnv/6hT/TRBVXyxnCzuTtvxiucfgaz fVbQ== X-Gm-Message-State: AOUpUlHZSAzYcx9DZSr3rbucFeavSFowliuRy2+PR2d++484oX7xsMIv 9iCXCXx5pvuTBRGiP4E+tI4RrQ== X-Received: by 2002:adf:e3c5:: with SMTP id k5-v6mr1854206wrm.94.1531842194289; Tue, 17 Jul 2018 08:43:14 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.13 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:13 -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 RESEND 01/15] ASoC: meson: add axg fifos DT binding documentation Date: Tue, 17 Jul 2018 17:42:50 +0200 Message-Id: <20180717154304.9973-2-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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 FIFOs: TODDR and FRDDR. Signed-off-by: Jerome Brunet --- .../devicetree/bindings/sound/amlogic,axg-fifo.txt | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt -- 2.14.4 diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt new file mode 100644 index 000000000000..3dfc2515e5c6 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt @@ -0,0 +1,23 @@ +* Amlogic Audio FIFO controllers + +Required properties: +- compatible: 'amlogic,axg-toddr' or + 'amlogic,axg-frddr' +- reg: physical base address of the controller and length of memory + mapped region. +- interrupts: interrupt specifier for the fifo. +- clocks: phandle to the fifo peripheral clock provided by the audio + clock controller. +- resets: phandle to memory ARB line provided by the arb reset controller. +- #sound-dai-cells: must be 0. + +Example of FRDDR A on the A113 SoC: + +frddr_a: audio-controller@1c0 { + compatible = "amlogic,axg-frddr"; + reg = <0x0 0x1c0 0x0 0x1c>; + #sound-dai-cells = <0>; + interrupts = ; + clocks = <&clkc_audio AUD_CLKID_FRDDR_A>; + resets = <&arb AXG_ARB_FRDDR_A>; +}; From patchwork Tue Jul 17 15:42:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142185 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3822366ljj; Tue, 17 Jul 2018 08:44:56 -0700 (PDT) X-Google-Smtp-Source: AAOMgpdkzyCBDfvOyNsmdsHU/icSUL9BEWqadcfFfshp8AdjKCiiclee+MVb9kqlCepGGk7O7JUZ X-Received: by 2002:a62:d544:: with SMTP id d65-v6mr1189342pfg.107.1531842295868; Tue, 17 Jul 2018 08:44:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842295; cv=none; d=google.com; s=arc-20160816; b=wg8pJy+g487gI+b3Ih924WiGQEZb7aQPcl0bDGIiQJjulltfRkWVu3AtD9haUcdnB2 DCg/ojdHUDp9bjcGNwv/R3EQo4Hnu3HRHbBSgGCBBNrVG7vItTHioHr/FeEp8zR+xFPE 79ZF6zS/FDuhGJOlaToCi5iXndumwJE+iZ+E1fEtbu6sreQE91OUXcg4V78YNEyjZLGE fhx6EqnPBE98VtgKZoRncVpqZr3kTfV0jQxFnnIQ3PppcHt6i/cZTt41pjT9MzxTQnWK wwZdEyVK7cz8ey/VsmXG0NbECyFp2OZRGHgvQjy2U9SoFxsEbWs9/cRN1RnYK0djztCI Uurw== 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=F8tYw34KHJ4HD9NBmPy+/0JwOQOMmHBpRz/p18HOb9eCCphlaiyl+fd9tmF7o8ou2Y KrWqLwF8tHy4uJm+vNqRumNfewA/kanVA3ABVig0K3TqN9bR0cid2dXnl5lsW6ttdjVz zyG3Ohv/o8JR8qC7NcnwMY89R5LGpVyLyBtRi4mmO101Dac2K+VAgzI1oE3CpS/zPqZJ MxEWyK6Xd+1GPCmxoioHG0dzieY5oy6K7bCT1i/zJdgUQmkqiAI+WMBaB2sc7RfR7qHq Dwhm4DPJcBB8czGNz29CwRye8iqtSLu1e0NyMILevK1RWk+cnrebFZoMVRZFr7fVp20S ZaqQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=d0N52d6V; 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 i6-v6si1222044pgk.517.2018.07.17.08.44.55; Tue, 17 Jul 2018 08:44: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=d0N52d6V; 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 S1731213AbeGQQQc (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:32 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:40952 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730999AbeGQQQb (ORCPT ); Tue, 17 Jul 2018 12:16:31 -0400 Received: by mail-wr1-f68.google.com with SMTP id t6-v6so1722165wrn.7 for ; Tue, 17 Jul 2018 08:43:16 -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=d0N52d6VsDinkTBAZvH1P3oB1QhcHEEAH1Jml8ttVsUUvziM/NY7gfF7nNAeaYE+A6 oX6O2UJ1GQwzfaCh1uqRNlcKbXwmK9wJUbuP6HPmWbfdEV83z5zrU6+kRmQJ9GYb+EBJ e5X8kgTUZWt4sox+IjXhUsDR46Wq/j8LCHUmvjOEH+syRPKeD71WGSbO6yXo8qZ6QMSh HQcPgWB6EAX3PbnKwkpvpLqktQSnFjeAMstS7amC4K2/7peLmOOE7ZeOQWORuWbUb7Lz 9NFOG3jN4YAC+8ihfW4B+h3MXGSC1dOZrgBi8LO1Kw1LxYSkgUU25gG3sPBYaSm6/dT+ VUmg== 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=MbgCFmhdrFmxiA+JxJ7PcgUjsYpYX0kdIRecju3BjqyT2oGWSJ7SfItYfD8F0brj0E rfJcdVHUkRBM1a8ICrxZ50BeWjd5/wHOkGSz3e3P0Yop9iBJjHDKn09hHKzo90k9ZCEc XxmoSibN2pUVx/REPOcqAuErJ03iuLTvbmHokXUShGt32r8uPs2V/OhI+nwSvoiNGHpn a7NbE0UeowU61rBzgqTGB2cUHzIh4hxZlC2WM2TCatwZBCtAG8Iij/hVaSAlerj507vv NJ22dxI8VvSpqOzpNsOibMMVp4MtpCETxI4dSY1iSXeI7aZ7NrYhqrkqD5wLbawKm3bB GDRg== X-Gm-Message-State: AOUpUlHLhfM3kKZw86inIJw7esa6+9bC1a4xU6uHZ9K6UTzjtGbwaOjy JymxWZiQshKpVqsc+4QxsnWxwQ== X-Received: by 2002:adf:9051:: with SMTP id h75-v6mr1841539wrh.65.1531842195329; Tue, 17 Jul 2018 08:43:15 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.14 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:14 -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 RESEND 02/15] ASoC: meson: add axg fifo base driver Date: Tue, 17 Jul 2018 17:42:51 +0200 Message-Id: <20180717154304.9973-3-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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:42:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142172 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3820653ljj; Tue, 17 Jul 2018 08:43:21 -0700 (PDT) X-Google-Smtp-Source: AAOMgpcSIIbRlnnCPntrHNvjUz7+bpowuXkVmIzZsrdEXwOCXTXXSIxYc2au7qPUocCL5DFeyhuD X-Received: by 2002:a63:4b5a:: with SMTP id k26-v6mr2038901pgl.384.1531842201792; Tue, 17 Jul 2018 08:43:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842201; cv=none; d=google.com; s=arc-20160816; b=r5yk5N4fYer8yErXxcSINGuJn8j8zXtEvRL5WlECGvU6+2Rf9UXe2xdLY9fWt9DzfS 4mrOqPKpTLw5UAOfXgbKp6MAZPazjjsHuOC0NUq/vdbipp20xYRKFgFSiH9qv5/KEsKT QGUvonZM2Acjiw0RHS5FeNdP1LRsaRkPhYEDjpC396dIxk1Z0ZioC0ZOGKlMzhvtAZ1W Y4dn85ZATCdcYG83jPYo/FELvJZAAtX+9xeldQtkERVh6VoAfUUlVykFZOM05zjPjXlQ QATwKsOG5QsoYbbGl5xFhMc5oxC3j/R+PwBN+n4FlnX3ym+6Ms33+oM0CWSPlazhN9YE YCeQ== 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=vNkHdoHxDTeCb62fmSaQ1EzoUhqjgTMT8K04+gGWmyw=; b=kY3fxUG5BVICBn5k9qBmFjk8yeJruVevc5eYotJRSgzvLF9YNPXUAR/mQ6Zr7oD6Bl 4ncDDitSGOMWpK7aFzFmc5sA8aXH9S9HAmUQvmUlCzGdrdF3yEn5KlQ1ArmpoV2s1Jgy V4USrt8jAiTtMdZSqSWyjiMrFgZEovdSLn2tXEB8lZ8bkRznF96JLLz+gZyTOEGxbWEj c/TAys60QVBymZkbZ7AqSlP8vLNlYNSoR+J9z6sP3L4APilo+ko6LysbPJarAJJ8w8Vg R0lJ+18o14mQw0y24U5FYW2KiXFJtuYCv3bvzx9urStCQXG1TjRlhiSdFL2KKLoFWKo+ roAA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=x4h6FNFI; 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 m12-v6si1075647plt.276.2018.07.17.08.43.21; Tue, 17 Jul 2018 08:43:21 -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=x4h6FNFI; 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 S1731269AbeGQQQd (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:33 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:33760 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730926AbeGQQQc (ORCPT ); Tue, 17 Jul 2018 12:16:32 -0400 Received: by mail-wr1-f68.google.com with SMTP id g6-v6so1745300wrp.0 for ; Tue, 17 Jul 2018 08:43:17 -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=vNkHdoHxDTeCb62fmSaQ1EzoUhqjgTMT8K04+gGWmyw=; b=x4h6FNFIbgslVABs4yx6Ef3hrKhmAIpPvW6tgE3K4xyzcCEy2n+ZA8Dcy9/SsbHkkY Vkae1JTqRp7WOdAthQ1i6XTIBVoFHbSztiYW8D7/HDfaL7w4evi/JmFmpH9DtLTqCVSx yNgNSBbhSb4zJnXUagOIB3xW1vvq+Gb+ydOxLUD7Lrmz9L0DOiHRbVNzDlJRv/qYLCEa U3ukyASfngFHyZ1aNM+e6C8cSnZ8EMDk8ytely5HlRXVL2KH4Mn1fC3J5OrEoNAgaIvK utIGTQqOqsHDldE9IfiXNTkKaU77aRojAOaiO1ToW1N/NQSlkXEjOgBeQnKBwxv5dSLn IcXQ== 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=vNkHdoHxDTeCb62fmSaQ1EzoUhqjgTMT8K04+gGWmyw=; b=c03ajeVd0d8SCwh33bYB+BormIE2eMH/I6uPY4iXu26Bu1JlMrOOplEUjdGK+f+CiX AHHRTcceRYqAUDzTER4G0a3BMZ/NtjFt5q5xpqcD/R8JggAVqpcCi8tFs4L9bp0UtSpV QVUaHQdfd8RWnHmSZ5yHVdHhQvLnmg7W3Lys4lWrbhfzTCNUG56QjYNbiHbfO915/EPw OMCm2Kb9dW1CiJ0Z+J6Gl5jaOQrecBwnpaMyFbtSjkCgq0TrYTUWOr8H26mBcAdRv1dE tBJUG/UmobdEQUjHNbBVkfeWWCfsGsZP790TrtMt6XX0/kxh3Oh3govrthee9nsT+AUA cbmA== X-Gm-Message-State: AOUpUlEANHoeLJ4GSuMWbNosOlLwetiovJtR04SpVsUR1cvHCzJZEDEp 2MivJr5AmFdkvxNaOGQYDI95Hw== X-Received: by 2002:adf:fe8f:: with SMTP id l15-v6mr1860963wrr.165.1531842196399; Tue, 17 Jul 2018 08:43:16 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.15 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:15 -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 RESEND 03/15] ASoC: meson: add axg frddr driver Date: Tue, 17 Jul 2018 17:42:52 +0200 Message-Id: <20180717154304.9973-4-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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 playback memory interface of Amlogic's axg SoCs. This device pulls data from DDR to an internal FIFO. This FIFO is then used to feed TDM and SPDIF Output devices. Signed-off-by: Jerome Brunet --- sound/soc/meson/Kconfig | 7 +++ sound/soc/meson/Makefile | 2 + sound/soc/meson/axg-frddr.c | 141 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 sound/soc/meson/axg-frddr.c -- 2.14.4 diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index c3eb5e050308..cdd78f62e8d7 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -5,4 +5,11 @@ config SND_MESON_AXG_FIFO tristate select REGMAP_MMIO +config SND_MESON_AXG_FRDDR + tristate "Amlogic AXG Playback FIFO support" + select SND_MESON_AXG_FIFO + help + Select Y or M to add support for the frontend playback interfaces + embedded in the Amlogic AXG SoC family + endmenu diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index 75289b6b3ade..9c5d7d4a8e33 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0 OR MIT) snd-soc-meson-axg-fifo-objs := axg-fifo.o +snd-soc-meson-axg-frddr-objs := axg-frddr.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 diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c new file mode 100644 index 000000000000..a6f6f6a2eca8 --- /dev/null +++ b/sound/soc/meson/axg-frddr.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright (c) 2018 BayLibre, SAS. +// Author: Jerome Brunet + +/* This driver implements the frontend playback DAI of AXG based SoCs */ + +#include +#include +#include +#include +#include +#include + +#include "axg-fifo.h" + +#define CTRL0_FRDDR_PP_MODE BIT(30) + +static int axg_frddr_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_depth, fifo_threshold; + int ret; + + /* Enable pclk to access registers and clock the fifo ip */ + ret = clk_prepare_enable(fifo->pclk); + if (ret) + return ret; + + /* Apply single buffer mode to the interface */ + regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_FRDDR_PP_MODE, 0); + + /* + * TODO: We could adapt the fifo depth and the fifo threshold + * depending on the expected memory throughput and lantencies + * For now, we'll just use the same values as the vendor kernel + * Depth and threshold are zero based. + */ + fifo_depth = AXG_FIFO_MIN_CNT - 1; + fifo_threshold = (AXG_FIFO_MIN_CNT / 2) - 1; + regmap_update_bits(fifo->map, FIFO_CTRL1, + CTRL1_FRDDR_DEPTH_MASK | CTRL1_THRESHOLD_MASK, + CTRL1_FRDDR_DEPTH(fifo_depth) | + CTRL1_THRESHOLD(fifo_threshold)); + + return 0; +} + +static void axg_frddr_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 int axg_frddr_pcm_new(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai) +{ + return axg_fifo_pcm_new(rtd, SNDRV_PCM_STREAM_PLAYBACK); +} + +static const struct snd_soc_dai_ops axg_frddr_ops = { + .startup = axg_frddr_dai_startup, + .shutdown = axg_frddr_dai_shutdown, +}; + +static struct snd_soc_dai_driver axg_frddr_dai_drv = { + .name = "FRDDR", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = AXG_FIFO_CH_MAX, + .rates = AXG_FIFO_RATES, + .formats = AXG_FIFO_FORMATS, + }, + .ops = &axg_frddr_ops, + .pcm_new = axg_frddr_pcm_new, +}; + +static const char * const axg_frddr_sel_texts[] = { + "OUT 0", "OUT 1", "OUT 2", "OUT 3" +}; + +static SOC_ENUM_SINGLE_DECL(axg_frddr_sel_enum, FIFO_CTRL0, CTRL0_SEL_SHIFT, + axg_frddr_sel_texts); + +static const struct snd_kcontrol_new axg_frddr_out_demux = + SOC_DAPM_ENUM("Output Sink", axg_frddr_sel_enum); + +static const struct snd_soc_dapm_widget axg_frddr_dapm_widgets[] = { + SND_SOC_DAPM_DEMUX("SINK SEL", SND_SOC_NOPM, 0, 0, + &axg_frddr_out_demux), + SND_SOC_DAPM_AIF_OUT("OUT 0", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("OUT 1", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("OUT 2", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("OUT 3", NULL, 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route axg_frddr_dapm_routes[] = { + { "SINK SEL", NULL, "Playback" }, + { "OUT 0", "OUT 0", "SINK SEL" }, + { "OUT 1", "OUT 1", "SINK SEL" }, + { "OUT 2", "OUT 2", "SINK SEL" }, + { "OUT 3", "OUT 3", "SINK SEL" }, +}; + +static const struct snd_soc_component_driver axg_frddr_component_drv = { + .dapm_widgets = axg_frddr_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(axg_frddr_dapm_widgets), + .dapm_routes = axg_frddr_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(axg_frddr_dapm_routes), + .ops = &axg_fifo_pcm_ops +}; + +static const struct axg_fifo_match_data axg_frddr_match_data = { + .component_drv = &axg_frddr_component_drv, + .dai_drv = &axg_frddr_dai_drv +}; + +static const struct of_device_id axg_frddr_of_match[] = { + { + .compatible = "amlogic,axg-frddr", + .data = &axg_frddr_match_data, + }, {} +}; +MODULE_DEVICE_TABLE(of, axg_frddr_of_match); + +static struct platform_driver axg_frddr_pdrv = { + .probe = axg_fifo_probe, + .driver = { + .name = "axg-frddr", + .of_match_table = axg_frddr_of_match, + }, +}; +module_platform_driver(axg_frddr_pdrv); + +MODULE_DESCRIPTION("Amlogic AXG playback fifo driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); From patchwork Tue Jul 17 15:42:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142184 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3822191ljj; Tue, 17 Jul 2018 08:44:47 -0700 (PDT) X-Google-Smtp-Source: AAOMgpcyIsWOonvr1hnq/bJG8KQu0epnhkWZu+5pyA2CXRtE+v4uVZAiMZInDRXQdlvrznribCut X-Received: by 2002:a65:62ce:: with SMTP id m14-v6mr2068099pgv.407.1531842286928; Tue, 17 Jul 2018 08:44:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842286; cv=none; d=google.com; s=arc-20160816; b=R1k6/1W366EoHjsqFMUs7yp8L7mpjNfJQuY64Zn3yOyue8Lu+n3YzbYQeAstQBCpjb asXjnPJ/EGN8z5Sp15B+iKv6uSuSyy8i1rroJ6q4zd+7cX8c4Srxuoxd3rNewbAsuPDI l2tplQNCLJ6szugOhDPU0ao5DGWej5qTAEiELJPZ19V1aKRlaI3vYhgbLsDw1vKV/Bov bQD9lpdtVqq/lKqnlmCIkcc/TeUqOZWIwaXBFTqZgSMu1HHbQefpC1YwTutlbCdFPYmt 1vkN/YQn7G4gsBEJChaQn7quIlGcZ+VQgrbeIN4AFtdKfvFCyeyVEJhlHyk4dOzfF5bL pQJw== 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=0H3CeH+v5ulfQ/7ne1OYkv5pTPPmknl3Elt9uzph3EERNVH7ti5aUaB10IYF+0Dani BNzhLzM4AJ9PLityBa2nyhZrlad3sBCWSlta+LKLW4atRfuNwTIh+xHMW75YwdchVol+ ENfomzDyRGHOEZhzIXzVHIBTwDz1pL1BDeEu6fqWz5VCuVkKV4AHdppOpDmLQDoE6PCr /00ssb/avpS72OvzknRVySiBbPV1ZV/SIIzLKA9SIcM5gETVxRS80LrdrVW+5tBfFM/h aK7s7j2mTF87hj5lg0buA0nEmpPbl/ZR/4xrVvKutOAFpgAmpTlDstNBsvq41mJrpB+p R4vg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=NPngoSNi; 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 i6-v6si1222044pgk.517.2018.07.17.08.44.46; Tue, 17 Jul 2018 08:44:46 -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=NPngoSNi; 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 S1731319AbeGQQQe (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:34 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:43073 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731221AbeGQQQd (ORCPT ); Tue, 17 Jul 2018 12:16:33 -0400 Received: by mail-wr1-f65.google.com with SMTP id b15-v6so1716315wrv.10 for ; Tue, 17 Jul 2018 08:43:18 -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=NPngoSNig8FPooJQra976pV6Jxs2r3iLZJBkOipANIztmOH9/SeU+TNNKpiANco//7 dxMoDjIEAHkB1xvHRcL3K4AoCApBrG84P/c+ihRXf1HbBe0MDyzu4VB3KRQdUK+Y5Vfz oYWYQ09r2r6Auk6eYcKc63iMINhv/463TIKlnVSSXEAYnaPs9maomcyknQd8lJk+WJV5 1KWVBKPZrvAb7rj89ZcMjYlpgOL1z0/JV2lNpCpaaZXPpiQWUZx7ccr4aD/JbQotob5z V6CrPi8Q7UGQdowm+Jmm0ZRnlTW8U02zAROgRdm5Q8OksNsQ5HKXs1jv8EhV7d0dvwiW Rv9w== 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=gPPsETwA1zgDUKtAnb6AG5KTXvp/qE+v1HzJb7vR2yDwxALCsE2ezcyy9dc29lLvrL 4r6cH/ztyd4CnHDeMwBwNzlbjGJgFQCMhzV52yprwp00is0afdPQ328BgXabtQNqdIJj 7iXPXfX8tJIEWM/3l7AVez72k/OICpZ6ZPnVxo7HTQEWQHixmqhInIsuQY2DpxxOM6dZ pr8SupWRSbmH5nPRODxsWMuYj7xiz2VohSsdaFba6K0EPrMRmomXZ71kp38gdVGK4nAc O6JKO19LSaNqbac9zp+ZcVVAXOHoIVpe1OHzIzUOG/oKih1xN5Bkm/dnKhRYMxFwvFz0 /VfQ== X-Gm-Message-State: AOUpUlF2v3amenb/P1kDMOgTSSDwwFCIVr0HGQQaaWWSekST4SkVUX1k cWsnZu5HRKxX55AuLvStXDVbpQ== X-Received: by 2002:adf:e405:: with SMTP id g5-v6mr1837079wrm.96.1531842197623; Tue, 17 Jul 2018 08:43:17 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.16 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:16 -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 RESEND 04/15] ASoC: meson: add axg toddr driver Date: Tue, 17 Jul 2018 17:42:53 +0200 Message-Id: <20180717154304.9973-5-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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:42:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142173 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3820688ljj; Tue, 17 Jul 2018 08:43:24 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfd/IWSh23noFvmlEoS5pdr2WRGCRrGtYKVQD6OtXejbCLDVnCiGjWpaoS4VLkglnEB5n0Q X-Received: by 2002:a63:b256:: with SMTP id t22-v6mr2141224pgo.101.1531842204212; Tue, 17 Jul 2018 08:43:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842204; cv=none; d=google.com; s=arc-20160816; b=ZDG7Hd0wV1qxa/RCGgJNvqb5RPITqmCfZrVHQnt+CebBUf0NlvCWe4nqTuH7wfnBvS eUbtOaN7y9pBwZ5n87uxoasVsfwNcGryXjALFBotwYPzzu2dZPauQzW+n1++prQ6hKqy s3/2o3cL3J4cj0cc5Bbzr+JPiw1kZA+ILc4kDx6Cav4rebxG7ynCL8KCbTvuE0VkS52f 74Vs2kob/Zbpyx9ENx8BFZ4BUCry7DQ9uMYZHBTqs/cqvklPHfGyVcUSlV7VJmtLIzqq aUjHJ6BfnO0yKd643WybLdP+F6J1XUXynDZw4gH+tHDe4gX6M1lVGk1wG6euk0BYuCZB PUsg== 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=MTkflaydBTJzVf0ZHkleSoX0FARPEM+k3qhZfYkvVTE=; b=l8CvcXyorzXGwkrWliW/BeHHzJq2ZhZlwoWiZIFRLf6SWO9psxuSyQe6cpQrbpNTdq wQT+NFAy8AhZLbNA6Eh/souW1jHGpIdIf4/md/rnNULL5FQpYhPH3apgahpiw8XzU2+v Gax7h4ZSgu6O+863wiYCjQm4GHp+ty8DSTlF/znXGFOJnFyhSLt1y9HvOlrQTsMfGluD PbN49io8nsuZuh9Qc5ycmAixw2cTt3vXz/oIYjONPsndQAr6rumGyoGil4TjuR/SznTJ dN2Y35ZZpmF/pGg+T8vpGPBWM6YDhPKhhhVJf3tMkye3nuGA93Zo8nVqNRVeeMG+n2Te RYnw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=o2IbnRjN; 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 q3-v6si1092456plb.238.2018.07.17.08.43.23; Tue, 17 Jul 2018 08:43:24 -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=o2IbnRjN; 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 S1731392AbeGQQQf (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:35 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:38767 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730926AbeGQQQe (ORCPT ); Tue, 17 Jul 2018 12:16:34 -0400 Received: by mail-wr1-f68.google.com with SMTP id v14-v6so1734807wro.5 for ; Tue, 17 Jul 2018 08:43:19 -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=MTkflaydBTJzVf0ZHkleSoX0FARPEM+k3qhZfYkvVTE=; b=o2IbnRjNYWuLXiTnISziSIqs8i1qAN2K1thxLHEt60Gv7oMpwwxZe54qQxipW9p8cP o/mEBbSMR7SxL4Y7Y4HoSSHKUfEDQhma+Pz0Inc/DY/Jb/hmnlAIPkPap40iJ1C82uaZ wwf/p3a58KX3gSu3yu08kWF34Ubxx01kT2P4e/p758fIZ986+IKWJfoSJjnwH0EVEvib Y5XN6AAEEoazChwinY8TBLqj0/cvVebKlawvDRL+jSy3WXs/c/jyHXVSIX22bdq2mnZz nyT2O7dyLI+rI7woKmnbGm7kN5KbtllaZesR6Qjwo9tNWmy3/quCRZsRHuUTmsJMykOo 4usQ== 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=MTkflaydBTJzVf0ZHkleSoX0FARPEM+k3qhZfYkvVTE=; b=pY+Bus+lrn4IS622q6xSIbXQtjpt6ESL9RjlzVaYuyB5YMJ30kP7QJQMpDslHrscsJ UXrjzaxkklAMVsMJ0fCgCnalVwzdLBv1tNpUOQcx3JaQFkiJk+LBzn3r4lVpb9euWk9p U7rOReZJOOjWo0PU7aJbX1gUabw+0FC2gsfq9OaxyOHzIS2kBTQJeY7ZQO71hqqUn9rS KGziECn+49Dg/m3gR83Qfkp+7GtScLH1bftcT3yx66/Kbi/xU8PEAWRiR/49IrWsXlG/ GvVQpMlzF7+mRfStzq4CmEpo/r+8Rou06TfRlyceuf621UMY6rKSbkrwLvrqz/1I5FfL kUIQ== X-Gm-Message-State: AOUpUlGQkf69PLz4BlAI6Pvx2ivzYb93oCwPGpVwI7X2CP1JiXUccKKf myEeMoRKQ+Oh1ePbU7LCgniG6g== X-Received: by 2002:adf:b2f4:: with SMTP id g107-v6mr1847981wrd.53.1531842198784; Tue, 17 Jul 2018 08:43:18 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.17 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:18 -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 RESEND 05/15] ASoC: meson: add axg spdif output DT bindings documentation Date: Tue, 17 Jul 2018 17:42:54 +0200 Message-Id: <20180717154304.9973-6-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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 SPDIF output. Signed-off-by: Jerome Brunet --- .../bindings/sound/amlogic,axg-spdifout.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,axg-spdifout.txt -- 2.14.4 diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-spdifout.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-spdifout.txt new file mode 100644 index 000000000000..521c38ad89e7 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-spdifout.txt @@ -0,0 +1,20 @@ +* Amlogic Audio SPDIF Output + +Required properties: +- compatible: 'amlogic,axg-spdifout' +- clocks: list of clock phandle, one for each entry clock-names. +- clock-names: should contain the following: + * "pclk" : peripheral clock. + * "mclk" : master clock +- #sound-dai-cells: must be 0. + +Example on the A113 SoC: + +spdifout: audio-controller@480 { + compatible = "amlogic,axg-spdifout"; + reg = <0x0 0x480 0x0 0x50>; + #sound-dai-cells = <0>; + clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>, + <&clkc_audio AUD_CLKID_SPDIFOUT_CLK>; + clock-names = "pclk", "mclk"; +}; From patchwork Tue Jul 17 15:42:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142174 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3820748ljj; Tue, 17 Jul 2018 08:43:27 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfpS39eo2HtxL0jHJh+zEnwt1pi27mPIQIiZTEyid+sFcZIZc/eBFoUg7GR9D36icCFlAku X-Received: by 2002:a65:460e:: with SMTP id v14-v6mr2028290pgq.177.1531842206893; Tue, 17 Jul 2018 08:43:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842206; cv=none; d=google.com; s=arc-20160816; b=MyuQK1HTIT1e/DLhNN0m7ED6XZoFHXivGZz0yBja6F52HUIbDvVYXYnITnYe4sUOPb ZXQShPVDdG4Y0UdUUNOjy6pgcQXpB6oLTvD8s1fbTVRtAKbxs5PK+uXaB2hWD8ctAwEd sVVKA09qroIp07ZEhVniW1Trn7XKv+lXB2B2IQLwz9yVqnE//vmbA1aV6YtlaSIpNDEO q80/YQLIScqTNF849x90CWHSJ2gYlmrLAg6C6u+XnOkTHSVUj9Js7K9iYhMOJegz0hTh aUVYbTFt6ef4Nvd3D1/38vwF32VyfxxvJAY3CJR06wqZkipTHQvjC4l8tf7yZJ+7ynV9 TYMg== 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=cNH0oqY+ES4dImG4yuCo90p0fCTl32YWDX8Dffc2cszuR6sq7QVA/oG4SrhNjDWCZs 7XW+Dv2/e3dSWOKWfWhmrC4yKxqbWza/NNI7FjN2n+H7mcqrcV7hViMa0KjFTYxTCalj Ka99YbfzQ8PdO/wqeZT7IngZGsm3TTny9qklBKOyMgIlBXdrgX0C4LfDdQKqqo90DLhy j3QTPqrmTGwxf3mpnSShY4+nrcWi0+WkPMI2vh/oolaom/opj5h00pfyNfgzj8mUmFQw pa8kQqGY7SvCiScbXk3ym4uQsx0aAWMLEdM/GDuiOL/mUCO1yEmm34L8hjh96LxtBgTt 2Agg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=kCs3jenb; 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 i28-v6si1198207pfi.105.2018.07.17.08.43.26; Tue, 17 Jul 2018 08:43:26 -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=kCs3jenb; 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 S1731538AbeGQQQi (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:38 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:46161 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731324AbeGQQQh (ORCPT ); Tue, 17 Jul 2018 12:16:37 -0400 Received: by mail-wr1-f66.google.com with SMTP id s11-v6so1708670wra.13 for ; Tue, 17 Jul 2018 08:43:20 -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=kCs3jenbNeMKekm2jlWc2f/6LolzdqmuSDp/dN4tbyF/4uQBlcmNPszbUPx5P7oAvi 5h3O1qj1c5FJNxftoIcJN5rQXI+IN91INPaQX9HZLlFsVvBGMYWaAZCi1ZnHDIvgpPvm ffa9oqXhpckn6dcm/OhVJlsZQK5xnCoKg0wDdXfvot8t1GTovgvsjmirvzHqqeSpzd7S 8il39ZFP9u4BteFqgjQIZokN+nqLfZV3BKzaX3HADSx8NH3uyYVc0NsrUdp4+auqAxk7 mrzPY3i5F+nmmiWWDskYjDh5TvaGZ6B1fJs5cvaNgLD6jG4fUVtD6og8eiKYpB2lP1v9 tOIg== 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=AaBqqyY/C9yvBiWDo9iU4upcKTR3o1+vFPgOP2rfs+UienZGM0HXcFw3reuCuZYWdu Kjz+MnYrEQ7wsKK4MlNzFHx3EF24/w1BS3K8SdGg9CcQLRWW24r3rfKK/2Yo7q+XILhP kN9C6Nfz5K+igyFkeDsaXI8rpUwYzVE8kyKeXfvEiyXL8Gu/n2vMH2Q/dRAM6A5lwK2T 2fpd2o8o64C5Jt4ELdcc+C2b+4eE0RXyRzLdlX34m26ag+nNmd5Xf41AvfveXk46OEgx cNpR5Js8SjgqLBIO+GAfmiIW0ETzcsEcr8o9TX5c8JAUz+t2vd4n7GJ4UdvOr7TV3VsU /TQQ== X-Gm-Message-State: AOUpUlFvdKXkQi26qY0O8PiOgIIx01WnNO4n/Df9eUwelacXLoY+eAEf YCPfpDpPdDkuZyBAWPM3AuHFPQ== X-Received: by 2002:adf:f74d:: with SMTP id z13-v6mr1906564wrp.85.1531842199939; Tue, 17 Jul 2018 08:43:19 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.18 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:19 -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 RESEND 06/15] ASoC: meson: add axg spdif output Date: Tue, 17 Jul 2018 17:42:55 +0200 Message-Id: <20180717154304.9973-7-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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:42:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142183 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3821696ljj; Tue, 17 Jul 2018 08:44:21 -0700 (PDT) X-Google-Smtp-Source: AAOMgpeZ2j5ueIdcpt68W0RoSGtFnt3p0G/3CuLlL/em6hLhssQwFqXv6lerWRtKdmujVf0+o/2l X-Received: by 2002:a62:4f5b:: with SMTP id d88-v6mr1188052pfb.225.1531842261411; Tue, 17 Jul 2018 08:44:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842261; cv=none; d=google.com; s=arc-20160816; b=mLShMni3P9fsb8F8HXxXCi71Z2C1bKOg/2elkma7x+Sd/jccEW2WGZ4TwIOTT5YBoM UJGRBo3wUlrM2PRce3HnH8GkmkXqtHSNpz9qToEZt9uryEQAEiK+/10+YX9k1f0KkBS8 ajPRCjU8gBRT5CHKTGRKFc5Yw0PP4rjaKhzDxCEIt0pVKmRE7KdS8iRzQldzKuy8pW+4 VHPlaiJ3P8A2MDiAHUYxEGLtAPBs4WMNykP0sAuOWv/pjUd32ERgUx0nJR1jSvjpjmMx fGrv2hpIO2wiWU5sPynVexMce6nZjXSiNglmvgDvsHmO9IvIC6Krjjf7y+XNwayGw2a2 IXMg== 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=RRj2wMAn4dHARtAnE7xYDfVvk3OhkLr78nUMGcYlLLRn2YpJs36A0xxnHGgOgEKFAG H+ZvhRLVBYDMMlBVyo6rvOP99SJt2jIi+I6lCUjSORRpfrN8vEebage5ap/oQnDEpLYR vRV1F/br1zn97HVJuNJG3CP3ymLL+pjPCrhUFBhEnLbA/9XBQcDsCPMIWTndo1w5y6at RBjgv7MIkU7FMIZHpY5LJHb1gT5ybICMRoxEIBCaPOFu5tdTuVPHERoKtRCTCBzADCwR AZSofmlFYckNozw7Y30T0tTvZb7X0XMzkzGU+51Bq56AmJtbfkXy3kTkkqhnxnCCHirE NhpA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=sUb+SpBt; 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 x7-v6si1244602pgb.297.2018.07.17.08.44.21; Tue, 17 Jul 2018 08:44:21 -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=sUb+SpBt; 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 S1731471AbeGQQQh (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:37 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:40580 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730926AbeGQQQh (ORCPT ); Tue, 17 Jul 2018 12:16:37 -0400 Received: by mail-wm0-f67.google.com with SMTP id z13-v6so2015406wma.5 for ; Tue, 17 Jul 2018 08:43:21 -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=sUb+SpBtY5p/OU0TIz0fdNH1wlzroS5oqKzTfMNAICZU8xfDqnfOImzyrXR5zYekG4 Kc0H2wQz4XTdhY19IkrVeB6wcQtM9lPRDJ1R8mbNgCkoomBoovudcw8G8hLwwvXtdP+X 3JJ4OeaonsWG/t3clLvN9Zg6uN4Q9ubrIUQORxhZzZmEo6MyqsqMjaqSlqRNFxmJ8it3 zRHsxf3NV6P8p8VYAI5cXlAfba0ZvAJHc3MN3lK+A0JW0harWosuwFEw2ZC4ccPMzmSt 2Ftny++fux1KVGWrIh7fhDSmhMjOxsmMdrbTi9l9Pf+qxHX5h8Wdg6mdQ8zVDHIGXhFz cPbA== 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=IFGKX3iNc4g5Q8NWtxvegv6EbVMJ0Ayum7iBTx8g36IOFdsb08ZHHMiNI5MWDk7uyF Z5TzInYtefykHiIhV/iQaj71bVkzamxKOIdKM9+0LPlzqiKJDLstDQZZedRFBSf5YrwH fGBnZE0yvsNUuPPoGlOAMpye6Jx9dG3pAe9c6kiYh2uDfcyc+8+EKRXCIUANWtUa6kqz Qgp4rYQB3uXR+L7ePAwZAQK0LLFbjFrjqlbPCdpU4JW5fGTArUv/F4U8oRovbP3DXlcr pPw8mST12Ov//fnJMppyBrzQ4eqEgs2hXVpfRxDHLsoJoI2N6FL8s3PoKtFl8sn8Y4VN p5jw== X-Gm-Message-State: AOUpUlGkafsRT7uSBN40qgDpMqmDtgRVNUO69EeTBuqsACPxX60MoUTu i+qrFshz1sn94slyH5vJEQjSuw== X-Received: by 2002:a1c:8682:: with SMTP id i124-v6mr1788908wmd.77.1531842201023; Tue, 17 Jul 2018 08:43:21 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.19 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:20 -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 RESEND 07/15] ASoC: meson: add axg tdm formatters DT bindings documentation Date: Tue, 17 Jul 2018 17:42:56 +0200 Message-Id: <20180717154304.9973-8-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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:42:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142176 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3820832ljj; Tue, 17 Jul 2018 08:43:30 -0700 (PDT) X-Google-Smtp-Source: AAOMgpdTK0h8WrQeli8ShKHQq7YEzu/8zb8ZHO3xpmRRs3jOvtiYjNUROVElE+Km2u6k/Kgc1gUB X-Received: by 2002:a63:cc04:: with SMTP id x4-v6mr2064215pgf.33.1531842210533; Tue, 17 Jul 2018 08:43:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842210; cv=none; d=google.com; s=arc-20160816; b=Q7BfiuME/6z4c3A4E8HWIjzF2rdWTyFduKt+OFvwPX6hNUx95JcMFqktbW8BDaYJp4 vwSuZ31XqTHrpWZ0RxCs6GPFbnIIqvDT26sNtUthyfEbAg+sKaNNuWmV4p5fQkSM9f8k 6qFyUEsqdGB0zSpfUsMQ1scQqXmsEZt8Umpd05Os7+g1U+9XPeAauzru8kdBhW0befCt 8gr1TeuC/gWrFpgXNjRSeGJcDilVpSpOa0qo5+5og717GV5Flo3H3I1nt98HKZPHK/mK XFk/2xw0uG4aaWk9q7o6oicgrOnY7mnSWYvinjfzNw4etTkFpwLsYCFqka0C8vClQ+Oc KS8Q== 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=/oCsoxn28JFsfA0ZpD62ZLBHrmZ2cJe+QwfO15qQ8Jw=; b=wJkTyG+mkRez6qfe6LhbVowlka0jVZ6VQe/frWPEn5nHzx6TuNi2BRf/fjbRYDqFZF nds+OrZ5WYM88FQ9t5a7rr2Ek0S+YpERMYYeFuY+dqCjRsS3QqyLhp7FU6LKvFJ4M0iJ 4j7VC9C7Rxxkg0fIWC2nzfWTsLtQXl2r3cz40pxKGoKgZkj1HDGP/9TJimpqYKiLKYjx p+KVt9UQzHhSALlFIv6NJ3G72uOocdp9o7tK8CFRlJW0FkNpD8FE/N5/OSjFQHPCjl8j vYB8S2PntSPEY7JfwUsE4M6spu6pl7yLzPgnlzzW9qDKZ2vo5QrGjjhL8/HzsLqrwcPD UdRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=nuXF4ty1; 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 j10-v6si1166935pfc.335.2018.07.17.08.43.30; Tue, 17 Jul 2018 08:43:30 -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=nuXF4ty1; 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 S1731584AbeGQQQk (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:40 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:38770 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731477AbeGQQQj (ORCPT ); Tue, 17 Jul 2018 12:16:39 -0400 Received: by mail-wr1-f65.google.com with SMTP id v14-v6so1735037wro.5 for ; Tue, 17 Jul 2018 08:43:24 -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=/oCsoxn28JFsfA0ZpD62ZLBHrmZ2cJe+QwfO15qQ8Jw=; b=nuXF4ty14bl1StDc+pVK6MRI6l5cbTSZBOWDClhKchNyhn/tzn/PNvkZ8xYAl4RHsA X+8v2gFIVpAgc9TEurij1FDRaYpMLCUNZrFqs5awVQRq1GfKXwezrAs5D3DOSVy8j1sU 84G+PLuxR6A92fa2+WQV0FkprsaRxygB4XC122uDJhPnBd66ZhtzQzgOsL4OK+uLZYcH M63KDeVtB0wv3ezh/tsB85SbodBN0yJhfDPvST7nPK+XNNzUWV1WzGLf0m3ltAz6rE/U tCkgBgCE+mLJx9pZ0mF7ET8+9oE2i26/Er10u1xodJ2zEPDvO6Jb9zdslB9kjvEjn7gJ o6Dw== 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=/oCsoxn28JFsfA0ZpD62ZLBHrmZ2cJe+QwfO15qQ8Jw=; b=pktYiRw9TWbTrgdY12eNugIXuHOlfFGeWzEd6BX5+6Y337QKoLAe2OrcI/eejybJIz BKJ69CgxGarll3R1ktrSknbaNa9lIlytIxFY5ElRZeb4B2DjGN2nmyfEDEilDXNd1yDc rce2SLqS66YJ3Pwfc8LViMTAOKXUYyQvbyyMlqulMNelb6Imdjaz43E5ZZBGcU2S23ZY yWoHuGKVM8yjg7W2XZDIsVSbCgzaACXcPlZYyIv6XzKjJIjsW3RSOJ43QDNqGJ84A6w1 wQacrgoipDdYTE7lGWK0unJx3qHapPRwENRZ/BRl0X6sKHDpuhgio8Kj1Ddo3Q0ffS2I 5Rvg== X-Gm-Message-State: AOUpUlHHCb5JGYu903Tim2LVopE5n8SJujeCGfSeKXRVvS5a2xGyQ6Py vp6rOciXxmYtekkq+V06xRNVaA== X-Received: by 2002:adf:92a5:: with SMTP id 34-v6mr1121590wrn.83.1531842203204; Tue, 17 Jul 2018 08:43:23 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.22 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:22 -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 RESEND 09/15] ASoC: meson: add tdm formatter base driver Date: Tue, 17 Jul 2018 17:42:58 +0200 Message-Id: <20180717154304.9973-10-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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 core driver. On this SoC, tdm is bit more complex than usual, mainly because the different TDM input decoders can be attached to any of TDM pad interface, including the output pads. For the this, TDM on this SoC is modeled like this: - TDM interface provides the DAIs the codecs will be attached to. The main responsibility of this driver is to manage the pad format and the TDM clock rates. - TDM Formatters: These are the entities which are actually dealing with the TDM signal. TDMOUT produce a TDM signal from the audio sample provided by FRDDR using the clocks provided the TDM interface. TDMIN feeds TODDR with audio sample using the clocks and TDM signal provided by the TDM Interface. - TDM Streams: This provides the link between 1 DAI stream of the TDM interface and one (or more) TDM formatters. This driver provides the TDM formatter and TDM stream operations. Signed-off-by: Jerome Brunet --- sound/soc/meson/Kconfig | 4 + sound/soc/meson/Makefile | 2 + sound/soc/meson/axg-tdm-formatter.c | 381 ++++++++++++++++++++++++++++++++++++ sound/soc/meson/axg-tdm-formatter.h | 39 ++++ sound/soc/meson/axg-tdm.h | 74 +++++++ 5 files changed, 500 insertions(+) create mode 100644 sound/soc/meson/axg-tdm-formatter.c create mode 100644 sound/soc/meson/axg-tdm-formatter.h create mode 100644 sound/soc/meson/axg-tdm.h -- 2.14.4 diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 9408214b5854..80a88689491f 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -19,6 +19,10 @@ 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_TDM_FORMATTER + tristate + select REGMAP_MMIO + 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 d51ae045ef08..a06b56a1c995 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -3,9 +3,11 @@ 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-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_SPDIFOUT) += snd-soc-meson-axg-spdifout.o diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c new file mode 100644 index 000000000000..43e390f9358a --- /dev/null +++ b/sound/soc/meson/axg-tdm-formatter.c @@ -0,0 +1,381 @@ +// 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" + +struct axg_tdm_formatter { + struct list_head list; + struct axg_tdm_stream *stream; + const struct axg_tdm_formatter_driver *drv; + struct clk *pclk; + struct clk *sclk; + struct clk *lrclk; + struct clk *sclk_sel; + struct clk *lrclk_sel; + bool enabled; + struct regmap *map; +}; + +int axg_tdm_formatter_set_channel_masks(struct regmap *map, + struct axg_tdm_stream *ts, + unsigned int offset) +{ + unsigned int val, ch = ts->channels; + unsigned long mask; + int i, j; + + /* + * Distribute the channels of the stream over the available slots + * of each TDM lane + */ + for (i = 0; i < AXG_TDM_NUM_LANES; i++) { + val = 0; + mask = ts->mask[i]; + + for (j = find_first_bit(&mask, 32); + (j < 32) && ch; + j = find_next_bit(&mask, 32, j + 1)) { + val |= 1 << j; + ch -= 1; + } + + regmap_write(map, offset, val); + offset += regmap_get_reg_stride(map); + } + + /* + * If we still have channel left at the end of the process, it means + * the stream has more channels than we can accommodate and we should + * have caught this earlier. + */ + if (WARN_ON(ch != 0)) { + pr_err("channel mask error\n"); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks); + +static int axg_tdm_formatter_enable(struct axg_tdm_formatter *formatter) +{ + struct axg_tdm_stream *ts = formatter->stream; + bool invert = formatter->drv->invert_sclk; + int ret; + + /* Do nothing if the formatter is already enabled */ + if (formatter->enabled) + return 0; + + /* + * If sclk is inverted, invert it back and provide the inversion + * required by the formatter + */ + invert ^= axg_tdm_sclk_invert(ts->iface->fmt); + ret = clk_set_phase(formatter->sclk, invert ? 180 : 0); + if (ret) + return ret; + + /* Setup the stream parameter in the formatter */ + ret = formatter->drv->ops->prepare(formatter->map, formatter->stream); + if (ret) + return ret; + + /* Enable the signal clocks feeding the formatter */ + ret = clk_prepare_enable(formatter->sclk); + if (ret) + return ret; + + ret = clk_prepare_enable(formatter->lrclk); + if (ret) { + clk_disable_unprepare(formatter->sclk); + return ret; + } + + /* Finally, actually enable the formatter */ + formatter->drv->ops->enable(formatter->map); + formatter->enabled = true; + + return 0; +} + +static void axg_tdm_formatter_disable(struct axg_tdm_formatter *formatter) +{ + /* Do nothing if the formatter is already disabled */ + if (!formatter->enabled) + return; + + formatter->drv->ops->disable(formatter->map); + clk_disable_unprepare(formatter->lrclk); + clk_disable_unprepare(formatter->sclk); + formatter->enabled = false; +} + +static int axg_tdm_formatter_attach(struct axg_tdm_formatter *formatter) +{ + struct axg_tdm_stream *ts = formatter->stream; + int ret = 0; + + mutex_lock(&ts->lock); + + /* Catch up if the stream is already running when we attach */ + if (ts->ready) { + ret = axg_tdm_formatter_enable(formatter); + if (ret) { + pr_err("failed to enable formatter\n"); + goto out; + } + } + + list_add_tail(&formatter->list, &ts->formatter_list); +out: + mutex_unlock(&ts->lock); + return ret; +} + +static void axg_tdm_formatter_dettach(struct axg_tdm_formatter *formatter) +{ + struct axg_tdm_stream *ts = formatter->stream; + + mutex_lock(&ts->lock); + list_del(&formatter->list); + mutex_unlock(&ts->lock); + + axg_tdm_formatter_disable(formatter); +} + +static int axg_tdm_formatter_power_up(struct axg_tdm_formatter *formatter, + struct snd_soc_dapm_widget *w) +{ + struct axg_tdm_stream *ts = formatter->drv->ops->get_stream(w); + int ret; + + /* + * If we don't get a stream at this stage, it would mean that the + * widget is powering up but is not attached to any backend DAI. + * It should not happen, ever ! + */ + if (WARN_ON(!ts)) + return -ENODEV; + + /* Clock our device */ + ret = clk_prepare_enable(formatter->pclk); + if (ret) + return ret; + + /* Reparent the bit clock to the TDM interface */ + ret = clk_set_parent(formatter->sclk_sel, ts->iface->sclk); + if (ret) + goto disable_pclk; + + /* Reparent the sample clock to the TDM interface */ + ret = clk_set_parent(formatter->lrclk_sel, ts->iface->lrclk); + if (ret) + goto disable_pclk; + + formatter->stream = ts; + ret = axg_tdm_formatter_attach(formatter); + if (ret) + goto disable_pclk; + + return 0; + +disable_pclk: + clk_disable_unprepare(formatter->pclk); + return ret; +} + +static void axg_tdm_formatter_power_down(struct axg_tdm_formatter *formatter) +{ + axg_tdm_formatter_dettach(formatter); + clk_disable_unprepare(formatter->pclk); + formatter->stream = NULL; +} + +int axg_tdm_formatter_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *control, + int event) +{ + struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); + struct axg_tdm_formatter *formatter = snd_soc_component_get_drvdata(c); + int ret = 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = axg_tdm_formatter_power_up(formatter, w); + break; + + case SND_SOC_DAPM_PRE_PMD: + axg_tdm_formatter_power_down(formatter); + break; + + default: + dev_err(c->dev, "Unexpected event %d\n", event); + return -EINVAL; + } + + return ret; +} +EXPORT_SYMBOL_GPL(axg_tdm_formatter_event); + +int axg_tdm_formatter_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct axg_tdm_formatter_driver *drv; + struct axg_tdm_formatter *formatter; + struct resource *res; + void __iomem *regs; + int ret; + + drv = of_device_get_match_data(dev); + if (!drv) { + dev_err(dev, "failed to match device\n"); + return -ENODEV; + } + + formatter = devm_kzalloc(dev, sizeof(*formatter), GFP_KERNEL); + if (!formatter) + return -ENOMEM; + platform_set_drvdata(pdev, formatter); + formatter->drv = drv; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + formatter->map = devm_regmap_init_mmio(dev, regs, drv->regmap_cfg); + if (IS_ERR(formatter->map)) { + dev_err(dev, "failed to init regmap: %ld\n", + PTR_ERR(formatter->map)); + return PTR_ERR(formatter->map); + } + + /* Peripharal clock */ + formatter->pclk = devm_clk_get(dev, "pclk"); + if (IS_ERR(formatter->pclk)) { + ret = PTR_ERR(formatter->pclk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get pclk: %d\n", ret); + return ret; + } + + /* Formatter bit clock */ + formatter->sclk = devm_clk_get(dev, "sclk"); + if (IS_ERR(formatter->sclk)) { + ret = PTR_ERR(formatter->sclk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get sclk: %d\n", ret); + return ret; + } + + /* Formatter sample clock */ + formatter->lrclk = devm_clk_get(dev, "lrclk"); + if (IS_ERR(formatter->lrclk)) { + ret = PTR_ERR(formatter->lrclk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get lrclk: %d\n", ret); + return ret; + } + + /* Formatter bit clock input multiplexer */ + formatter->sclk_sel = devm_clk_get(dev, "sclk_sel"); + if (IS_ERR(formatter->sclk_sel)) { + ret = PTR_ERR(formatter->sclk_sel); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get sclk_sel: %d\n", ret); + return ret; + } + + /* Formatter sample clock input multiplexer */ + formatter->lrclk_sel = devm_clk_get(dev, "lrclk_sel"); + if (IS_ERR(formatter->lrclk_sel)) { + ret = PTR_ERR(formatter->lrclk_sel); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get lrclk_sel: %d\n", ret); + return ret; + } + + return devm_snd_soc_register_component(dev, drv->component_drv, + NULL, 0); +} +EXPORT_SYMBOL_GPL(axg_tdm_formatter_probe); + +int axg_tdm_stream_start(struct axg_tdm_stream *ts) +{ + struct axg_tdm_formatter *formatter; + int ret = 0; + + mutex_lock(&ts->lock); + ts->ready = true; + + /* Start all the formatters attached to the stream */ + list_for_each_entry(formatter, &ts->formatter_list, list) { + ret = axg_tdm_formatter_enable(formatter); + if (ret) { + pr_err("failed to start tdm stream\n"); + goto out; + } + } + +out: + mutex_unlock(&ts->lock); + return ret; +} +EXPORT_SYMBOL_GPL(axg_tdm_stream_start); + +void axg_tdm_stream_stop(struct axg_tdm_stream *ts) +{ + struct axg_tdm_formatter *formatter; + + mutex_lock(&ts->lock); + ts->ready = false; + + /* Stop all the formatters attached to the stream */ + list_for_each_entry(formatter, &ts->formatter_list, list) { + axg_tdm_formatter_disable(formatter); + } + + mutex_unlock(&ts->lock); +} +EXPORT_SYMBOL_GPL(axg_tdm_stream_stop); + +struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface) +{ + struct axg_tdm_stream *ts; + + ts = kzalloc(sizeof(*ts), GFP_KERNEL); + if (ts) { + INIT_LIST_HEAD(&ts->formatter_list); + mutex_init(&ts->lock); + ts->iface = iface; + } + + return ts; +} +EXPORT_SYMBOL_GPL(axg_tdm_stream_alloc); + +void axg_tdm_stream_free(struct axg_tdm_stream *ts) +{ + /* + * If the list is not empty, it would mean that one of the formatter + * widget is still powered and attached to the interface while we + * we are removing the TDM DAI. It should not be possible + */ + WARN_ON(!list_empty(&ts->formatter_list)); + mutex_destroy(&ts->lock); + kfree(ts); +} +EXPORT_SYMBOL_GPL(axg_tdm_stream_free); + +MODULE_DESCRIPTION("Amlogic AXG TDM formatter driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/meson/axg-tdm-formatter.h b/sound/soc/meson/axg-tdm-formatter.h new file mode 100644 index 000000000000..cf947caf3cb1 --- /dev/null +++ b/sound/soc/meson/axg-tdm-formatter.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) + * + * Copyright (c) 2018 Baylibre SAS. + * Author: Jerome Brunet + */ + +#ifndef _MESON_AXG_TDM_FORMATTER_H +#define _MESON_AXG_TDM_FORMATTER_H + +#include "axg-tdm.h" + +struct platform_device; +struct regmap; +struct snd_soc_dapm_widget; +struct snd_kcontrol; + +struct axg_tdm_formatter_ops { + struct axg_tdm_stream *(*get_stream)(struct snd_soc_dapm_widget *w); + void (*enable)(struct regmap *map); + void (*disable)(struct regmap *map); + int (*prepare)(struct regmap *map, struct axg_tdm_stream *ts); +}; + +struct axg_tdm_formatter_driver { + const struct snd_soc_component_driver *component_drv; + const struct regmap_config *regmap_cfg; + const struct axg_tdm_formatter_ops *ops; + bool invert_sclk; +}; + +int axg_tdm_formatter_set_channel_masks(struct regmap *map, + struct axg_tdm_stream *ts, + unsigned int offset); +int axg_tdm_formatter_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *control, + int event); +int axg_tdm_formatter_probe(struct platform_device *pdev); + +#endif /* _MESON_AXG_TDM_FORMATTER_H */ diff --git a/sound/soc/meson/axg-tdm.h b/sound/soc/meson/axg-tdm.h new file mode 100644 index 000000000000..435d95b86457 --- /dev/null +++ b/sound/soc/meson/axg-tdm.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) + * + * Copyright (c) 2018 Baylibre SAS. + * Author: Jerome Brunet + */ + +#ifndef _MESON_AXG_TDM_H +#define _MESON_AXG_TDM_H + +#include +#include +#include +#include +#include + +#define AXG_TDM_NUM_LANES 4 +#define AXG_TDM_CHANNEL_MAX 128 +#define AXG_TDM_RATES (SNDRV_PCM_RATE_5512 | \ + SNDRV_PCM_RATE_8000_192000) +#define AXG_TDM_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) + +struct axg_tdm_iface { + struct clk *sclk; + struct clk *lrclk; + struct clk *mclk; + unsigned long mclk_rate; + + /* format is common to all the DAIs of the iface */ + unsigned int fmt; + unsigned int slots; + unsigned int slot_width; + + /* For component wide symmetry */ + int rate; +}; + +static inline bool axg_tdm_lrclk_invert(unsigned int fmt) +{ + return (fmt & SND_SOC_DAIFMT_I2S) ^ + !!(fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_NB_IF)); +} + +static inline bool axg_tdm_sclk_invert(unsigned int fmt) +{ + return fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_IB_NF); +} + +struct axg_tdm_stream { + struct axg_tdm_iface *iface; + struct list_head formatter_list; + struct mutex lock; + unsigned int channels; + unsigned int width; + unsigned int physical_width; + u32 *mask; + bool ready; +}; + +struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface); +void axg_tdm_stream_free(struct axg_tdm_stream *ts); +int axg_tdm_stream_start(struct axg_tdm_stream *ts); +void axg_tdm_stream_stop(struct axg_tdm_stream *ts); + +static inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts) +{ + axg_tdm_stream_stop(ts); + return axg_tdm_stream_start(ts); +} + +#endif /* _MESON_AXG_TDM_H */ From patchwork Tue Jul 17 15:43:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142177 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3820840ljj; Tue, 17 Jul 2018 08:43:31 -0700 (PDT) X-Google-Smtp-Source: AAOMgpeqj0WkiHAirMAHU45JK+YnpeQsqIIzvIB95SnN7a7mxr7cefvF3KgGTA7keZCs6BXY6koD X-Received: by 2002:a63:291:: with SMTP id 139-v6mr2094663pgc.365.1531842210990; Tue, 17 Jul 2018 08:43:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842210; cv=none; d=google.com; s=arc-20160816; b=XfkVgRnhlvWt5op7ZjxouaBpECAeYRuG4xP0Y/XL9m0l+kWccVF3n63HI5P5Ou+R4E lBhJCssCA3sZWUust6ISDV9OC2qJWt1yDSs1xIzrbxqdzBVQyFXxaXT+nrYWLixfx3ro pK2P3C0oBmiwYet3ExYfRLeykqjrRDbZ2QSsy2kxhKuF/18cyQpbDc1twsgSJ3lqVXVA OYRDkdqXq+JmtgAX4muGDQb2Pn5cJdk8A0s5+OjZDf/WIhB1j5GsrqSwSUok1FKB+bur MLmX50GKBBUUrsUyQPg1sWcKRAD0Sce832QHCajhcbGFT+o749vvK4szXykDib6PUnyL s7tQ== 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=9Vq7WqNYq1Y6EqDZPVqrYIfFVBrINTzO3zRHsykCFCk=; b=I04WELFELxNhiycjQHgpnhFrgJ/sMDFU9Y5VbJhVsP3OKX65c68zbpNhtq/UaEAptQ SmHkVuq2N5VDXMKbECA+/6OnYkhUNB3ls/W3JTgSPwYzUBefs/WBEnl5ZEzn2si5GFkK b5zH331MArkyEO1Pl0r27iAStn/gre5/b/iys4OVLXJOIHx+Tj4vEnJf8lFEbOTB1xV6 fFMD/XRnmVWzPWUGiCHdO6m8iJlXgqf3YDsg5C6x3CTyx1q59ctLM0H9ox/v41ePHOWb aiJuPwWuguGJ+xFFnH8riI9OK/HcGZQI2BJJ1JNTpmxCbfKsf+uUV34PLJ3xEZbcEfUo dFRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=GFh3XZBe; 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 j10-v6si1166935pfc.335.2018.07.17.08.43.30; Tue, 17 Jul 2018 08:43:30 -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=GFh3XZBe; 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 S1731608AbeGQQQm (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:42 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:55285 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731545AbeGQQQl (ORCPT ); Tue, 17 Jul 2018 12:16:41 -0400 Received: by mail-wm0-f65.google.com with SMTP id c14-v6so1993465wmb.4 for ; Tue, 17 Jul 2018 08:43:26 -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=9Vq7WqNYq1Y6EqDZPVqrYIfFVBrINTzO3zRHsykCFCk=; b=GFh3XZBeqjVhELdr9jTXiQZ8iL3FqWyTwP3FweOqgLfCbOQ+D1R9+iKE4VIk9xwCyt OyaxvQMaC+2YcbOzyFCPjpHxliRGuwvrapdQQbREhJ86QflR5ObJ08pr11ykJrqVOnu1 Sjg0WJhAOnof/hkL3v4OGfPGo/4JZWx67JeUxspkfHg8RmjTX1/rMqQbchLK8q1zyq6x aVzY+MJqNbY/ImCj1+VBZMotZL8stOeW28oDf7QqryIF0EQ8GPaQ8OV/ajfWKxlYMe53 Kfo3QEKg7XbhIfnEj6IOZ1NSX7TmpEc5uEPDaQsDDSzgUjsIQ3iJtmA88pLqtBO/vF38 j5LA== 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=9Vq7WqNYq1Y6EqDZPVqrYIfFVBrINTzO3zRHsykCFCk=; b=bXhx/vx/d/PZA0Y7n4Dm6tey300ROVFJ+NN8g4Y8bwB7jv3quczBIhP9gEbQCQivzN rTtkOVlrLoefGx6RHf4wW+24aoppoWAwKCc06PD/nSaLfV8VJH4sfgCnPaSEOgYQEuoN Tor0tM0yVCwZrn2du71KKrd2eNzRJ6R0yWSiXfWmoLh1O71VyzOlcjdhuAhZuI2Mmz3M GOqCjtLESYO4T5Si7GAAM6H+qPY1/oE3ttxjfuYGeKdcb7GyQ43Y9/wORBYl6MoD+I5k 6A2mMnX4rDIxjTYsGzfMee5Y2ZPm9s/SxEYHM7WC3KrjfFFtz5xR5JnYDDDNRazcFkmg VaGw== X-Gm-Message-State: AOUpUlENMz2N3xFYQ27fbzYFYD4FXNwZ9VMx7ey4tQmKEffv64OXFlDg 4r+BUs5rouC3DNgMweex6kgEbQ== X-Received: by 2002:a1c:b9cf:: with SMTP id j198-v6mr1759703wmf.93.1531842205406; Tue, 17 Jul 2018 08:43:25 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.24 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:24 -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 RESEND 11/15] ASoC: meson: add tdm output driver Date: Tue, 17 Jul 2018 17:43:00 +0200 Message-Id: <20180717154304.9973-12-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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 output driver which pulls data from FRDDR fifo and produce the TDM signals for 4 output lanes. Signed-off-by: Jerome Brunet --- sound/soc/meson/Kconfig | 8 ++ sound/soc/meson/Makefile | 2 + sound/soc/meson/axg-tdmout.c | 259 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 269 insertions(+) create mode 100644 sound/soc/meson/axg-tdmout.c -- 2.14.4 diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 869b359c2ce7..08a522b77749 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_TDMOUT + tristate "Amlogic AXG TDM Output Support" + select SND_MESON_AXG_TDM_FORMATTER + select SND_MESON_AXG_TDM_INTERFACE + help + Select Y or M to add support for TDM output formatter embedded + in the Amlogic AXG SoC family + 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 1a8eb77402e3..a665c6b76a95 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-tdmout-objs := axg-tdmout.o snd-soc-meson-axg-spdifout-objs := axg-spdifout.o obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o @@ -12,4 +13,5 @@ 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_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-tdmout.c b/sound/soc/meson/axg-tdmout.c new file mode 100644 index 000000000000..f73368ee1088 --- /dev/null +++ b/sound/soc/meson/axg-tdmout.c @@ -0,0 +1,259 @@ +// 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 TDMOUT_CTRL0 0x00 +#define TDMOUT_CTRL0_BITNUM_MASK GENMASK(4, 0) +#define TDMOUT_CTRL0_BITNUM(x) ((x) << 0) +#define TDMOUT_CTRL0_SLOTNUM_MASK GENMASK(9, 5) +#define TDMOUT_CTRL0_SLOTNUM(x) ((x) << 5) +#define TDMOUT_CTRL0_INIT_BITNUM_MASK GENMASK(19, 15) +#define TDMOUT_CTRL0_INIT_BITNUM(x) ((x) << 15) +#define TDMOUT_CTRL0_ENABLE BIT(31) +#define TDMOUT_CTRL0_RST_OUT BIT(29) +#define TDMOUT_CTRL0_RST_IN BIT(28) +#define TDMOUT_CTRL1 0x04 +#define TDMOUT_CTRL1_TYPE_MASK GENMASK(6, 4) +#define TDMOUT_CTRL1_TYPE(x) ((x) << 4) +#define TDMOUT_CTRL1_MSB_POS_MASK GENMASK(12, 8) +#define TDMOUT_CTRL1_MSB_POS(x) ((x) << 8) +#define TDMOUT_CTRL1_SEL_SHIFT 24 +#define TDMOUT_CTRL1_GAIN_EN 26 +#define TDMOUT_CTRL1_WS_INV BIT(28) +#define TDMOUT_SWAP 0x08 +#define TDMOUT_MASK0 0x0c +#define TDMOUT_MASK1 0x10 +#define TDMOUT_MASK2 0x14 +#define TDMOUT_MASK3 0x18 +#define TDMOUT_STAT 0x1c +#define TDMOUT_GAIN0 0x20 +#define TDMOUT_GAIN1 0x24 +#define TDMOUT_MUTE_VAL 0x28 +#define TDMOUT_MUTE0 0x2c +#define TDMOUT_MUTE1 0x30 +#define TDMOUT_MUTE2 0x34 +#define TDMOUT_MUTE3 0x38 +#define TDMOUT_MASK_VAL 0x3c + +static const struct regmap_config axg_tdmout_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = TDMOUT_MASK_VAL, +}; + +static const struct snd_kcontrol_new axg_tdmout_controls[] = { + SOC_DOUBLE("Lane 0 Volume", TDMOUT_GAIN0, 0, 8, 255, 0), + SOC_DOUBLE("Lane 1 Volume", TDMOUT_GAIN0, 16, 24, 255, 0), + SOC_DOUBLE("Lane 2 Volume", TDMOUT_GAIN1, 0, 8, 255, 0), + SOC_DOUBLE("Lane 3 Volume", TDMOUT_GAIN1, 16, 24, 255, 0), + SOC_SINGLE("Gain Enable Switch", TDMOUT_CTRL1, + TDMOUT_CTRL1_GAIN_EN, 1, 0), +}; + +static const char * const tdmout_sel_texts[] = { + "IN 0", "IN 1", "IN 2", +}; + +static SOC_ENUM_SINGLE_DECL(axg_tdmout_sel_enum, TDMOUT_CTRL1, + TDMOUT_CTRL1_SEL_SHIFT, tdmout_sel_texts); + +static const struct snd_kcontrol_new axg_tdmout_in_mux = + SOC_DAPM_ENUM("Input Source", axg_tdmout_sel_enum); + +static struct snd_soc_dai * +axg_tdmout_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_sink_path(w, p) { + if (!p->connect) + continue; + + if (p->sink->id == snd_soc_dapm_dai_in) + return (struct snd_soc_dai *)p->sink->priv; + + be = axg_tdmout_get_be(p->sink); + if (be) + return be; + } + + return NULL; +} + +static struct axg_tdm_stream * +axg_tdmout_get_tdm_stream(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dai *be = axg_tdmout_get_be(w); + + if (!be) + return NULL; + + return be->playback_dma_data; +} + +static void axg_tdmout_enable(struct regmap *map) +{ + /* Apply both reset */ + regmap_update_bits(map, TDMOUT_CTRL0, + TDMOUT_CTRL0_RST_OUT | TDMOUT_CTRL0_RST_IN, 0); + + /* Clear out reset before in reset */ + regmap_update_bits(map, TDMOUT_CTRL0, + TDMOUT_CTRL0_RST_OUT, TDMOUT_CTRL0_RST_OUT); + regmap_update_bits(map, TDMOUT_CTRL0, + TDMOUT_CTRL0_RST_IN, TDMOUT_CTRL0_RST_IN); + + /* Actually enable tdmout */ + regmap_update_bits(map, TDMOUT_CTRL0, + TDMOUT_CTRL0_ENABLE, TDMOUT_CTRL0_ENABLE); +} + +static void axg_tdmout_disable(struct regmap *map) +{ + regmap_update_bits(map, TDMOUT_CTRL0, TDMOUT_CTRL0_ENABLE, 0); +} + +static int axg_tdmout_prepare(struct regmap *map, struct axg_tdm_stream *ts) +{ + unsigned int val = 0; + + /* Set the stream skew */ + switch (ts->iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_DSP_A: + val |= TDMOUT_CTRL0_INIT_BITNUM(1); + break; + + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_DSP_B: + val |= TDMOUT_CTRL0_INIT_BITNUM(2); + break; + + default: + pr_err("Unsupported format: %u\n", + ts->iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK); + return -EINVAL; + } + + /* Set the slot width */ + val |= TDMOUT_CTRL0_BITNUM(ts->iface->slot_width - 1); + + /* Set the slot number */ + val |= TDMOUT_CTRL0_SLOTNUM(ts->iface->slots - 1); + + regmap_update_bits(map, TDMOUT_CTRL0, + TDMOUT_CTRL0_INIT_BITNUM_MASK | + TDMOUT_CTRL0_BITNUM_MASK | + TDMOUT_CTRL0_SLOTNUM_MASK, val); + + /* Set the sample width */ + val = TDMOUT_CTRL1_MSB_POS(ts->width - 1); + + /* FIFO data are arranged in chunks of 64bits */ + switch (ts->physical_width) { + case 8: + /* 8 samples of 8 bits */ + val |= TDMOUT_CTRL1_TYPE(0); + break; + case 16: + /* 4 samples of 16 bits - right justified */ + val |= TDMOUT_CTRL1_TYPE(2); + break; + case 32: + /* 2 samples of 32 bits - right justified */ + val |= TDMOUT_CTRL1_TYPE(4); + break; + default: + pr_err("Unsupported physical width: %u\n", + ts->physical_width); + return -EINVAL; + } + + /* If the sample clock is inverted, invert it back for the formatter */ + if (axg_tdm_lrclk_invert(ts->iface->fmt)) + val |= TDMOUT_CTRL1_WS_INV; + + regmap_update_bits(map, TDMOUT_CTRL1, + (TDMOUT_CTRL1_TYPE_MASK | TDMOUT_CTRL1_MSB_POS_MASK | + TDMOUT_CTRL1_WS_INV), val); + + /* Set static swap mask configuration */ + regmap_write(map, TDMOUT_SWAP, 0x76543210); + + return axg_tdm_formatter_set_channel_masks(map, ts, TDMOUT_MASK0); +} + +static const struct snd_soc_dapm_widget axg_tdmout_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_tdmout_in_mux), + SND_SOC_DAPM_PGA_E("ENC", 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_tdmout_dapm_routes[] = { + { "SRC SEL", "IN 0", "IN 0" }, + { "SRC SEL", "IN 1", "IN 1" }, + { "SRC SEL", "IN 2", "IN 2" }, + { "ENC", NULL, "SRC SEL" }, + { "OUT", NULL, "ENC" }, +}; + +static const struct snd_soc_component_driver axg_tdmout_component_drv = { + .controls = axg_tdmout_controls, + .num_controls = ARRAY_SIZE(axg_tdmout_controls), + .dapm_widgets = axg_tdmout_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(axg_tdmout_dapm_widgets), + .dapm_routes = axg_tdmout_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(axg_tdmout_dapm_routes), +}; + +static const struct axg_tdm_formatter_ops axg_tdmout_ops = { + .get_stream = axg_tdmout_get_tdm_stream, + .prepare = axg_tdmout_prepare, + .enable = axg_tdmout_enable, + .disable = axg_tdmout_disable, +}; + +static const struct axg_tdm_formatter_driver axg_tdmout_drv = { + .component_drv = &axg_tdmout_component_drv, + .regmap_cfg = &axg_tdmout_regmap_cfg, + .ops = &axg_tdmout_ops, + .invert_sclk = true, +}; + +static const struct of_device_id axg_tdmout_of_match[] = { + { + .compatible = "amlogic,axg-tdmout", + .data = &axg_tdmout_drv, + }, {} +}; +MODULE_DEVICE_TABLE(of, axg_tdmout_of_match); + +static struct platform_driver axg_tdmout_pdrv = { + .probe = axg_tdm_formatter_probe, + .driver = { + .name = "axg-tdmout", + .of_match_table = axg_tdmout_of_match, + }, +}; +module_platform_driver(axg_tdmout_pdrv); + +MODULE_DESCRIPTION("Amlogic AXG TDM output formatter driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); From patchwork Tue Jul 17 15:43:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142178 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3820901ljj; Tue, 17 Jul 2018 08:43:34 -0700 (PDT) X-Google-Smtp-Source: AAOMgpccadRl5lzMiQAAuzLupEKnuENKAZHjM4MLjvFEDAfFxBTA3h+tdyOB6FPMBUyZn8mCBbgm X-Received: by 2002:a65:6094:: with SMTP id t20-v6mr2132624pgu.264.1531842214082; Tue, 17 Jul 2018 08:43:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842214; cv=none; d=google.com; s=arc-20160816; b=YjUxjks6bHDoR/17GaO7c2wQ704mNngo3niVw8NweDISQI3F6eTQFTdXwOdTxBuUQc DaZGLotGiGixVZjo8cqc9ZZFLk3S8jXYQ8hNmb5t04bW5mSvX0KTKKiyeojHR4xg4aA8 yEsGnDnlCHuYbPUV8c2Ipl18KBNyzkU0X8z+018QJybU4zXTXgJo47/hpicKGZ9DfCwh stQYk/m2AwLcYRV9LxeD7szT8B1RbnkIoUD2YQa5BLL+OUvcXvfLnmBza/BXxJufpDRy prCRA5Zn9Wm5bJSvREC7MWr+/KOATendhFC0FBOJv+ysEKvF7zQXr9jWfOx2ojL1MyT+ in1w== 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=fYfn6eWt0ds16ETxxQ9EO7Y+UB6FrRqktZCSFevoDFG7+iDMk6UpUAvIB9nJAITAhH VWg4e17ozz+RI8mgQpzGDYSs+CB5GwUgZhKV7Nwo9dkFv5ktL1IBS58cf0jbs1o6iJDA oX0rhpgrS4JDzzIhUkWwD2CLj54wc11LPI0SN0erDTGW9hblCgUF0jyRpZzqsPn5rGsq BHrVXAJYUvnhoxRm0VmtL9W2Wr7rMTVBrsQAvuR+EdlcsyCC3BJsGjIWwNL0M4EGTOhl sqgSw+LnaWgJMQzl4DR8mNLgRp6G7OPc5eMjCftjcKSO2KY5w/gCrSsglOF7IrLJAEwu Jehw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=UjvrkwkC; 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 j67-v6si1260057pgc.186.2018.07.17.08.43.33; Tue, 17 Jul 2018 08:43:34 -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=UjvrkwkC; 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 S1731669AbeGQQQp (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:45 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:37825 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729683AbeGQQQn (ORCPT ); Tue, 17 Jul 2018 12:16:43 -0400 Received: by mail-wm0-f68.google.com with SMTP id a19-v6so2013147wmb.2 for ; Tue, 17 Jul 2018 08:43:27 -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=UjvrkwkCXfnrbEsYYxd64Fs8KXb7gU2udWfBuvXaHBEyNFP8D495YJi5vQTUUmZAzC gmG7FVnFkNErTqe/m627BjH5YYFZZy6Ecp4oSJIuBe1dY0r0NqmYH7l/Ja54PjcVKl5Z XMEYiAZeKhTlERRLfBBi0wptSQNCHXNlIKbST6fln9MaWrQ0P/ugq0DNh/Gad4x/sN71 0f2IOcoWshWdmBqtXydotS5e+MDzbSsd9ZFPlTFsJ3PryGjxMOWzSaBMeFQn7yQhOaU0 Yuibi2/E5FqbjmMhO2Cp03y/BwTyl+JuuMTHAcg1/Q334qlec6Boo7YCJKZeTKUD26sw jhIw== 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=Xz4osC0GfByttNyrKkceQTyzjxY+HinpM53wf7F3MZ1AcqX6W1JjrsXADBAyK407Zn 7O5yl+Dwt06OKBp+yCfWEEu/i9V9PssY8TQjOZZc0uIyhAPfBDAwr7SgHf69nFqRLKiC ydqoZPK5REL3gqyVQKHIYtiZ8hcJifkL0ZlH8Mso2LznVQuG6KYF3H7NWgLOXIvZdDv6 DZU3xz8OQSz3Fsgv6RyoCxXuSTPwHlV2mAV3auHu0FAmWynzAuGe9gTLQGFimlQ16At1 vJ/QKofau3zJd2tz/zjJgkElh1kMyVsYVpi77Zuw4eI3vLZWiGpC3io4VO0nFx0VUiTj 5oEQ== X-Gm-Message-State: AOUpUlEJkvM1bg+88HiiyMgDECTzdPPweUzAfnh5Hq/YQ7y/x7EER8+x M3IW40XCjXwpjtZ4LsV4CQaPZg== X-Received: by 2002:a1c:b756:: with SMTP id h83-v6mr1832934wmf.8.1531842206423; Tue, 17 Jul 2018 08:43:26 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.25 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:25 -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 RESEND 12/15] ASoC: meson: add tdm input driver Date: Tue, 17 Jul 2018 17:43:01 +0200 Message-Id: <20180717154304.9973-13-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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:43:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142180 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3821201ljj; Tue, 17 Jul 2018 08:43:52 -0700 (PDT) X-Google-Smtp-Source: AAOMgpdtzOhZm0EKOLYYXY4DTWOxMwZRob7Q+a0zFNX4OmyDwJ7ZQ4L9pcgK6vbNtkiV91Gzj+1g X-Received: by 2002:a63:686:: with SMTP id 128-v6mr2077946pgg.338.1531842232281; Tue, 17 Jul 2018 08:43:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531842232; cv=none; d=google.com; s=arc-20160816; b=MRQG81wS/BRBUvHDaE4++RdY0vGooD0MFExLSWL3/XYcZnvlL/PQaXuh7hTAVyQR/9 tFVeRIrSFnZva7e/+JQzq/SAaffuGt/b6OiEYo+plUEKuyUYAbaA59pckMyU1JZMgYU6 yHICTD/M2+8VTJ++9NEPFvuoyr10ez5x02QGvnT06rZ2Xt79egF4xhYLsF7+5iPNWTwN cIDZ5unmCX0W5Rz0Xb1GDFNbf/NujWUVVpf0r8MaI8a+2MCkmQEHJW7/JRMrZEskSif5 rqcl/WpfgN4vIvAWue1IQjPn6tx3tEp1iwu60Q+ZTFIla03Ydu+xLUjYMEm0dWZkVvsu AABA== 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=NfF7crfagmkQ65OXa3KqgDIEiPypv49GIW8hCqMTUXjVJ3JwRTGgFu0IkmoYl/CNy0 9DrNYt78aV8WHvdyNdDq4F5DC7UHs14vvotlfm880H4vStW7+wSdLH1wCf+rbAAogptz NVSWgnRp+bjTq9/VkJVlp96v+9YPKqchz7ufC+C0P7Az+sYM3Z3z7pxjRHC0b35Y/SfW L2ZnXMAXPYqlJiDuWaOsEfqEjbBfJvssFI5vbk0Rry3mLZFqS4J8g/xdsSIZ9BDlZViY h5AZnDWKxB7fdsSUNisDS9iR/SJFHg1cgLs5zfO6wksxeHX7oWsTtdl8Tp4v4/8s5VM8 Ti0Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=dEDKps7Y; 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 q10-v6si1108536pge.674.2018.07.17.08.43.52; Tue, 17 Jul 2018 08:43:52 -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=dEDKps7Y; 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 S1731652AbeGQQQp (ORCPT + 31 others); Tue, 17 Jul 2018 12:16:45 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:37035 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730514AbeGQQQn (ORCPT ); Tue, 17 Jul 2018 12:16:43 -0400 Received: by mail-wr1-f66.google.com with SMTP id q10-v6so1736986wrd.4 for ; Tue, 17 Jul 2018 08:43:28 -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=dEDKps7YDghxieJzjM8X9UBYmwOkqbT2PJEv1Ec+rXPRkYmQMD5laevucQA6IufmN4 /3AeqbPYdqV/a4jS3Walgiy2KCIHJA5tb5klid5YA3S3YRUmdbuifX+7wRnjaSfBWvFt 8ofsoodry7PiaiwNxVKcRiVNMjTeiIUzxZ5X4+e/ryvto945E02L8TSuPjcGI9kM85j6 nt9IYhSCG1sfF8vgOZVmv+Y4yRsYiT6wwBp9o4DubKFwRzh/7J1u7CpD+KzCmVkbAjWz ms5AbkWoMC3U/31XxrGhaGx1x7qBF8hRA8mkXokvLh2bzkzU0kITfwyzhu79jq/dw5MV SVTQ== 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=lj1KI7zAad21EBQXxIn6/x1d3kDm13bS7wXlQMVkviZPSdgYg/1IDXDbE5SDI+w5vm CauPJ/DCnsqxByJqwEavwLln4v9s9Jow0AuDLbD+2DT3zWY/5uHaVL4EJ29GBq4yGdK1 4il+32OI0qQMlaHOQYPvN5w6k/Snb7bnQwITdUTSZfpdRLq36YahE3VOlizHtMrbm9Bv mP0WlfsVMckxKVyWfDV0iMAUQU+8+JlCQVC/g32mm3toazX21H5TfXBJADQaQZrdKWYb h7UjplALBZHhtW46X9uwvmcG+uzpE4RnAI6ZKYKcI0BMIYh8Y4a+kDBH+mOOEzznw+zD RCbw== X-Gm-Message-State: AOUpUlGyg8EnRV2GZp+1NAfVbEDu/DyclNnMaJIV9gYsCvdBYmSug5Y1 pqWdqQyfnkfDkVuxJRppIACE+A== X-Received: by 2002:adf:f188:: with SMTP id h8-v6mr1900105wro.214.1531842207504; Tue, 17 Jul 2018 08:43:27 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id s12-v6sm17598252wmc.2.2018.07.17.08.43.26 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:43:26 -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 RESEND 13/15] ASoC: export snd_soc_of_get_slot_mask Date: Tue, 17 Jul 2018 17:43:02 +0200 Message-Id: <20180717154304.9973-14-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717154304.9973-1-jbrunet@baylibre.com> References: <20180717154304.9973-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,