From patchwork Tue Jul 17 15:36:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142151 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3813141ljj; Tue, 17 Jul 2018 08:36:53 -0700 (PDT) X-Google-Smtp-Source: AAOMgpepe0f7TkVMu1B+kTU+MAuPdOXJGZjZeaeoDRSBh6CBX8ukI6frqOP38d8CTT63r3FGnpY3 X-Received: by 2002:a63:941a:: with SMTP id m26-v6mr2050216pge.82.1531841813386; Tue, 17 Jul 2018 08:36:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841813; cv=none; d=google.com; s=arc-20160816; b=vsjlSHFy8HiCQfztcsUtPj3RLaR7vH/JYr3QyG2vDFu0g4JVqUACPx0YqdqeaN8chQ k/cDaUZ3qlv4DV10/+VwPw5H7BymrCBTpTW26d4vVqC5PheRtRRmMksRhN4wsd+aIAU1 W6z2mWbt3T4ydQfz+eZ5wQmniZ9/nzLqoQaYr/g9QiiPEbZ5kfgQqQfnbS/Vxr2mnf98 67oI69IL9Zs6BIT+uu6yjikRwIsQT/HnsQ2NVw2k7cNaXQa+4oi1ju96BlFYuWBX8wJo BK6dSWbgaXdf5Wg8nVYVxl+7wi7pZqwEc3Th7sUmpzygt/drV26LLryszqYoiofS3RR3 IG0w== 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=nw2WVMHMiOd4l6MalgTqt79GGHxY8Ok08X/WCS0IF/Y=; b=hH3E2ENwNEZF8VKhShP90aIqX6oulZkvAXY6hMW/0HZKXEBdlcx2ua2OYIs+pd+58s ghqlznMEx0fRBpZvXxUcofHpDvAokqs6ETqjyr8D7O1STOzwiR5epphC/kss3+1Dz2QM NGSBLCJ6rIaiqPUSiVYsEYl+3wSMG+NLqq5XqQD7iAO8RVgMx0z9/1MqM2+PdTlvLl6U HE/cHa4g/8CtrR/0jL0TyhIyQ4io+R9ip4Y04trKtBUp3heDlw+O1YCZCZjHnTHyx0cO 6kaOlXw9PTf/GPbk4Y//1hiTTD4zSN31keNjvE6/r8rr1l7QL9eOmkkKz3ebsjMO1BUO IpWQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=tEYgpMcS; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-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 f12-v6si1166777pgm.601.2018.07.17.08.36.53; Tue, 17 Jul 2018 08:36:53 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=tEYgpMcS; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729675AbeGQQKD (ORCPT + 5 others); Tue, 17 Jul 2018 12:10:03 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:42961 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729677AbeGQQKB (ORCPT ); Tue, 17 Jul 2018 12:10:01 -0400 Received: by mail-wr1-f65.google.com with SMTP id e7-v6so1706662wrs.9 for ; Tue, 17 Jul 2018 08:36:48 -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=tEYgpMcSVhKeFLn59F2/ms1O7JqnRZw7/Zb/T2X0vIcvIJdGnSHeYnLv05fqmh7f65 1s58Kzr9hhGYc7TDSvB0P32coupLWr6FWTvZQPNNi1BIDj5CR/SAagY0YAtgSJjC88QX 79cCUiri3zpFgnmxaNfpXxtHyocohyN5MOuyioskrjbn5lxcK2xe1hqXPIZYiy/CD0nY sNhBTvcuJamxtqn4LhXYYkDQgZyMlh/VboO9sSMvOTPjBiCNRZpa+EwvmAs44cLVBhyC NNHcmtHY0OZJhp1pfjHzcV2ne8TDTiXk09jM9LanXnTKEuUQZZXlOHtZtRwey6Ll/G8I R8rQ== 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=r88yV7vEaHIiO4ndoC+7Ji6xQ8ZCVvHiAohysqIzpnxlKOojs1oh+tefcYElJLt9DY udvsTQzUBZXmtPaO1sAtCFj6aIzQtVcOQUtxKBhPo09IHBeO3LyTsZS0JqW2dJ1WM+On M1ZBQGsOJby22iZpb3iRKf/CZrCGsI+vkfgig99vzqk1eeugp0hPSmVuIABjE9QJWBCs pxzNg1jbB2JZFC82y1IsP7DNzIsAcDoYb90aBRKPWy4idrzcnLoZTT0WuSoqS/6V0zdx 6P1E6Bub6Qgdgolryk1rKScxR61DjV2O0VpBmjOOkyurMPqBnaLkQ9YVtSk/Q+qHWjOP jI0Q== X-Gm-Message-State: AOUpUlEESng0vWsOyJk60Q/ZBaKkXeQWsaM521FJ717vVdR9VxLM0YcM z2t+hi7x9XjDWTwT2aiYfhUFO6te X-Received: by 2002:adf:8276:: with SMTP id 109-v6mr1804507wrb.127.1531841808205; Tue, 17 Jul 2018 08:36:48 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.36.47 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:36:47 -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 01/15] ASoC: meson: add axg fifos DT binding documentation Date: Tue, 17 Jul 2018 17:36:25 +0200 Message-Id: <20180717153643.8806-2-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@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 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html 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:36:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142169 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3815194ljj; Tue, 17 Jul 2018 08:38:38 -0700 (PDT) X-Google-Smtp-Source: AAOMgpe13F2uqz0R1a9QCPH2c6MdE2hYixzDasj3pA3w959eCqC8+jCvWNi4e+gWzFbZ0fmAD+aa X-Received: by 2002:a17:902:ab90:: with SMTP id f16-v6mr2190576plr.182.1531841918296; Tue, 17 Jul 2018 08:38:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841918; cv=none; d=google.com; s=arc-20160816; b=zdLDwj9UkephuB9bddK3nM71Hl1gFs68BfLaIlXIUYl8owNUpXFgDTWACn8ojacPRY StUGH+tGO5HUjsD8vb2IAPwaIRgg/aKqry7FfPnFF2fwZ2etjDq2yW42uQmNG327cTgV 8sPz9t/fOOb9E+0N81bu6XEpwU1E+CCPN2eryn1lKckqBLscXwvlP8U1YEyha+UaaEBA seMIHTA+izTmSXPj5gXPeUIgrFuv9Z17zStu6fRd6zJRtbcrtUvjEoEPDyliJU/n0O3Z aFyUmtb0aKLHap8ViZgrI0023S1FImykZuglcCfszBkvDLJaJzfyfVPkjx5KuxKwNeYP cbMg== 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=ObzoIbszGsCmSHCgo1hROdFV4i0q6q98Fx0np8dIIFw=; b=HnCoUN2lNh0sQ6py+XxqUFezAN0Dm0Z5W1Ga5I6uZ5BU1iDEbRMU3/R2LBe70qDyiY kqndwV7IODGthcXYpXb3zZkeNN731zTzju/V41wdMagDylAgHf41OnrdNhyjRXKDLhSC YVZXSyILFOkA/a6b4WeSkXHX9sKJKySNOlAdi5Sn0OIpp3T88AqlCs9JgK084BBEC1jq 7tGdhruh8+zwRKMD63cpZ1ksHEWdI7dGzjlTAJ9AbhAHs3Aq+T3L67vFDaOjEDqrNqOb NbTKroGO3rw3pQnwSJSY8ApRWXpIOCP1bbptmvCoRzDf5PrYoybK3jzUW9dtkAyFDEGq ItgA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=nOzCp3GB; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g10-v6si1131585pge.694.2018.07.17.08.38.38; Tue, 17 Jul 2018 08:38:38 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=nOzCp3GB; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729677AbeGQQLt (ORCPT + 5 others); Tue, 17 Jul 2018 12:11:49 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:54127 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730371AbeGQQKH (ORCPT ); Tue, 17 Jul 2018 12:10:07 -0400 Received: by mail-wm0-f66.google.com with SMTP id s9-v6so1974075wmh.3 for ; Tue, 17 Jul 2018 08:36:54 -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=nOzCp3GB+YXez9IagCoZCya2xkPkTA/P6MDbH8qf9IV4tO7NUsHnF+2sKZNEiaHRSD r4/62oHZBzBmU0w0CLfWoZm8KEnNqwsy0uRtMjXkbvCwHTFzIu6jLKzZ7699kB1CEf8D aq8OMHpcC2a4eag/OrtLgWn9gGUiKOKRsq5R1c243htahJqlCLSTLggNHQaqip6bsrXV soLzQGl+8iKZOhCY3oECBRRiRweDFfGwGsMpnti0eW+5HR+Umss7LYYc3c+TA65Vu1tF 0y1ADf3rRAWpIlKW6SLLYpYTSRAeslyvBGK7TiC9KEy3eaBkgtroC83wVftUr4iuXXdH LX4A== 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=hhygJlipqKYO6kdhG96izGeQRNWnP5f4E/l1Y5kaMZWiQ1Y7Rhvqj6HsrjhhVCAabt MHpxYhVvQS5U25cxbq0pcD8x/3AQQ7m/t7Z3EcSwVpWXsdC5hZ/S5pxLWk+P+QuIjnyQ J3e2F7ovl9RiBQ05ZQew3sPOKH0CajPTEvJkC3vukXebyZrADO/L/DOXOqFypBvNohX+ 16M4RJK4bFI46LwkDLn+jAS/ZIfp5UyxtY3tQckYuFSWr0XAX97MgHHW8TyU+6B/Udoc QDvHQZF1yqVTzMbI8eh15Jxzi3l6zpyMWb3L6m26JYexKiTW29hj1ZowMQ/P7JDZ+Ab8 g/5Q== X-Gm-Message-State: AOUpUlGhCx5XriOg7AJ4fYyQm8t+MfsPVlYzEgxOiQB1f5mRFGdKSNAq CurOc79IGQX3MTv6mI90hbm30A== X-Received: by 2002:a1c:7c13:: with SMTP id x19-v6mr1778173wmc.27.1531841813426; Tue, 17 Jul 2018 08:36:53 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.36.52 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:36:52 -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 05/15] ASoC: meson: add axg spdif output DT bindings documentation Date: Tue, 17 Jul 2018 17:36:30 +0200 Message-Id: <20180717153643.8806-7-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@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 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html 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:36:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142154 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3813266ljj; Tue, 17 Jul 2018 08:36:59 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfEUCb37mHCsFKuFXv5YbzYDil8JOhg8/T2rwyzgzqi93LwtilE2dpLJeuhUf/2pIbZPBua X-Received: by 2002:a63:4c56:: with SMTP id m22-v6mr2006121pgl.299.1531841819535; Tue, 17 Jul 2018 08:36:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841819; cv=none; d=google.com; s=arc-20160816; b=WLxrlOAgjdZICbrN/Jm7YYsUqs0dsiWFa9a15oREhotCrP4OZTyo2lHdqBqrxJ+Dn2 rRlSOgn5EgrDi0TaFSZMttZO7y9PSm4i0imSsIehmetwMQUXmRDiLiDWBWdrU54iT63n X0bq8K9vIK7wsG22hpUuVA79/XleTlMCtzO0/DpbLfUwYS4nr4t+2PAvy8bUomreVyUa ELzBpJsPqpx+oZHdYWBGPoWpwEw19wWTAsbCLV5MVj74SqJG7taY+dRtiG8lCUwatCE3 834WYj/LGBmvYMbjhNqZyiohJ/o8bri+tJFqYBfHOVNd+Rn7dDX8s5WWUIKGGXntUo/9 Mbxw== 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=gM8aXn2j1D326cO+Z/D9OgNONv3NNNZbPcug/cERQ/o=; b=qE3EoFJfLFFV7PP339c2napyyk20hIGaa5dvIoW468f7RWgGKvxVdimGZrdCbMxqFt zqE2hYT5ttRpgDlJ3De/yDk5wqZ7ylV58glFKTIKay/+Qh1z0I5lNuM4EpeqyfKXDxgD yFHYzrK3AIPJATh/3RtuEW3/jhAVtbrgd5TAGbv3uXtzPKCRcTOLgXUlfmJqw7wCg/lH NfUhS1wmiwZYk4TSV5TXHUVEmxmKrMHY/rx+khzTvQw7ROjhXzMyINLflfrAxbIXCljf ETUMrpMGwzgz9xeHew0DdzPmDZMyWEkYec+6PZoiJKas2fKHPNLlEYcfj7T1+JaMDeoF WF9g== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=pbMAVZBT; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f16-v6si1146929pff.13.2018.07.17.08.36.59; Tue, 17 Jul 2018 08:36:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=pbMAVZBT; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730798AbeGQQKJ (ORCPT + 5 others); Tue, 17 Jul 2018 12:10:09 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:55620 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729677AbeGQQKJ (ORCPT ); Tue, 17 Jul 2018 12:10:09 -0400 Received: by mail-wm0-f68.google.com with SMTP id f21-v6so1965625wmc.5 for ; Tue, 17 Jul 2018 08:36:56 -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=9ALvnp5uq2xLjL8h9XoNNtkDEu/doiTiZp6Fj7u9vNo=; b=pbMAVZBT9/aEWBYTIJMttF8XDtjNc0VOUWAtwyo/FYEeHyUGLSQaiA/vFPuCvIUIds KdmqX5nmhfbGlXmDJUveTzehNqmPWhB/4U/p+eTxrQycZCvO9xlsv9obRoAin1UZW1IG SfTxJwx/eJ4YAhWp/13MHi7nT3bET7eHHWb9oImPbzRRn0z9Y4XH+jzlj7/MXvXm95UM FxZH/2eXKJBiFXKTPzR45yQFuccZqWNhuO3U97k/fhrIjyyVFmZN0b5lh4rkYoLYEE1y yXu8oOHGFnHw1DrFh1PzC61Mf64Os3ALj6uGurxtkF8qc4c6hHPnGbFOyVDUOr8eGEgE swTg== 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=9ALvnp5uq2xLjL8h9XoNNtkDEu/doiTiZp6Fj7u9vNo=; b=Ouq+ZbUmjtttaRH1LCY/dGvfr1rW9HLNcMsXuDCR1ezaMgzk0Ch34GQmbOzWk7G+SL N/5qFtayfQlN2CMyne9Gg/DqRbpq0OgMg3s10QjPFotyp79JNG7f0MYziOQGigKXK0dg tfQvFG5IcD+gzjXcQaojj/m8nZ31wZac4UUJGX125v5LiCCMO6fO0SQcCQB0Kb/hgUUC 9ofGW2rVQNI4aHofm9qsac1VTYm+QGGvlVr5aPx7kOLcU6OEyXSQuFtLxxT3GfWpDenG C5Kw0QmbqvWVh5G8kkKH2l96VcYKQGukLSig4uoJ1TN2DwHT4CIiw1EtkCpEkaKiK4Jd i8cw== X-Gm-Message-State: AOUpUlHP9mdy5tHC9i5KbXACL+ZO1pjc9TbVaO1GOre0q1WkwvphI6ON nmukEc6O5q+IIRE7f/g6CSjMXQ== X-Received: by 2002:a1c:b915:: with SMTP id j21-v6mr1771836wmf.104.1531841815589; Tue, 17 Jul 2018 08:36:55 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.36.54 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:36:55 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 07/15] ASoC: meson: add axg tdm formatters DT binding documentation Date: Tue, 17 Jul 2018 17:36:32 +0200 Message-Id: <20180717153643.8806-9-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add the DT binding 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 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt new file mode 100644 index 000000000000..1c1b7490554e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt @@ -0,0 +1,28 @@ +* Amlogic Audio TDM formatters + +Required properties: +- compatible: 'amlogic,axg-tdmin' or + 'amlogic,axg-tdmout' +- reg: physical base address of the controller and length of memory + mapped region. +- clocks: list of clock phandle, one for each entry clock-names. +- clock-names: should contain the following: + * "pclk" : peripheral clock. + * "sclk" : bit clock. + * "sclk_sel" : bit clock input multiplexer. + * "lrclk" : sample clock + * "lrclk_sel": sample clock input multiplexer + +Example of TDMOUT_A on the A113 SoC: + +tdmout_a: audio-controller@500 { + compatible = "amlogic,axg-tdmout"; + reg = <0x0 0x500 0x0 0x40>; + clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>, + <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; +}; From patchwork Tue Jul 17 15:36:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142164 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3814422ljj; Tue, 17 Jul 2018 08:38:01 -0700 (PDT) X-Google-Smtp-Source: AAOMgpc5+3RKIda3yJmcpuZ0QZ8VSyLSjtv4pY3lRFikxNRMqzg88+MsDV2z8Hm1DhdgQuhY6Ywi X-Received: by 2002:a63:1126:: with SMTP id g38-v6mr2066946pgl.122.1531841881672; Tue, 17 Jul 2018 08:38:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841881; cv=none; d=google.com; s=arc-20160816; b=UMeRmpovZU6CV31FcWw2hsl/xOwu4dPFXV5jioWx7APyEdBYlxU0MOuuF8fDedceZO 6o4R/Cp8jiNAm9l9PvotpCVf7+tBxxZZRtuuyzGzyU1tUui4gXNU7nPodoXZaOTUV4NP pswEcFNHPArwnxWlEu4i2U3cjT01M4vcE2cLWB0OcUuR8Hm95KxAcWu3F48SH/z+MUTF hbTYb3gIfospeiCvgJ+Fbqt25VKtl/CWngygLyg30cIzTBCx/AkUt2HxTXqS5qVjjN8A 77vrLmYF1SDb7A/7rUUXD2eCouf2Lqpm3Jy8y5od2fsZA/tAH+c9h+Qk0Y/TbrSnT9HJ efpQ== 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=9ByC4itomJz7xBC1xAus8gsVD0717+Chb9lm/lRhmkg=; b=RVjihaogD5XPi2qWJAuHHdYlQJWjGGvlNgn4vmqqkzDrWCE/EEd9cNdi7HCauPgMby l9EwQL1U6bv+Y5l+UZ+Rg18cYAeYFof7YrUAuKdSlnHqioeiPFh52Ivo0AgucE6YueWr HguouOsjMG2V4IhgJD3dXYkKb8BzfIBzWBwRnWvjh+t07tY9z2e6QMFTodRXYAPj8Ktz 2Cm2R9BBxuk9h+FAAfCRfbky2gENy5NTH32IT/FZwEusbP4LGvSrRUw0BQvSRrKiQIF8 g9pEZg+3T1X2hcGXGw5ST8/nLUxM84vPLONfH7wZ0aPnRcxO37W/IIzHREKzP5Dh8BG0 fJUQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=NMr9YnsC; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m37-v6si1072366plg.491.2018.07.17.08.38.01; Tue, 17 Jul 2018 08:38:01 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=NMr9YnsC; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731285AbeGQQKP (ORCPT + 5 others); Tue, 17 Jul 2018 12:10:15 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:51786 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730638AbeGQQKO (ORCPT ); Tue, 17 Jul 2018 12:10:14 -0400 Received: by mail-wm0-f65.google.com with SMTP id s12-v6so1984134wmc.1 for ; Tue, 17 Jul 2018 08:37:00 -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=NMr9YnsC9aW6K/F8HnFeed7X90AGcLKJTQxldgpLUH1YLmgVFseAahYQHJp6lIq3a2 RuKnjI2K1Qs9BSOa3gjtOiqw2runVOYB7oCZptgmuJHVvsXzFHWm2CG6Y8Jzkyy+Vl/i Nz4dVENf8R7+Ew0TgrPsngsHFpCZfrONHjHOI/OPhLuCaaFLDQhEoGiRm2wrnyOyCFQR 32Vwh3WC6ONkhNV0tQo7IQ86MfEgxBghXWwimm53Aof5XR+eIVWJlw/qyQiKCnbGxH8s jgC66Q2nbqRi01KIYX/OpdMgPzLHit71srIukhV7YfjtQc6WWEmPM1kvH9JhwrjhWtrB SMkQ== 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=Kd3J4VIGXQJEG4EP4s63DH+ATYAsNWq/JPgYCS0sTYFLr8tgQ48nyxa5ri13qs2mu8 3OsuIXx3evMKx7DPvjaq+4YaTi2oEBB1ZhKjgnjl7UEh7gEQw4f6jXy/53hC3xr1rHPU DByCKMNsYCBbQrPOd0Fkj+fYuPu7lvwuYCCoVsvdCvphtcTa+bgKGkcEaNCFs4svf5DF 7LUIlwSwGcUWG47RUZ92ZKzkUdX1Eq/+BVD3wnTcsWG5aLaiBolGI5YfXc3KEUZ/Lgt5 iZQdkeI3nlfC6yHKkocGQXyJ6XZRwj5NgcuHBJ2TtitN7ihsXcxz8nb2+Fe/dCdjF4CI fRTQ== X-Gm-Message-State: AOUpUlHWpADo1tnvdTkyYtRKAFE+uxFslyUaF1QQ+K4U4x4SDf3atdq8 7PbElTb9qdRqX7HmMmUEpvCdQQ== X-Received: by 2002:a1c:cbc1:: with SMTP id b184-v6mr1809923wmg.149.1531841819712; Tue, 17 Jul 2018 08:36:59 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.36.58 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:36:59 -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 09/15] ASoC: meson: add tdm formatter base driver Date: Tue, 17 Jul 2018 17:36:36 +0200 Message-Id: <20180717153643.8806-13-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@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 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html 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:36:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142156 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3813399ljj; Tue, 17 Jul 2018 08:37:06 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfnPRzuvaXlS0mSYvhSFjTXmRi4NQMcEaWnFikifyhsifACRZXAihz0xf3u7ZD1GYy90Bv/ X-Received: by 2002:a17:902:2e83:: with SMTP id r3-v6mr2169595plb.80.1531841826652; Tue, 17 Jul 2018 08:37:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841826; cv=none; d=google.com; s=arc-20160816; b=HiCFdqh6+ohlf/Oud9/kyp/qSwCeOflvezkurmwo49ykZc4nUUZt1SBp/l5kL6Y7NX EUFx2YzoZHay06SpcDEYtXz10FC3EFR4QLBU+9+n4XBREc/9y8fLdV4J/477QP8DpzQ3 iv8hZdn4LaQAuj9mQGVwG1SRinv5g84+w88UUiserLxiTb/q55d0WIYx7bYCo+FutzV/ Lp6VAJh0/mL2wdQC3/VaQ0md2Pihom5nTw3KqQWAyU4EAOy+krDhlwSGzqJuSzj6+Hvz 70TVv8cI6PMug3W1AAoaIFxvDTF+97lDLi6zwr1Txz7HMUzJHUqTpqLRnzBL7WDzibho SIGw== 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=SKbDw6Qr+FFVfOIJ/I9O3JTGeHXHj6s0/+w92X0SCD0=; b=ozkG9TzonMtkH0s+ecDSj8/FK1zyb0ofAPXBBsh4LcHwYuWPqDSiYPg9AoQt5m78pL HaSuC/OKrf6wvv4IqUljlHCh2qvC9P4Ir0E/V1nh0v0JAxrEzQ3bLzlYWo91EMmpxKdg 8mjv92rXAQM0F51vm+NerqJCd7WxeegeDnSnuCpdQWWsUUsv1rq2NoSMpJzPH6ndezEG V63enujCIgc8rK+XYks1454b8lcxmzGGar8SXhulS+pet9sj8DFX+vbaJ9SgTe+o7AMz n7Kmo424Eh/qOITLK0HMJix16GdRr26MSKb9fox5jcNEXZQtO+Hq27SXOQrs5p5DAr7t Ph/Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=DjGHzVCG; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-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 n1-v6si1020752pgv.641.2018.07.17.08.37.06; Tue, 17 Jul 2018 08:37:06 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=DjGHzVCG; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729640AbeGQQKR (ORCPT + 5 others); Tue, 17 Jul 2018 12:10:17 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:38333 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731205AbeGQQKQ (ORCPT ); Tue, 17 Jul 2018 12:10:16 -0400 Received: by mail-wm0-f68.google.com with SMTP id 69-v6so1983043wmf.3 for ; Tue, 17 Jul 2018 08:37:02 -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=DjGHzVCGLsadHfOgMJtZa2/wVdBMpSaeX+ODU7qO9Arx6V1SHEDdsUME4dJkzNwr8D 5gvOJ3Cgny5zT4fSYynOEYoniNLX3o/8MFH4A1LP+82XtsR1Rlk0Y+KMze6grsM+NCzo dsBJ5v/9rFPOTttKNKBVTx+QV7IleCBv+PiXYr956tPHaBgj3uD4zwRvs4uUXbMPKalk GufaDBTLDM8X4Ewm/7YGr4Bd4DJZ4BSBpV/Y51yqogKEn/O0SR/kw6Mtya0FIpRJlGKS Yw2YDEwPNTWje974UCFyjeKAt+z9xL5xfgbfWF3/CoaUZzTP/vXXAt4ID80cGmP6inhU 3PeQ== 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=pwJTNNmTXT5xLWquHTGNUcdg+e5zWXvSMtckqkBeq402zrdxx5gScFwnd1/YVHjNWa eehMGvCGP9I/TdumYvYe9ZkPgEan/S8UlrHlWZLLbnXM25CQ5a2NfHr1W/wh98seKN4R GgnlLfyBeb/8zd2uu3DIC2+Tr1EdddVP3CQ9M1AUIuZsSP06NDt6b3TiXT5MRNPXTNbK SNMLruoN/CzgK7Hg+gjBr/PTQTTOiyXvfQUIruBcHyrEtQFAbqIo3fVU6qqxD465/rd+ ksKDKhJ+vVc3EdRD4spZ493D1DbFwpYYdB5kgXewogAk/ahG3SGPRlZgyPFQ3yaNIXSG KGPA== X-Gm-Message-State: AOUpUlEnBAq0pFgVV5yRcVe4NwmgsdOp3m0mQW2X8yvQUCdrNQugvZ3v BHkOW9dezSYOIeCg0UllQZHejg== X-Received: by 2002:a1c:e043:: with SMTP id x64-v6mr1726778wmg.58.1531841821860; Tue, 17 Jul 2018 08:37:01 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.37.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:37:01 -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 11/15] ASoC: meson: add tdm output driver Date: Tue, 17 Jul 2018 17:36:38 +0200 Message-Id: <20180717153643.8806-15-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@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 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html 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:36:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142159 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3813481ljj; Tue, 17 Jul 2018 08:37:11 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfGyWksu43NVqC45zc1tG6rc+M6E3cW2ppJ0oymCQ53bULdP1A4m8mHe/KKXo1ktaiF1yl1 X-Received: by 2002:a17:902:6ac3:: with SMTP id i3-v6mr2134115plt.252.1531841830917; Tue, 17 Jul 2018 08:37:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841830; cv=none; d=google.com; s=arc-20160816; b=KJHp/2BD/Di34r0ND5petVhhfF7WcwBXS0kWFxOK+oFt+DSQvxWzY6/vkqxhInikJU 4ykzTil/x3qyUjA/i13ts8qzZfN7dA5p/2jSd0QL0vzee5Zzm2u4ZLbHbtcuXv478u1c kvsILkeG8VUBHua4RrfopiPEH3MTHxpFlK9npl7jjYpOZHExXU/FmpKzcVU3bUyz5Cye nd9q1n+hdYr1ELBqE8gcIKj8RveJuOWG5bg1Eh/iH+dhZ1uehKMVH4c+5fYUZl4fWDrL QapiUtSW11BtHUcWtOBxv+wU3S3KTNA0J3pvBUeo7EupTs+g3tHPKFmF91K2FjV82vJz xlzQ== 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=VBv8/QDWk+qHjJZaxe5JulpWKLqIxa2ERSD6Eqkd9xk=; b=tMJsaW5SqSfLh/RSVllWq8Z6XbF5Kdwl6ETyyDitr+YyrxOpideKSEpD5bsW9VDXbG 1nKRoGW22ek5V6nekcGW1Oo5SF0u8/jQ7BhFp5bXL1Ca3pWvzBt2/Soj+72hhpdgLC5/ XLATEcyRG/snXVRerJ4eQ43NTsXTH3hEyvIBsmvop9KcgyqaYKPzap+Z9pGXnmvyNF3G ODHnJrHVRSseYin/VSiTVWQqdjCNnzAYfXAejy0GfrLXaCrMjxuvcEfd12lq8a1J+Sjb QWlp7FWhboxLjp4n+Rmn486+t4y0Vzzi3crEuIFYn5PVFJk7bwZo13Epf1aHTx2pCO5/ naNA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=zD0rJqpz; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z13-v6si1172763pfc.118.2018.07.17.08.37.10; Tue, 17 Jul 2018 08:37:10 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=zD0rJqpz; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729683AbeGQQKV (ORCPT + 5 others); Tue, 17 Jul 2018 12:10:21 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:44522 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731412AbeGQQKU (ORCPT ); Tue, 17 Jul 2018 12:10:20 -0400 Received: by mail-wr1-f65.google.com with SMTP id r16-v6so1698731wrt.11 for ; Tue, 17 Jul 2018 08:37:06 -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=N6GTffq4VROTez5mVO69vAu2OUH/qIKN2B9n0MrCC48=; b=zD0rJqpzzmZeQRz+j/gOf0lnbKMZFINYgLzHVw1wZL9K1//hl43MbJvT1ynw9kXR8o Uy+awm0k3n6FqkWlGnngjmsS8JMQ/jEVcEVMOTUdZol/Vm1pf0eCZuobbC4L53SJ24CT SWr6jXpJ0SsZ+V0LkwsC/68cBL/8iZfWKcyEU7PYNXciPuTSrn3BAy8dPpL8t49NoISQ 9xf8d45EFRitwgIEp0Ua1aOTcttg3U84cDbeyLUWLRJQK3ti5v6DtbrJot/MnBm7iCeH 9azCXL+DhkAjECAfiEyt4G2Y+3i6wT23cTgFJv5EhV8SKDAp1q9HdH74AkX8Jfv/Rarn PF9A== 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=N6GTffq4VROTez5mVO69vAu2OUH/qIKN2B9n0MrCC48=; b=qX0CUZwXeasNCkfL2lNan3dg289E8zZ3Xy1F0iFowOT0kFsZ/OQauXrh0rdEo1R+O+ 9TNmq5wj3RUXnFPaa/bGLNyRSeMqTvinuZa7zXaUithbXcldXj7epjUFxutUdG9PlpQH iiRpcbROLjDECFzSWVvdw3DF3KUe7tU2PWFb581bJUWTwklWPlyhc4sBWbAJrKix0agJ sXRfnF9L3sQ42dX6j8SK7c0BSaD1Q/PxFExk1sbhFQ4aaZT050rRt2GilG8169bU2U9h 2qU1m87msLhjCNyNMi+I+1dqWgOcehIGWW7FaThvH5SKJma/DP2XXClzWvjgA4pZJq4e XP/w== X-Gm-Message-State: AOUpUlFK7xyvzP17a/v/0P3MnUZh39wCahu7uXqd3lvM4MOUOAJGvO8F wSHzD5EalaAlaB2zctAaW4L3wg== X-Received: by 2002:adf:c554:: with SMTP id s20-v6mr1857934wrf.46.1531841826105; Tue, 17 Jul 2018 08:37:06 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.37.05 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:37:05 -0700 (PDT) From: Jerome Brunet To: Mark Brown , Liam Girdwood , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org Subject: [PATCH 14/15] ASoC: meson: add axg sound card DT bindings documentation Date: Tue, 17 Jul 2018 17:36:42 +0200 Message-Id: <20180717153643.8806-19-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add the DT bindings documentation for axg sound card Signed-off-by: Jerome Brunet --- .../bindings/sound/amlogic,axg-sound-card.txt | 124 +++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,axg-sound-card.txt -- 2.14.4 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-sound-card.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-sound-card.txt new file mode 100644 index 000000000000..39e005da0407 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-sound-card.txt @@ -0,0 +1,124 @@ +Amlogic AXG sound card: + +Required properties: + +- compatible: "amlogic,axg-sound-card" +- amlogic,name : User specified audio sound card name, one string + +Optional properties: + +- amlogic,aux-devs : List of phandles pointing to auxiliary devices +- amlogic,widgets : Please refer to widgets.txt. +- amlogic,routing : A list of the connections between audio components. + +Subnodes: + +- amlogic,dai-link: Container for dai-link level properties and the + CODEC sub-nodes. There should be at least one (and + probably) subnode of this type. + +Required dai-link properties: + +- sound-dai: phandle and port of the CPU DAI. + +Required TDM Backend dai-link properties: +- dai-format : CPU/CODEC common audio format + +Optional TDM Backend dai-link properties: +- dai-tdm-slot-rx-mask-{0,1,2,3}: Receive direction slot masks +- dai-tdm-slot-tx-mask-{0,1,2,3}: Transmit direction slot masks + When omitted, mask is assumed to have to no + slots. A valid must have at one slot, so at + least one these mask should be provided with + an enabled slot. +- dai-tdm-slot-num : Please refer to tdm-slot.txt. + If omitted, slot number is set to accommodate the largest + mask provided. +- dai-tdm-slot-width : Please refer to tdm-slot.txt. default to 32 if omitted. +- mclk-fs : Multiplication factor between stream rate and mclk + +Backend dai-link subnodes: + +- codec: dai-link representing backend links should have at least one subnode. + One subnode for each codec of the dai-link. + dai-link representing frontend links have no codec, therefore have no + subnodes + +Required codec subnodes properties: + +- sound-dai: phandle and port of the CODEC DAI. + +Optional codec subnodes properties: + +- dai-tdm-slot-tx-mask : Please refer to tdm-slot.txt. +- dai-tdm-slot-rx-mask : Please refer to tdm-slot.txt. + +Example: + +sound { + compatible = "amlogic,axg-sound-card"; + amlogic,name = "AXG-S420"; + amlogic,aux-devs = <&tdmin_a>, <&tdmout_c>; + amlogic,widgets = "Line", "Lineout", + "Line", "Linein", + "Speaker", "Speaker1 Left", + "Speaker", "Speaker1 Right"; + "Speaker", "Speaker2 Left", + "Speaker", "Speaker2 Right"; + amlogic,routing = "TDMOUT_C IN 0", "FRDDR_A OUT 2", + "SPDIFOUT IN 0", "FRDDR_A OUT 3", + "TDM_C Playback", "TDMOUT_C OUT", + "TDMIN_A IN 2", "TDM_C Capture", + "TDMIN_A IN 5", "TDM_C Loopback", + "TODDR_A IN 0", "TDMIN_A OUT", + "Lineout", "Lineout AOUTL", + "Lineout", "Lineout AOUTR", + "Speaker1 Left", "SPK1 OUT_A", + "Speaker2 Left", "SPK2 OUT_A", + "Speaker1 Right", "SPK1 OUT_B", + "Speaker2 Right", "SPK2 OUT_B", + "Linein AINL", "Linein", + "Linein AINR", "Linein"; + + amlogic,dai-link@0 { + sound-dai = <&frddr_a>; + }; + + amlogic,dai-link@1 { + sound-dai = <&toddr_a>; + }; + + amlogic,dai-link@2 { + sound-dai = <&tdmif_c>; + dai-format = "i2s"; + dai-tdm-slot-tx-mask-2 = <1 1>; + dai-tdm-slot-tx-mask-3 = <1 1>; + dai-tdm-slot-rx-mask-1 = <1 1>; + mclk-fs = <256>; + + codec@0 { + sound-dai = <&lineout>; + }; + + codec@1 { + sound-dai = <&speaker_amp1>; + }; + + codec@2 { + sound-dai = <&speaker_amp2>; + }; + + codec@3 { + sound-dai = <&linein>; + }; + + }; + + amlogic,dai-link@4 { + sound-dai = <&spdifout>; + + codec { + sound-dai = <&spdif_dit>; + }; + }; +}; From patchwork Tue Jul 17 15:36:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 142160 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp3813513ljj; Tue, 17 Jul 2018 08:37:12 -0700 (PDT) X-Google-Smtp-Source: AAOMgpeKvmEX4NustZFIeLjleV0M9Lw7E7mZdvgApxRyZ70GGw0qzNub/i+4lmYsePzddPSr0lG8 X-Received: by 2002:a62:2646:: with SMTP id m67-v6mr1198988pfm.254.1531841832492; Tue, 17 Jul 2018 08:37:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531841832; cv=none; d=google.com; s=arc-20160816; b=ga07FwmOf6wPnlz7b3RAoT51OWgQ0jC4PwaIVEnhXSPz/R6MtABE3uWPy+jX2puipk eke9TkJoWVduReKCrr+mByQt/F1kk4wsnimsVv2nRk2U9+33wmXPo5iSfKGGQuf/zjdk RvKRbpgJAoX2aaHPcFXhzobIbN/4UjdcoLhTRt+jL2Ag6wNIVHrqsx11uDX4FedjRt5m fItzCio4mavqmuBvVT0HtULkypCbtHbyq8xvIcYXCS6JIbdu99BGAl/kGo53o5hWt3Ip Jkijszz57OeW3111p8SRQljefbGjwCoAAeR0yE/tO0r9RDmY0gXmfPtntDeAF4PeGzFF zI2g== 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=eQH5FfxfpVEVcJwDqD+dgaqcqqPgOyvW3VUc5DaZVv0=; b=Cf7gaXRD2iq6JwrnqYvqMIvfHhPCvRdSZwKLXDpTKH2YU+d8lq4n58sP+A+D0Q2SwI VR8uXrV6ZHTzZOlBBLeeizU/c9USv2O4d3VQXWmwJftPAnqaBHuKd2Y6smtRNMp3wYId PNwCDQ/xMUmKuF4JVbNtFrKs0MUXfetHL1HR9TVGsYehG64MSq+FJP33v2cYnTZ5Cyge JZSCogs07SCx4vP9Y5pp6nQwz54jHNpXtZxIvP3yVaHWXSDc9lWvfblDphySMlNGDe2M ukeTmVWR3YumOIGErMytOCx3fnBEz2ID74tF6sCe6SCrxsTfUl4DZw4pcaS46Fd3S2Sz D+vg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=RxDYlf1J; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z13-v6si1172763pfc.118.2018.07.17.08.37.12; Tue, 17 Jul 2018 08:37:12 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=RxDYlf1J; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731296AbeGQQKW (ORCPT + 5 others); Tue, 17 Jul 2018 12:10:22 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:38341 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730811AbeGQQKV (ORCPT ); Tue, 17 Jul 2018 12:10:21 -0400 Received: by mail-wm0-f67.google.com with SMTP id 69-v6so1983390wmf.3 for ; Tue, 17 Jul 2018 08:37:08 -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=G74vTuT1DlINnuNuMu1EDadR9iCBF+SYA+UnFGqXqHY=; b=RxDYlf1JrGyxJSyNyC20Bvb40M8czIKRmWgRUIhPInyaTvaT24YB+rjnUR8lDac2FE ZGqADMcQK+KPlc3rz8XMvTnHJaBx2YCImDOftLmEibvXvv+X0A7+CzztzC08FoIwPnq5 MXt5mUuf79yqVQTmo9WpfyVsezUsgg6jK871I4A0yWNA6iOXvgXvQKiR7b9pAK1dtMq1 cI87OhA198qQNaQFlRtpKRo9MKadcoJLrtChWwqysEHNReF7DbEsF6jU7n9/fq7fFLx5 J1GJHAd6VosfcYFwTk2D1c/907060es1U7UUF3/pIAUI8s2N7fJXFhxjtiTKfceLH2y9 v82g== 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=G74vTuT1DlINnuNuMu1EDadR9iCBF+SYA+UnFGqXqHY=; b=ULLLAej1N9up7/1+n7p5eWQtvTBw/TEZJzNIlz+cF0rBvUeM2CIX2bLruls8ues/7Z FBbNV+ctds/5Nbj64qStYxFarTVQWLxQCaj23z9q3r4dEmOKJoG1yw4KzwZonR+wmKmt RLLu3A+wQ8nr+3mjDEthjLi/FjyBRhMDHqOW/cExcZKfuLs238iCyVaopOvHEMa84VA+ KkAciPSH84DV9yG6uc2JUrhr5eyatHHZQMqcreri0tc8bf3jdA0EyP++gX/QciMtH6fY +491l8WQvMyiUz3gMeqtxR0jojbb3f/wJ8O9zLxcbf3MtpK5ULNOu6T0lWRBiOO8nLtC wzQg== X-Gm-Message-State: AOUpUlEBemfkycbDYmyrMQ4XMA0e/J5Q8F6//TV7KQdxZd7wQTcfAaEd ONh1nY/ybObObHvhmwqDG/hJJw== X-Received: by 2002:a1c:9b43:: with SMTP id d64-v6mr1708288wme.109.1531841827384; Tue, 17 Jul 2018 08:37:07 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id h12-v6sm16971464wmb.3.2018.07.17.08.37.06 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 17 Jul 2018 08:37:06 -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 15/15] ASoC: meson: add axg sound card support Date: Tue, 17 Jul 2018 17:36:43 +0200 Message-Id: <20180717153643.8806-20-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153643.8806-1-jbrunet@baylibre.com> References: <20180717153643.8806-1-jbrunet@baylibre.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add the axg sound card to handle the specifities of the axg audio sub system. This card is required to: * setup the dpcm links specific to the AXG (with a cpu sound dai) * handle the 4 lanes masks of the tdm interfaces * add the loopback link when a tdm pad interface has a playback stream * handle multi-codec links Signed-off-by: Jerome Brunet --- sound/soc/meson/Kconfig | 11 + sound/soc/meson/Makefile | 2 + sound/soc/meson/axg-card.c | 671 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 684 insertions(+) create mode 100644 sound/soc/meson/axg-card.c -- 2.14.4 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 00d05df67b52..4cf93c05a982 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -43,6 +43,17 @@ config SND_MESON_AXG_TDMOUT Select Y or M to add support for TDM output formatter embedded in the Amlogic AXG SoC family +config SND_MESON_AXG_SOUND_CARD + tristate "Amlogic AXG Sound Card Support" + select SND_MESON_AXG_TDM_INTERFACE + imply SND_MESON_AXG_FRDDR + imply SND_MESON_AXG_TODDR + imply SND_MESON_AXG_TDMIN + imply SND_MESON_AXG_TDMOUT + imply SND_MESON_AXG_SPDIFOUT + help + Select Y or M to add support for the AXG SoC sound card + 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 f62833fb44d8..c5e003b093db 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -7,6 +7,7 @@ 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-sound-card-objs := axg-card.o snd-soc-meson-axg-spdifout-objs := axg-spdifout.o obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o @@ -16,4 +17,5 @@ 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_SOUND_CARD) += snd-soc-meson-axg-sound-card.o obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c new file mode 100644 index 000000000000..d6d1081d94ad --- /dev/null +++ b/sound/soc/meson/axg-card.c @@ -0,0 +1,671 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright (c) 2018 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include + +#include "axg-tdm.h" + +struct axg_card { + struct snd_soc_card card; + void **link_data; +}; + +struct axg_dai_link_tdm_mask { + u32 tx; + u32 rx; +}; + +struct axg_dai_link_tdm_data { + unsigned int mclk_fs; + unsigned int slots; + unsigned int slot_width; + u32 *tx_mask; + u32 *rx_mask; + struct axg_dai_link_tdm_mask *codec_masks; +}; + +#define PREFIX "amlogic," + +static int axg_card_reallocate_links(struct axg_card *priv, + unsigned int num_links) +{ + struct snd_soc_dai_link *links; + void **ldata; + + links = krealloc(priv->card.dai_link, + num_links * sizeof(*priv->card.dai_link), + GFP_KERNEL | __GFP_ZERO); + ldata = krealloc(priv->link_data, + num_links * sizeof(*priv->link_data), + GFP_KERNEL | __GFP_ZERO); + + if (!links || !ldata) { + dev_err(priv->card.dev, "failed to allocate links\n"); + return -ENOMEM; + } + + priv->card.dai_link = links; + priv->link_data = ldata; + priv->card.num_links = num_links; + return 0; +} + +static int axg_card_parse_dai(struct snd_soc_card *card, + struct device_node *node, + struct device_node **dai_of_node, + const char **dai_name) +{ + struct of_phandle_args args; + int ret; + + if (!dai_name || !dai_of_node || !node) + return -EINVAL; + + ret = of_parse_phandle_with_args(node, "sound-dai", + "#sound-dai-cells", 0, &args); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(card->dev, "can't parse dai %d\n", ret); + return ret; + } + *dai_of_node = args.np; + + return snd_soc_get_dai_name(&args, dai_name); +} + +static int axg_card_set_link_name(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + const char *prefix) +{ + char *name = devm_kasprintf(card->dev, GFP_KERNEL, "%s.%s", + prefix, link->cpu_of_node->full_name); + if (!name) + return -ENOMEM; + + link->name = name; + link->stream_name = name; + + return 0; +} + +static void axg_card_clean_references(struct axg_card *priv) +{ + struct snd_soc_card *card = &priv->card; + struct snd_soc_dai_link *link; + int i, j; + + if (card->dai_link) { + for (i = 0; i < card->num_links; i++) { + link = &card->dai_link[i]; + of_node_put(link->cpu_of_node); + for (j = 0; j < link->num_codecs; j++) + of_node_put(link->codecs[j].of_node); + } + } + + if (card->aux_dev) { + for (i = 0; i < card->num_aux_devs; i++) + of_node_put(card->aux_dev[i].codec_of_node); + } + + kfree(card->dai_link); + kfree(priv->link_data); +} + +static int axg_card_add_aux_devices(struct snd_soc_card *card) +{ + struct device_node *node = card->dev->of_node; + struct snd_soc_aux_dev *aux; + int num, i; + + num = of_count_phandle_with_args(node, PREFIX "aux-devs", NULL); + if (num == -ENOENT) { + /* + * It is ok to have no auxiliary devices but for this card it + * is a strange situtation. Let's warn the about it. + */ + dev_warn(card->dev, "card has no auxiliary devices\n"); + return 0; + } else if (num < 0) { + dev_err(card->dev, "error getting auxiliary devices: %d\n", + num); + return num; + } + + aux = devm_kcalloc(card->dev, num, sizeof(*aux), GFP_KERNEL); + if (!aux) + return -ENOMEM; + card->aux_dev = aux; + card->num_aux_devs = num; + + for (i = 0; i < card->num_aux_devs; i++, aux++) { + aux->codec_of_node = of_parse_phandle(node, + PREFIX "aux-devs", i); + if (!aux->codec_of_node) + return -EINVAL; + } + + return 0; +} + +static int axg_card_tdm_be_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card); + struct axg_dai_link_tdm_data *be = + (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; + struct snd_soc_dai *codec_dai; + unsigned int mclk; + int ret, i; + + if (be->mclk_fs) { + mclk = params_rate(params) * be->mclk_fs; + + for (i = 0; i < rtd->num_codecs; i++) { + codec_dai = rtd->codec_dais[i]; + ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, + SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) + return ret; + } + + ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, + SND_SOC_CLOCK_OUT); + if (ret && ret != -ENOTSUPP) + return ret; + } + + return 0; +} + +static const struct snd_soc_ops axg_card_tdm_be_ops = { + .hw_params = axg_card_tdm_be_hw_params, +}; + +static int axg_card_tdm_dai_init(struct snd_soc_pcm_runtime *rtd) +{ + struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card); + struct axg_dai_link_tdm_data *be = + (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; + struct snd_soc_dai *codec_dai; + int ret, i; + + for (i = 0; i < rtd->num_codecs; i++) { + codec_dai = rtd->codec_dais[i]; + ret = snd_soc_dai_set_tdm_slot(codec_dai, + be->codec_masks[i].tx, + be->codec_masks[i].rx, + be->slots, be->slot_width); + if (ret && ret != -ENOTSUPP) { + dev_err(codec_dai->dev, + "setting tdm link slots failed\n"); + return ret; + } + } + + ret = axg_tdm_set_tdm_slots(rtd->cpu_dai, be->tx_mask, be->rx_mask, + be->slots, be->slot_width); + if (ret) { + dev_err(rtd->cpu_dai->dev, "setting tdm link slots failed\n"); + return ret; + } + + return 0; +} + +static int axg_card_tdm_dai_lb_init(struct snd_soc_pcm_runtime *rtd) +{ + struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card); + struct axg_dai_link_tdm_data *be = + (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; + int ret; + + /* The loopback rx_mask is the pad tx_mask */ + ret = axg_tdm_set_tdm_slots(rtd->cpu_dai, NULL, be->tx_mask, + be->slots, be->slot_width); + if (ret) { + dev_err(rtd->cpu_dai->dev, "setting tdm link slots failed\n"); + return ret; + } + + return 0; +} + +static int axg_card_add_tdm_loopback(struct snd_soc_card *card, + int *index) +{ + struct axg_card *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_dai_link *pad = &card->dai_link[*index]; + struct snd_soc_dai_link *lb; + int ret; + + /* extend links */ + ret = axg_card_reallocate_links(priv, card->num_links + 1); + if (ret) + return ret; + + lb = &card->dai_link[*index + 1]; + + lb->name = kasprintf(GFP_KERNEL, "%s-lb", pad->name); + if (!lb->name) + return -ENOMEM; + + lb->stream_name = lb->name; + lb->cpu_of_node = pad->cpu_of_node; + lb->cpu_dai_name = "TDM Loopback"; + lb->codec_name = "snd-soc-dummy"; + lb->codec_dai_name = "snd-soc-dummy-dai"; + lb->dpcm_capture = 1; + lb->no_pcm = 1; + lb->ops = &axg_card_tdm_be_ops; + lb->init = axg_card_tdm_dai_lb_init; + + /* Provide the same link data to the loopback */ + priv->link_data[*index + 1] = priv->link_data[*index]; + + /* + * axg_card_clean_references() will iterate over this link, + * make sure the node count is balanced + */ + of_node_get(lb->cpu_of_node); + + /* Let add_links continue where it should */ + *index += 1; + + return 0; +} + +static unsigned int axg_card_parse_daifmt(struct device_node *node, + struct device_node *cpu_node) +{ + struct device_node *bitclkmaster = NULL; + struct device_node *framemaster = NULL; + unsigned int daifmt; + + daifmt = snd_soc_of_parse_daifmt(node, PREFIX, + &bitclkmaster, &framemaster); + daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; + + /* If no master is provided, default to cpu master */ + if (!bitclkmaster || bitclkmaster == cpu_node) { + daifmt |= (!framemaster || framemaster == cpu_node) ? + SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBS_CFM; + } else { + daifmt |= (!framemaster || framemaster == cpu_node) ? + SND_SOC_DAIFMT_CBM_CFS : SND_SOC_DAIFMT_CBM_CFM; + } + + of_node_put(bitclkmaster); + of_node_put(framemaster); + + return daifmt; +} + +static int axg_card_parse_cpu_tdm_slots(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + struct device_node *node, + struct axg_dai_link_tdm_data *be) +{ + char propname[32]; + u32 tx, rx; + int i; + + be->tx_mask = devm_kcalloc(card->dev, AXG_TDM_NUM_LANES, + sizeof(*be->tx_mask), GFP_KERNEL); + be->rx_mask = devm_kcalloc(card->dev, AXG_TDM_NUM_LANES, + sizeof(*be->rx_mask), GFP_KERNEL); + if (!be->tx_mask || !be->rx_mask) + return -ENOMEM; + + for (i = 0, tx = 0; i < AXG_TDM_NUM_LANES; i++) { + snprintf(propname, 32, "dai-tdm-slot-tx-mask-%d", i); + snd_soc_of_get_slot_mask(node, propname, &be->tx_mask[i]); + tx = max(tx, be->tx_mask[i]); + } + + /* Disable playback is the interface has no tx slots */ + if (!tx) + link->dpcm_playback = 0; + + for (i = 0, rx = 0; i < AXG_TDM_NUM_LANES; i++) { + snprintf(propname, 32, "dai-tdm-slot-rx-mask-%d", i); + snd_soc_of_get_slot_mask(node, propname, &be->rx_mask[i]); + rx = max(rx, be->rx_mask[i]); + } + + /* Disable capture is the interface has no rx slots */ + if (!rx) + link->dpcm_capture = 0; + + /* ... but the interface should at least have one of them */ + if (!tx && !rx) { + dev_err(card->dev, "tdm link has no cpu slots\n"); + return -EINVAL; + } + + of_property_read_u32(node, "dai-tdm-slot-num", &be->slots); + if (!be->slots) { + /* + * If the slot number is not provided, set it such as it + * accommodates the largest mask + */ + be->slots = fls(max(tx, rx)); + } else if (be->slots < fls(max(tx, rx)) || be->slots > 32) { + /* + * Error if the slots can't accommodate the largest mask or + * if it is just too big + */ + dev_err(card->dev, "bad slot number\n"); + return -EINVAL; + } + + of_property_read_u32(node, "dai-tdm-slot-width", &be->slot_width); + + return 0; +} + +static int axg_card_parse_codecs_masks(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + struct device_node *node, + struct axg_dai_link_tdm_data *be) +{ + struct axg_dai_link_tdm_mask *codec_mask; + struct device_node *np; + + codec_mask = devm_kcalloc(card->dev, link->num_codecs, + sizeof(*codec_mask), GFP_KERNEL); + if (!codec_mask) + return -ENOMEM; + + be->codec_masks = codec_mask; + + for_each_child_of_node(node, np) { + snd_soc_of_get_slot_mask(np, "dai-tdm-slot-rx-mask", + &codec_mask->rx); + snd_soc_of_get_slot_mask(np, "dai-tdm-slot-tx-mask", + &codec_mask->tx); + + codec_mask++; + } + + return 0; +} + +static int axg_card_parse_tdm(struct snd_soc_card *card, + struct device_node *node, + int *index) +{ + struct axg_card *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_dai_link *link = &card->dai_link[*index]; + struct axg_dai_link_tdm_data *be; + int ret; + + /* Allocate tdm link parameters */ + be = devm_kzalloc(card->dev, sizeof(*be), GFP_KERNEL); + if (!be) + return -ENOMEM; + priv->link_data[*index] = be; + + /* Setup tdm link */ + link->ops = &axg_card_tdm_be_ops; + link->init = axg_card_tdm_dai_init; + link->dai_fmt = axg_card_parse_daifmt(node, link->cpu_of_node); + + of_property_read_u32(node, "mclk-fs", &be->mclk_fs); + + ret = axg_card_parse_cpu_tdm_slots(card, link, node, be); + if (ret) { + dev_err(card->dev, "error parsing tdm link slots\n"); + return ret; + } + + ret = axg_card_parse_codecs_masks(card, link, node, be); + if (ret) + return ret; + + /* Add loopback if the pad dai has playback */ + if (link->dpcm_playback) { + ret = axg_card_add_tdm_loopback(card, index); + if (ret) + return ret; + } + + return 0; +} + +static int axg_card_set_be_link(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + struct device_node *node) +{ + struct snd_soc_dai_link_component *codec; + struct device_node *np; + int ret, num_codecs; + + link->no_pcm = 1; + link->dpcm_playback = 1; + link->dpcm_capture = 1; + + num_codecs = of_get_child_count(node); + if (!num_codecs) { + dev_err(card->dev, "be link %s has no codec\n", + node->full_name); + return -EINVAL; + } + + codec = devm_kcalloc(card->dev, num_codecs, sizeof(*codec), GFP_KERNEL); + if (!codec) + return -ENOMEM; + + link->codecs = codec; + link->num_codecs = num_codecs; + + for_each_child_of_node(node, np) { + ret = axg_card_parse_dai(card, np, &codec->of_node, + &codec->dai_name); + if (ret) { + of_node_put(np); + return ret; + } + + codec++; + } + + ret = axg_card_set_link_name(card, link, "be"); + if (ret) + dev_err(card->dev, "error setting %s link name\n", np->name); + + return ret; +} + +static int axg_card_set_fe_link(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + bool is_playback) +{ + link->dynamic = 1; + link->dpcm_merged_format = 1; + link->dpcm_merged_chan = 1; + link->dpcm_merged_rate = 1; + link->codec_dai_name = "snd-soc-dummy-dai"; + link->codec_name = "snd-soc-dummy"; + + if (is_playback) + link->dpcm_playback = 1; + else + link->dpcm_capture = 1; + + return axg_card_set_link_name(card, link, "fe"); +} + +static int axg_card_cpu_is_capture_fe(struct device_node *np) +{ + return of_device_is_compatible(np, PREFIX "axg-toddr"); +} + +static int axg_card_cpu_is_playback_fe(struct device_node *np) +{ + return of_device_is_compatible(np, PREFIX "axg-frddr"); +} + +static int axg_card_cpu_is_tdm_iface(struct device_node *np) +{ + return of_device_is_compatible(np, PREFIX "axg-tdm-iface"); +} + +static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, + int *index) +{ + struct snd_soc_dai_link *dai_link = &card->dai_link[*index]; + int ret; + + ret = axg_card_parse_dai(card, np, &dai_link->cpu_of_node, + &dai_link->cpu_dai_name); + if (ret) + return ret; + + if (axg_card_cpu_is_playback_fe(dai_link->cpu_of_node)) + ret = axg_card_set_fe_link(card, dai_link, true); + else if (axg_card_cpu_is_capture_fe(dai_link->cpu_of_node)) + ret = axg_card_set_fe_link(card, dai_link, false); + else + ret = axg_card_set_be_link(card, dai_link, np); + + if (ret) + return ret; + + if (axg_card_cpu_is_tdm_iface(dai_link->cpu_of_node)) + ret = axg_card_parse_tdm(card, np, index); + + return ret; +} + +static int axg_card_add_links(struct snd_soc_card *card) +{ + struct axg_card *priv = snd_soc_card_get_drvdata(card); + struct device_node *node = card->dev->of_node; + struct device_node *np; + int num, i, ret; + + num = of_get_child_count(node); + if (!num) { + dev_err(card->dev, "card has no links\n"); + return -EINVAL; + } + + ret = axg_card_reallocate_links(priv, num); + if (ret) + return ret; + + i = 0; + for_each_child_of_node(node, np) { + ret = axg_card_add_link(card, np, &i); + if (ret) { + of_node_put(np); + return ret; + } + + i++; + } + + return 0; +} + +static int axg_card_parse_of_optional(struct snd_soc_card *card, + const char *propname, + int (*func)(struct snd_soc_card *c, + const char *p)) +{ + /* If property is not provided, don't fail ... */ + if (!of_property_read_bool(card->dev->of_node, propname)) + return 0; + + /* ... but do fail if it is provided and the parsing fails */ + return func(card, propname); +} + +static const struct of_device_id axg_card_of_match[] = { + { .compatible = "amlogic,axg-sound-card", }, + {} +}; +MODULE_DEVICE_TABLE(of, axg_card_of_match); + +static int axg_card_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct axg_card *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + snd_soc_card_set_drvdata(&priv->card, priv); + + priv->card.owner = THIS_MODULE; + priv->card.dev = dev; + + ret = snd_soc_of_parse_card_name(&priv->card, PREFIX "name"); + if (ret < 0) + return ret; + + ret = axg_card_parse_of_optional(&priv->card, PREFIX "routing", + snd_soc_of_parse_audio_routing); + if (ret) { + dev_err(dev, "error while parsing routing\n"); + return ret; + } + + ret = axg_card_parse_of_optional(&priv->card, PREFIX "widgets", + snd_soc_of_parse_audio_simple_widgets); + if (ret) { + dev_err(dev, "error while parsing widgets\n"); + return ret; + } + + ret = axg_card_add_links(&priv->card); + if (ret) + goto out_err; + + ret = axg_card_add_aux_devices(&priv->card); + if (ret) + goto out_err; + + ret = devm_snd_soc_register_card(dev, &priv->card); + if (ret) + goto out_err; + + return 0; + +out_err: + axg_card_clean_references(priv); + return ret; +} + +static int axg_card_remove(struct platform_device *pdev) +{ + struct axg_card *priv = platform_get_drvdata(pdev); + + axg_card_clean_references(priv); + + return 0; +} + +static struct platform_driver axg_card_pdrv = { + .probe = axg_card_probe, + .remove = axg_card_remove, + .driver = { + .name = "axg-sound-card", + .of_match_table = axg_card_of_match, + }, +}; +module_platform_driver(axg_card_pdrv); + +MODULE_DESCRIPTION("Amlogic AXG ALSA machine driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2");