From nobody Mon May 25 08:13:47 2026 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D333F48B36A for ; Fri, 15 May 2026 15:11:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778857879; cv=none; b=f3Qx5lhY08sD7KsqtCOhnnKfdpXp2YF4Jtqv7KTdesMU4KcZQJBq3j9EFHH23zbulLwLzspPPAy+vFEo4Ys9r3ilXWRK+0LKyIP1lZkQcDQSU1pMelhSZptnOAn/4+GSP2qTivkesQvhvgO8BlIW0G+bS4kYLU7fdUU535Ab7/s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778857879; c=relaxed/simple; bh=j6Zh4RLoIBZtyp/kwYar+Xu3SLB01yR+UX6gB7d84TE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=B8Ju80TH5Ibe7/W165mwjTSeaPMlUNM7M7dvBLSVgzlpEzWhFpmfIX6s25S1/9AA9+k0g3rW1eNbyGhEbBTfKHwbjvJ8zRWfjrtvkyRsUL/v8+EeKxIRg5cnUYlPQy5SVv4clCC3tuzRDwG3x/PsVurKlgWB3m7TJhZ6KhJEvr0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.b=dnUc9wh6; arc=none smtp.client-ip=209.85.221.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.b="dnUc9wh6" Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-44a74032ff8so6966421f8f.1 for ; Fri, 15 May 2026 08:11:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20251104.gappssmtp.com; s=20251104; t=1778857875; x=1779462675; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=rDDrzBwWLv7cxXzysL5yYXylItmsqFDKcdeZuZx/a38=; b=dnUc9wh6pFl6CjEekwGsbAZW3V0w23UbCmxf47+l9eJcD/Rp8AxHjR2sXeswDfxGi7 4loF14CEP0msMqVxm2iN+skTX0mH9Yi4mPyVLM3V01PLAdRbohojdAdg8a/NB8IPcLo0 JVUqRUVGe+7THN8sMMHVgxrgeDLYfNSr37i9vgLADJMytEFPzZRTtlXIyo+ITDy/Ap9l XPtqfJUXXm8yZh+bJOEZR2SI+M4M4bzDKNlmNqTmW+H7BdXMHm3UPiKZOqe577XSy+c3 xX95G1SVyinJ0Fk0YVT6ekYDnDc4WZUapnXNwljGXsSRpDMATzTPP8qlwpRZr/kJ8nog XvpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778857875; x=1779462675; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=rDDrzBwWLv7cxXzysL5yYXylItmsqFDKcdeZuZx/a38=; b=J0TvtIL+KSouuDeciz1Yc3ZcGsjnuX0ouwvm9/BEhmPB+7xrHky1Wgoe7PVJHUlyP2 oZLWW7lqtm5O3mgbQRxdeIXqEjoxaOm0l9tkGWEl3Mf2mR6hYJ6BiDAPa5P+vWAcjTa9 kzcMtr1w3iEOQdOG3GKPPen6MWJodrtbrf07VJiIQLBp2X2TRqXmrzbTsSoFayx+eXcb 84dfO3JYoLObJbCitZifq7iphSWBRnPkNRjhGQ2WRE9SLcpE+A/9by0G9h7CuJo8uYTN jqs/yB0NOlDwkylQ4z7ttzgIz4WT48Xh7fbYm3AsOezc7+21SBNH6NRempZS+vE57KCt sFmA== X-Gm-Message-State: AOJu0YzObQF1b7Ljpic4lUjMF6fKmNcMFqCSnrOT974mljvOgtV2Ko0R HYmLzPKb1Sj4EmaORZAz1knJ0MAo1D50qtuQ9dnce3tkAW/LIMESx27VJwsRj8pdpV8= X-Gm-Gg: Acq92OH8VaLCf25UoCC23f2LNrvUE4znw90h8HFdi6xRCdRc6Xt7bXsyJ2YDRQr+SxT WnUS1zgfcsJVULPUn7UytnqvrHL42aaCC4d9W8J84FGFZ1BkyD8sQRuhM3QQcpSCgI8l15fK+xo QU6ecximT+vWkp/aDFEOina803Q5X2eI1ZCIyxlyVorLeFi04c4QCe42doJZHOqPhmfPnXIqO4J nnYn0MNxkAy7FZ2zMh9jGE0nVQNDUj0lZM/7U0l9bfH8v8svasf5NPT3U2YWKEuoR64cV7a1bZa CuuwN/kebFviT2e3QMLK1Es3nuqyPF0ME2tDh+IeREFsB9XmMbeIN+ArIuMbc5C5zXnTpStv2Eb ak+0MZde7Cf5f3nt20GV5trKrjfg0s7FegsbTDtLw+XrMu4e7FpdMkjL37KqUrfKCqPDuO3xOl4 +qLs1n0LoqtCysS73tUAR4 X-Received: by 2002:a05:6000:250a:b0:45d:4b37:7fcf with SMTP id ffacd0b85a97d-45e5c58951emr6150818f8f.15.1778857875103; Fri, 15 May 2026 08:11:15 -0700 (PDT) Received: from [127.0.1.1] ([151.41.223.93]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45da0a19c2dsm15262062f8f.21.2026.05.15.08.11.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2026 08:11:14 -0700 (PDT) From: Valerio Setti Date: Fri, 15 May 2026 17:10:37 +0200 Subject: [PATCH 1/4] ASoC: meson: gx: add gx-formatter and gx-interface Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260515-reshape-aiu-as-axg-v1-1-53b457784ff3@baylibre.com> References: <20260515-reshape-aiu-as-axg-v1-0-53b457784ff3@baylibre.com> In-Reply-To: <20260515-reshape-aiu-as-axg-v1-0-53b457784ff3@baylibre.com> To: Jerome Brunet , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Neil Armstrong , Kevin Hilman , Martin Blumenstingl Cc: linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-amlogic@lists.infradead.org, Valerio Setti X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=11315; i=vsetti@baylibre.com; h=from:subject:message-id; bh=j6Zh4RLoIBZtyp/kwYar+Xu3SLB01yR+UX6gB7d84TE=; b=owGbwMvMwCF2z3ty7kUrRgbG02pJDFns5v31Lufn3Togwrkoq36i9Qw/rjX9GdeMVPrFWk+yH Fun+Muto5SFQYyDQVZMkYVl+r3fBaVqD40TThbAzGFlAhnCwMUpABM5xMrIsFjmd/bqK9ytE3dO Pvxcr6I7fsrG8NwWPUGJH20TdFW3mTEyTJYTNnnVqf89bObMKLn4HxtbVkpOFO5mvtskMT9jWUI /FwA= X-Developer-Key: i=vsetti@baylibre.com; a=openpgp; fpr=0497DEFB707526E13360C970DE4B936DD13A0100 These files are the basic block which allow to shape I2S in GX devices the same as the AXG ones: the DAI backend only controls the interface (i.e. clocks and pins) whereas a formatter takes care of properly formatting the data. gx-formatter and gx-interface are strongly inspired to axg-tdm-formatter and axg-tdm, respectively. The long term plan is to join the two platforms to use the same formatter solution. There is only a minor addition here compared to what has been done for AXG and it's "gx_formatter_create()" which is required in order to let already existing AIU code to make use of this formatter without making any devicetree change. Signed-off-by: Valerio Setti --- sound/soc/meson/Makefile | 1 + sound/soc/meson/gx-formatter.c | 277 +++++++++++++++++++++++++++++++++++++= ++++ sound/soc/meson/gx-formatter.h | 47 +++++++ sound/soc/meson/gx-interface.h | 45 +++++++ 4 files changed, 370 insertions(+) diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index 24078e4396b02d545d8ba4bcb1632979001354e3..146ec81526ba091a174a113ce3d= 8412ddbbfd9dd 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -4,6 +4,7 @@ snd-soc-meson-aiu-y :=3D aiu.o snd-soc-meson-aiu-y +=3D aiu-acodec-ctrl.o snd-soc-meson-aiu-y +=3D aiu-codec-ctrl.o snd-soc-meson-aiu-y +=3D aiu-encoder-i2s.o +snd-soc-meson-aiu-y +=3D gx-formatter.o snd-soc-meson-aiu-y +=3D aiu-encoder-spdif.o snd-soc-meson-aiu-y +=3D aiu-fifo.o snd-soc-meson-aiu-y +=3D aiu-fifo-i2s.o diff --git a/sound/soc/meson/gx-formatter.c b/sound/soc/meson/gx-formatter.c new file mode 100644 index 0000000000000000000000000000000000000000..db93546ed9217f711fcdbeddbd8= 15ce21f27bab5 --- /dev/null +++ b/sound/soc/meson/gx-formatter.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright (c) 2026 BayLibre, SAS. +// Author: Valerio Setti + +#include +#include +#include +#include + +#include "gx-formatter.h" + +struct gx_formatter { + struct list_head list; + struct gx_stream *stream; + const struct gx_formatter_driver *drv; + bool enabled; + struct regmap *map; +}; + +static int gx_formatter_enable(struct gx_formatter *formatter) +{ + int ret; + + /* Do nothing if the formatter is already enabled */ + if (formatter->enabled) + return 0; + + /* Setup the stream parameter in the formatter */ + if (formatter->drv->ops->prepare) { + ret =3D formatter->drv->ops->prepare(formatter->map, + formatter->drv->quirks, + formatter->stream); + if (ret) + return ret; + } + + /* Finally, actually enable the formatter */ + if (formatter->drv->ops->enable) + formatter->drv->ops->enable(formatter->map); + + formatter->enabled =3D true; + + return 0; +} + +static void gx_formatter_disable(struct gx_formatter *formatter) +{ + /* Do nothing if the formatter is already disabled */ + if (!formatter->enabled) + return; + + if (formatter->drv->ops->disable) + formatter->drv->ops->disable(formatter->map); + + formatter->enabled =3D false; +} + +static int gx_formatter_attach(struct gx_formatter *formatter) +{ + struct gx_stream *ts =3D formatter->stream; + int ret =3D 0; + + mutex_lock(&ts->lock); + + /* Catch up if the stream is already running when we attach */ + if (ts->ready) { + ret =3D gx_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 gx_formatter_detach(struct gx_formatter *formatter) +{ + struct gx_stream *ts =3D formatter->stream; + + mutex_lock(&ts->lock); + list_del(&formatter->list); + mutex_unlock(&ts->lock); + + gx_formatter_disable(formatter); +} + +static int gx_formatter_power_up(struct gx_formatter *formatter, + struct snd_soc_dapm_widget *w) +{ + struct gx_stream *ts =3D 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; + + formatter->stream =3D ts; + ret =3D gx_formatter_attach(formatter); + if (ret) + return ret; + + return 0; +} + +static void gx_formatter_power_down(struct gx_formatter *formatter) +{ + gx_formatter_detach(formatter); + formatter->stream =3D NULL; +} + +int gx_formatter_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *control, + int event) +{ + struct snd_soc_component *c; + struct gx_formatter *formatter; + int ret =3D 0; + + c =3D snd_soc_dapm_to_component(w->dapm); + + if (w->priv) + formatter =3D w->priv; + else + formatter =3D snd_soc_component_get_drvdata(c); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret =3D gx_formatter_power_up(formatter, w); + break; + + case SND_SOC_DAPM_PRE_PMD: + gx_formatter_power_down(formatter); + break; + + default: + dev_err(c->dev, "Unexpected event %d\n", event); + return -EINVAL; + } + + return ret; +} +EXPORT_SYMBOL_GPL(gx_formatter_event); + +int gx_formatter_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + const struct gx_formatter_driver *drv; + struct gx_formatter *formatter; + void __iomem *regs; + + drv =3D of_device_get_match_data(dev); + if (!drv) { + dev_err(dev, "failed to match device\n"); + return -ENODEV; + } + + formatter =3D devm_kzalloc(dev, sizeof(*formatter), GFP_KERNEL); + if (!formatter) + return -ENOMEM; + platform_set_drvdata(pdev, formatter); + formatter->drv =3D drv; + + regs =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + formatter->map =3D 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); + } + + return devm_snd_soc_register_component(dev, drv->component_drv, + NULL, 0); +} +EXPORT_SYMBOL_GPL(gx_formatter_probe); + +int gx_formatter_create(struct device *dev, + struct snd_soc_dapm_widget *w, + const struct gx_formatter_driver *drv, + struct regmap *regmap) +{ + struct gx_formatter *formatter; + + formatter =3D devm_kzalloc(dev, sizeof(*formatter), GFP_KERNEL); + if (!formatter) + return -ENOMEM; + + formatter->drv =3D drv; + formatter->map =3D regmap; + + w->priv =3D formatter; + + return 0; +} + +int gx_stream_start(struct gx_stream *ts) +{ + struct gx_formatter *formatter; + int ret =3D 0; + + mutex_lock(&ts->lock); + + /* Start all the formatters attached to the stream */ + list_for_each_entry(formatter, &ts->formatter_list, list) { + ret =3D gx_formatter_enable(formatter); + if (ret) { + pr_err("failed to start tdm stream\n"); + goto out; + } + } + + ts->ready =3D true; + +out: + mutex_unlock(&ts->lock); + return ret; +} +EXPORT_SYMBOL_GPL(gx_stream_start); + +void gx_stream_stop(struct gx_stream *ts) +{ + struct gx_formatter *formatter; + + mutex_lock(&ts->lock); + ts->ready =3D false; + + /* Stop all the formatters attached to the stream */ + list_for_each_entry(formatter, &ts->formatter_list, list) { + gx_formatter_disable(formatter); + } + + mutex_unlock(&ts->lock); +} +EXPORT_SYMBOL_GPL(gx_stream_stop); + +struct gx_stream *gx_stream_alloc(struct gx_iface *iface) +{ + struct gx_stream *ts; + + ts =3D kzalloc(sizeof(*ts), GFP_KERNEL); + if (ts) { + INIT_LIST_HEAD(&ts->formatter_list); + mutex_init(&ts->lock); + ts->iface =3D iface; + } + + return ts; +} +EXPORT_SYMBOL_GPL(gx_stream_alloc); + +void gx_stream_free(struct gx_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 + * 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(gx_stream_free); + +MODULE_DESCRIPTION("Amlogic GX formatter driver"); +MODULE_AUTHOR("Valerio Setti "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/meson/gx-formatter.h b/sound/soc/meson/gx-formatter.h new file mode 100644 index 0000000000000000000000000000000000000000..05670c3dfb9f43ac3ee959f1d3d= 11bacee020c43 --- /dev/null +++ b/sound/soc/meson/gx-formatter.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Copyright (c) 2026 Baylibre SAS. + * Author: Valerio Setti + */ + +#ifndef _MESON_GX_FORMATTER_H +#define _MESON_GX_FORMATTER_H + +#include "gx-interface.h" + +struct platform_device; +struct regmap; +struct snd_soc_dapm_widget; +struct snd_kcontrol; + +struct gx_formatter_hw { + unsigned int skew_offset; +}; + +struct gx_formatter_ops { + struct gx_stream *(*get_stream)(struct snd_soc_dapm_widget *w); + void (*enable)(struct regmap *map); + void (*disable)(struct regmap *map); + int (*prepare)(struct regmap *map, + const struct gx_formatter_hw *quirks, + struct gx_stream *ts); +}; + +struct gx_formatter_driver { + const struct snd_soc_component_driver *component_drv; + const struct regmap_config *regmap_cfg; + const struct gx_formatter_ops *ops; + const struct gx_formatter_hw *quirks; +}; + +int gx_formatter_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *control, + int event); +int gx_formatter_probe(struct platform_device *pdev); + +int gx_formatter_create(struct device *dev, + struct snd_soc_dapm_widget *w, + const struct gx_formatter_driver *drv, + struct regmap *regmap); + +#endif /* _MESON_GX_FORMATTER_H */ diff --git a/sound/soc/meson/gx-interface.h b/sound/soc/meson/gx-interface.h new file mode 100644 index 0000000000000000000000000000000000000000..d9ab894589fa039f7fdd7676539= 0630a2c6d8fbf --- /dev/null +++ b/sound/soc/meson/gx-interface.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Copyright (c) 2026 Baylibre SAS. + * Author: Valerio Setti + */ + +#ifndef _MESON_GX_INTERFACE_H +#define _MESON_GX_INTERFACE_H + +#include +#include +#include +#include +#include + +struct gx_iface { + struct clk *mclk; + unsigned long mclk_rate; + + /* format is common to all the DAIs of the iface */ + unsigned int fmt; + + /* For component wide symmetry */ + int rate; +}; + +struct gx_stream { + struct gx_iface *iface; + struct list_head formatter_list; + struct mutex lock; + unsigned int channels; + unsigned int width; + unsigned int physical_width; + bool ready; + + /* For continuous clock tracking */ + bool clk_enabled; +}; + +struct gx_stream *gx_stream_alloc(struct gx_iface *iface); +void gx_stream_free(struct gx_stream *ts); +int gx_stream_start(struct gx_stream *ts); +void gx_stream_stop(struct gx_stream *ts); + +#endif /* _MESON_GX_INTERFACE_H */ --=20 2.39.5 From nobody Mon May 25 08:13:47 2026 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9FA1548AE3E for ; Fri, 15 May 2026 15:11:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778857880; cv=none; b=esTfKFeLECotr+LW4TUlHmnDPA3exzO58hDQqKD564CqyMn9EyaVU6rE3D5YQW1NxHbvke988ZThul49RfYhzSStB6Vt9A+GSwRDyzb4HOCAr09SIJQ0dZ1C6Y8DgYbHTNO5ifkf3JubgblCEU4c/jRs3bdgj1eqH2eu20VOhA8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778857880; c=relaxed/simple; bh=54PIae7SEeel0cOzqQW3XSaYMJnLQDfwZn/z4oQ7lbg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EsOYp5MqxK+SvXMAtTQDyVsAEO33//JzBj4S8VWpmpT+BYQRD4223/p9m/soSLZzk/xysHf6Ud2ULItyUjrV6D0c5Pa9zkI/SMjYU61/j0tyLyckFuKNf0N50JaHqQcptZTqEzNndPItemcggEeyPqus9s/J+klP0z24aEbB1ls= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.b=n9l4ed6C; arc=none smtp.client-ip=209.85.128.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.b="n9l4ed6C" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-48e8132c6d0so47890805e9.1 for ; Fri, 15 May 2026 08:11:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20251104.gappssmtp.com; s=20251104; t=1778857877; x=1779462677; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=0EaEtp+NjgujiEJl+onPEKqRbgJwif9DxxZ8e5Jffn0=; b=n9l4ed6CglS91TiL/MKu7pC0d+dXu35LzNqhXjl9IfsqSPQ1QCYdsu/kr/cLOXY2Pi WJ3FivKTBuiIsnxmVkpYIswisObs1mMK5Q89RKon0aQpYk3VJNDgQ73QgUGrTGEBoto7 /Xj1+64fGeGObaBJcM2ZCZNFJbq6GIqwpO93Pt9Ni5cPUYxmf0pxB5YOFFIPyVb+je8F 1VNNx/ECbgCB4Vco8yE9LxKz7Nqu96em41Ad/JD3VBSWikfLrTXm3utBgTTat3RzJSxu SpWfrqisUFmC0C5X5BaphXWQwwIOQMgGF3Lop66w1Nw2cKcSMfJgu3VMUismer7NcHBU vURw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778857877; x=1779462677; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=0EaEtp+NjgujiEJl+onPEKqRbgJwif9DxxZ8e5Jffn0=; b=dYoTC/wYgLh+bjE2D6o7uNEdW5Zincb8/tKrjfTMqdR8KL2uCPBmCsB9O+BQG+3HR+ oy+TnJ9m+QuINbuERYkmxPIc79dkC3NMnu7NL/KiMxEubiLy6/JmojLJY0eUAKCqaHef diVkukhYRfoVrIAGnRfL450z3zUibodS/+cOvub/J21kKBiT5bq7eX2NNPuBj4sKNnkh uD6vN/R8RuIpRNmHg8eOEAq2aRQs2onDoFSk/a9bD9FOedMhuLv95rYREx47+CNpoEAf b4mezsSxINXzWDtDOuhsj4pwSRRhisYWhTQTksxG3NTqbEC2hunJnwCj3z0e9/efmldM yVPg== X-Gm-Message-State: AOJu0Yx4t4cOa56+v/5BEOUy1kxUCfKKaEAPDPeEmfsQ6SJq+uvz2HLe /zriP0M7Nq6qylTNIzNjx2sg5GHTrQTf+uMpICWZXZftoxJcSivZSVT9iTqBWgaJJKI= X-Gm-Gg: Acq92OF5GEpcQ77wOl5EKcqqCQNC7wZTP/DWcdmuRgmr7Aiy6EukcxJ1SycTJRq6aWv 6PdIsYyvGh29eZ/lXGnFkgA6+5ovPjpBNZ60lt4HJNfpHAIFLDe2D6IsjujkoOebq40mGJi0HyL FcSQIwLbUukyglAB0QMu+7CwiGv++NAmdq0EsdgMvy8Kkr2i0xWO/Iz60rM7lsEl6+H68RMjE3f oEXIVw4+kiA+adi+F2DJmSvvPPQcQ0jY3ENPKwftoPNxqEbYbXBmtAG6JgjafXeRgl+e0OreqMn Ha4/nyv9y85QBi0sgtLgUPE52/0EKhnP43bsMnWocUq0kvh6vZbZA69TEIZNmci1ubzPiNzLGFD dIvl6aWOGeTtTqznzJZouJu2IznRWwH6tDQV17XGBSLsDggkWoQITMIGZ3QZobDap5ggVmlWckH ttfT/haxMZ5grczU+YSmd5 X-Received: by 2002:a05:600c:848c:b0:48a:52d4:888c with SMTP id 5b1f17b1804b1-48fe60e5241mr65301055e9.3.1778857876640; Fri, 15 May 2026 08:11:16 -0700 (PDT) Received: from [127.0.1.1] ([151.41.223.93]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45da0a19c2dsm15262062f8f.21.2026.05.15.08.11.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2026 08:11:16 -0700 (PDT) From: Valerio Setti Date: Fri, 15 May 2026 17:10:38 +0200 Subject: [PATCH 2/4] ASoC: meson: aiu-encoder-i2s: use gx_iface and gx_stream structures Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260515-reshape-aiu-as-axg-v1-2-53b457784ff3@baylibre.com> References: <20260515-reshape-aiu-as-axg-v1-0-53b457784ff3@baylibre.com> In-Reply-To: <20260515-reshape-aiu-as-axg-v1-0-53b457784ff3@baylibre.com> To: Jerome Brunet , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Neil Armstrong , Kevin Hilman , Martin Blumenstingl Cc: linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-amlogic@lists.infradead.org, Valerio Setti X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=12028; i=vsetti@baylibre.com; h=from:subject:message-id; bh=54PIae7SEeel0cOzqQW3XSaYMJnLQDfwZn/z4oQ7lbg=; b=owGbwMvMwCF2z3ty7kUrRgbG02pJDFns5v1F/TXLIne8vloWHF1x7urD1lyx+TL183Y4nUuUn nzcynhNRykLgxgHg6yYIgvL9Hu/C0rVHhonnCyAmcPKBDKEgYtTACbSMZ+RYZWZbg3T1Ilh1Y82 rexo2MgQP/GASdmXWVYf9P9NU30qrs3wT73JVOeMSOnk64vYk84927LvcpTgZFWrh8YTDv395TZ 1CgcA X-Developer-Key: i=vsetti@baylibre.com; a=openpgp; fpr=0497DEFB707526E13360C970DE4B936DD13A0100 Start using gx_iface and gx_stream to store interface and stream info, respectively. probe()/remove() functions are added to allocate/free the gx_stream structures for each PCM stream. Clock-wise instead of bulk enabling all the clocks on startup and disabling them on shutdown, only the peripheral's internal ones are enabled/disabled in those functions, whereas MCLK and I2S clock divider are handled in hw_params/hw_free. Interface wide rate symmetry is also enforced here. This is useful when the interface is used for playback and capture at the same time. Finally a trigger() callback is also added to start/stop the associated I2S data formatter. Signed-off-by: Valerio Setti --- sound/soc/meson/aiu-encoder-i2s.c | 200 ++++++++++++++++++++++++++++++++--= ---- sound/soc/meson/aiu.h | 3 + 2 files changed, 174 insertions(+), 29 deletions(-) diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encode= r-i2s.c index 3b4061508c18047fe8d6f3f98061720f8ce238f2..39accd396affb8beb49fa7cca39= 4244730b24574 100644 --- a/sound/soc/meson/aiu-encoder-i2s.c +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -10,6 +10,8 @@ #include =20 #include "aiu.h" +#include "gx-formatter.h" +#include "gx-interface.h" =20 #define AIU_I2S_SOURCE_DESC_MODE_8CH BIT(0) #define AIU_I2S_SOURCE_DESC_MODE_24BIT BIT(5) @@ -79,7 +81,7 @@ static int aiu_encoder_i2s_setup_desc(struct snd_soc_comp= onent *component, } =20 static int aiu_encoder_i2s_set_legacy_div(struct snd_soc_component *compon= ent, - struct snd_pcm_hw_params *params, + struct gx_stream *ts, unsigned int bs) { switch (bs) { @@ -109,7 +111,7 @@ static int aiu_encoder_i2s_set_legacy_div(struct snd_so= c_component *component, } =20 static int aiu_encoder_i2s_set_more_div(struct snd_soc_component *componen= t, - struct snd_pcm_hw_params *params, + struct gx_stream *ts, unsigned int bs) { /* @@ -119,7 +121,7 @@ static int aiu_encoder_i2s_set_more_div(struct snd_soc_= component *component, * increased by 50% to get the correct output rate. * No idea why ! */ - if (params_width(params) =3D=3D 16 && params_channels(params) =3D=3D 8) { + if (ts->width =3D=3D 16 && ts->channels =3D=3D 8) { if (bs % 2) { dev_err(component->dev, "Cannot increase i2s divider by 50%%\n"); @@ -142,24 +144,18 @@ static int aiu_encoder_i2s_set_more_div(struct snd_so= c_component *component, } =20 static int aiu_encoder_i2s_set_clocks(struct snd_soc_component *component, - struct snd_pcm_hw_params *params) + struct gx_stream *ts) { struct aiu *aiu =3D snd_soc_component_get_drvdata(component); - unsigned int srate =3D params_rate(params); unsigned int fs, bs; int ret; =20 /* Get the oversampling factor */ - fs =3D DIV_ROUND_CLOSEST(clk_get_rate(aiu->i2s.clks[MCLK].clk), srate); + fs =3D DIV_ROUND_CLOSEST(ts->iface->mclk_rate, ts->iface->rate); =20 if (fs % 64) return -EINVAL; =20 - /* Send data MSB first */ - snd_soc_component_update_bits(component, AIU_I2S_DAC_CFG, - AIU_I2S_DAC_CFG_MSB_FIRST, - AIU_I2S_DAC_CFG_MSB_FIRST); - /* Set bclk to lrlck ratio */ snd_soc_component_update_bits(component, AIU_CODEC_DAC_LRCLK_CTRL, AIU_CODEC_DAC_LRCLK_CTRL_DIV, @@ -169,9 +165,9 @@ static int aiu_encoder_i2s_set_clocks(struct snd_soc_co= mponent *component, bs =3D fs / 64; =20 if (aiu->platform->has_clk_ctrl_more_i2s_div) - ret =3D aiu_encoder_i2s_set_more_div(component, params, bs); + ret =3D aiu_encoder_i2s_set_more_div(component, ts, bs); else - ret =3D aiu_encoder_i2s_set_legacy_div(component, params, bs); + ret =3D aiu_encoder_i2s_set_legacy_div(component, ts, bs); =20 if (ret) return ret; @@ -188,25 +184,55 @@ static int aiu_encoder_i2s_hw_params(struct snd_pcm_s= ubstream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + struct gx_stream *ts =3D snd_soc_dai_get_dma_data(dai, substream); + struct gx_iface *iface =3D ts->iface; struct snd_soc_component *component =3D dai->component; int ret; =20 - /* Disable the clock while changing the settings */ - aiu_encoder_i2s_divider_enable(component, false); + /* Enforce interface wide rate symmetry. */ + if (iface->rate && (iface->rate !=3D params_rate(params))) { + dev_err(dai->dev, "can't set iface rate (%d !=3D %d)\n", + iface->rate, params_rate(params)); + return -EINVAL; + } + + iface->rate =3D params_rate(params); + ts->physical_width =3D params_physical_width(params); + ts->width =3D params_width(params); + ts->channels =3D params_channels(params); =20 ret =3D aiu_encoder_i2s_setup_desc(component, params); if (ret) { - dev_err(dai->dev, "setting i2s desc failed\n"); + dev_err(dai->dev, "setting i2s desc failed: %d\n", ret); return ret; } =20 - ret =3D aiu_encoder_i2s_set_clocks(component, params); + ret =3D aiu_encoder_i2s_set_clocks(component, ts); if (ret) { - dev_err(dai->dev, "setting i2s clocks failed\n"); + dev_err(dai->dev, "setting i2s clocks failed: %d\n", ret); return ret; } =20 - aiu_encoder_i2s_divider_enable(component, true); + return 0; +} + +static int aiu_encoder_i2s_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct gx_stream *ts =3D snd_soc_dai_get_dma_data(dai, substream); + struct snd_soc_component *component =3D dai->component; + int ret; + + if (ts->clk_enabled) + return 0; + + ret =3D clk_prepare_enable(ts->iface->mclk); + if (ret) + return ret; + + ts->clk_enabled =3D true; + + aiu_encoder_i2s_divider_enable(component, 1); =20 return 0; } @@ -214,9 +240,20 @@ static int aiu_encoder_i2s_hw_params(struct snd_pcm_su= bstream *substream, static int aiu_encoder_i2s_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + struct gx_stream *ts =3D snd_soc_dai_get_dma_data(dai, substream); struct snd_soc_component *component =3D dai->component; =20 - aiu_encoder_i2s_divider_enable(component, false); + /* + * Disable the i2s clock divider only if this is the last substream + * being closed. + */ + if (snd_soc_dai_active(dai) <=3D 1) + aiu_encoder_i2s_divider_enable(component, 0); + + if (ts->clk_enabled) { + clk_disable_unprepare(ts->iface->mclk); + ts->clk_enabled =3D false; + } =20 return 0; } @@ -224,6 +261,8 @@ static int aiu_encoder_i2s_hw_free(struct snd_pcm_subst= ream *substream, static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int f= mt) { struct snd_soc_component *component =3D dai->component; + struct aiu *aiu =3D snd_soc_component_get_drvdata(component); + struct gx_iface *iface =3D &aiu->i2s.iface; unsigned int inv =3D fmt & SND_SOC_DAIFMT_INV_MASK; unsigned int val =3D 0; unsigned int skew; @@ -255,9 +294,12 @@ static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai = *dai, unsigned int fmt) skew =3D 0; break; default: + dev_err(dai->dev, "unsupported dai format\n"); return -EINVAL; } =20 + iface->fmt =3D fmt; + val |=3D FIELD_PREP(AIU_CLK_CTRL_LRCLK_SKEW, skew); snd_soc_component_update_bits(component, AIU_CLK_CTRL, AIU_CLK_CTRL_LRCLK_INVERT | @@ -281,10 +323,14 @@ static int aiu_encoder_i2s_set_sysclk(struct snd_soc_= dai *dai, int clk_id, return 0; =20 ret =3D clk_set_rate(aiu->i2s.clks[MCLK].clk, freq); - if (ret) - dev_err(dai->dev, "Failed to set sysclk to %uHz", freq); + if (ret) { + dev_err(dai->dev, "Failed to set sysclk to %uHz: %d", freq, ret); + return ret; + } =20 - return ret; + aiu->i2s.iface.mclk_rate =3D freq; + + return 0; } =20 static const unsigned int hw_channels[] =3D {2, 8}; @@ -305,30 +351,126 @@ static int aiu_encoder_i2s_startup(struct snd_pcm_su= bstream *substream, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_channel_constraints); if (ret) { - dev_err(dai->dev, "adding channels constraints failed\n"); + dev_err(dai->dev, "adding channels constraints failed: %d\n", ret); return ret; } =20 - ret =3D clk_bulk_prepare_enable(aiu->i2s.clk_num, aiu->i2s.clks); - if (ret) - dev_err(dai->dev, "failed to enable i2s clocks\n"); + /* + * Enable only clocks which are required for the interface internal + * logic. MCLK is enabled/disabled from the formatter and the I2S + * divider is enabled/disabled in "hw_params"/"hw_free", respectively. + */ + ret =3D clk_prepare_enable(aiu->i2s.clks[PCLK].clk); + if (ret) { + dev_err(dai->dev, "failed to enable PCLK: %d\n", ret); + return ret; + } + ret =3D clk_prepare_enable(aiu->i2s.clks[MIXER].clk); + if (ret) { + dev_err(dai->dev, "failed to enable MIXER: %d\n", ret); + clk_disable_unprepare(aiu->i2s.clks[PCLK].clk); + return ret; + } + ret =3D clk_prepare_enable(aiu->i2s.clks[AOCLK].clk); + if (ret) { + dev_err(dai->dev, "failed to enable AOCLK: %d\n", ret); + clk_disable_unprepare(aiu->i2s.clks[MIXER].clk); + clk_disable_unprepare(aiu->i2s.clks[PCLK].clk); + return ret; + } =20 - return ret; + return 0; } =20 static void aiu_encoder_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct aiu *aiu =3D snd_soc_component_get_drvdata(dai->component); + struct gx_stream *ts =3D snd_soc_dai_get_dma_data(dai, substream); + struct gx_iface *iface =3D ts->iface; + + if (!snd_soc_dai_active(dai)) + iface->rate =3D 0; + + clk_disable_unprepare(aiu->i2s.clks[AOCLK].clk); + clk_disable_unprepare(aiu->i2s.clks[MIXER].clk); + clk_disable_unprepare(aiu->i2s.clks[PCLK].clk); +} =20 - clk_bulk_disable_unprepare(aiu->i2s.clk_num, aiu->i2s.clks); +static int aiu_encoder_i2s_trigger(struct snd_pcm_substream *substream, + int cmd, + struct snd_soc_dai *dai) +{ + struct gx_stream *ts =3D snd_soc_dai_get_dma_data(dai, substream); + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret =3D gx_stream_start(ts); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: + gx_stream_stop(ts); + ret =3D 0; + break; + default: + ret =3D -EINVAL; + } + + return ret; +} + +static int aiu_encoder_i2s_remove_dai(struct snd_soc_dai *dai) +{ + int stream; + + for_each_pcm_streams(stream) { + struct gx_stream *ts =3D snd_soc_dai_dma_data_get(dai, stream); + + if (ts) + gx_stream_free(ts); + } + + return 0; +} + +static int aiu_encoder_i2s_probe_dai(struct snd_soc_dai *dai) +{ + struct aiu *aiu =3D snd_soc_dai_get_drvdata(dai); + struct gx_iface *iface =3D &aiu->i2s.iface; + int stream; + + for_each_pcm_streams(stream) { + struct gx_stream *ts; + + if (!snd_soc_dai_get_widget(dai, stream)) + continue; + + ts =3D gx_stream_alloc(iface); + if (!ts) { + aiu_encoder_i2s_remove_dai(dai); + return -ENOMEM; + } + snd_soc_dai_dma_data_set(dai, stream, ts); + } + + iface->mclk =3D aiu->i2s.clks[MCLK].clk; + + return 0; } =20 const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops =3D { + .probe =3D aiu_encoder_i2s_probe_dai, + .remove =3D aiu_encoder_i2s_remove_dai, .hw_params =3D aiu_encoder_i2s_hw_params, + .prepare =3D aiu_encoder_i2s_prepare, .hw_free =3D aiu_encoder_i2s_hw_free, .set_fmt =3D aiu_encoder_i2s_set_fmt, .set_sysclk =3D aiu_encoder_i2s_set_sysclk, .startup =3D aiu_encoder_i2s_startup, .shutdown =3D aiu_encoder_i2s_shutdown, + .trigger =3D aiu_encoder_i2s_trigger, }; diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h index 0f94c8bf608181112d78402532b832eb50c2d409..68310de0bdf7a97d8de2ff306c1= 59248ee9b0ede 100644 --- a/sound/soc/meson/aiu.h +++ b/sound/soc/meson/aiu.h @@ -7,6 +7,8 @@ #ifndef _MESON_AIU_H #define _MESON_AIU_H =20 +#include "gx-formatter.h" + struct clk; struct clk_bulk_data; struct device; @@ -25,6 +27,7 @@ struct aiu_interface { struct clk_bulk_data *clks; unsigned int clk_num; int irq; + struct gx_iface iface; }; =20 struct aiu_platform_data { --=20 2.39.5 From nobody Mon May 25 08:13:47 2026 Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 799AC48B36F for ; Fri, 15 May 2026 15:11:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778857881; cv=none; b=YHcSQIqF0tLiLeypU6OlAYsz04QZQA2T1XHx1zjbjsqgXE8nppSUBuKpNDdBl5lOWmeFLBmPs3QDqxc9k52+HwlLxUQP55KO+yXo7y7PDrq6xV9WL8G5QmiLWBkQME8oyAjH1WEDupoyVFRnDJ9J7I3QBOG6KYgDytrdvGdhWrU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778857881; c=relaxed/simple; bh=wXLRsbmPRrk2661x1UmBAXkax+7ikv0+c3YhjvlmDR8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CnuMOV8rNVlR5PJQ3Ygohxacq2zEaEwCbHH5m6xhXNbjTzERcjfKAA8tj1MSLHnlc1+LUlX++z6jbdaAYnS1mF+OrhLhqWoDlScvv4NVTNXf4KfatFWj3tRd4TqYhFruoSDvqM17Y2YaBGFBzgOXaLfMeQw9rYnAGMKR40YBYjw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.b=uekvryax; arc=none smtp.client-ip=209.85.221.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.b="uekvryax" Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-44dd5cb0f81so708740f8f.0 for ; Fri, 15 May 2026 08:11:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20251104.gappssmtp.com; s=20251104; t=1778857878; x=1779462678; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=kImEqI0xCMuGmoIKI0CGRRt1bkclZfcyl+UtBK7F4Ss=; b=uekvryaxMsJ15SyGq97ZN+WDgyXMgKTLVPuwSMLJRl//VTFYGqqCv4iZbA7Mh5xryQ IHUHHurveZ3ygvFnseIpLvOe7AEUlnaasPWKMT29BCGzgsb3LDxe8jlkURundnwu+jTW WxuDFK0doC+1zQ/i7JYo577uGIBZ7jb59iYtjAFiSuW5e/qBrbOWLjveu3zRfFZk0x+r hAI2vlSwfh5roKmhB6Y1xvKfdtRG1Ri+bgL99Y0l801ClTTGfJS3xH3sVZU3YYYUc/Xs Zbe5WuKFV7Zotm2fL0+v8mWcPj5XTesMxTpeLMTXm+zSKr2kJL9CAHRXu8/ZGXOFDSH7 FOjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778857878; x=1779462678; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=kImEqI0xCMuGmoIKI0CGRRt1bkclZfcyl+UtBK7F4Ss=; b=fA282iq2Mxb43SF8mgHjhpiZYnUcLKOXT8lqlXu36eUiMeQHRSGJrSm5bNRy3R4lWm 85/f2EsRTgp8HfgdsJhyD4XYEQgeXlKzHpcDAPWhcsij0A3QT4TiLprLtokX1o7pfjLi eydJbMY+M2ZMcJ0lZJtJhuHLNifjI5sG52+k/Ln/SDrD4tri0MAl5BaFCwpgFtmViHjZ afCRkAhg5DZ+cc80KgxZtaWjHAmciqTpj443qQ3Px/z6ZccX02DmsgbmQ1e4FpNK9N9p p4V8NcM3ToHvBUmgfVsNpqToV7I/ufQTDyk9U+oXUVNGLwpW6w6iQJv8UZYmuiu1pych CDVA== X-Gm-Message-State: AOJu0YwNFf1rKoblXxc8Oumnw/rhyvoDLA0d4bCZ0Z8nLqbrPc3pbKja zSW2qnAnY7TZOfNvHI5d+QBdl636k6bkbT7hQKYVHJu2DPEoboB8rzSOHUz2iCSMwgU= X-Gm-Gg: Acq92OGe3Dmab/PNowfhL1rRZftJmghTLxDGlLzY9nT9Y3wrYh96zwd+DaItJfZEvRC HQ6/VgV0dOVtDqE15imrRGFKy0a360fKnrOzYMDSbIeObsDPP29RwbG2ONgqcbk5zSN2SFNuU8z Ovha/O4O1cnTA6XmwZrERauPU6syGaFYMNJS8Obmdl7OZiUa18e1CXzBDnRazt82Y5GBwiNcqyx OqdNFsi0SQQrBz+yh7VTZ+Sf9DhEbbfI6pMH7CxyoPwRQzMkiXKjvY+2bVpBz4qs6o/F9qU+Nj7 99LnuePx8al2DUXnWJjdOAu0rrAZoidvLXW31qTWPEj3W2CscUw/Lzod6ltNS+QkL2hqp2ixoEl 0BBobkwkyQ1gYTdcp7Eqf8kpscURQHaOlbW8Xv7kMAcik5l6gbv3+UIMSvwKLNMgHDzZL2cq21m CQYHHjiFPud2YHA++TZm1VL/9TOQnENi4= X-Received: by 2002:a05:600c:a41a:b0:48e:6be6:168d with SMTP id 5b1f17b1804b1-48fd6333317mr83104435e9.8.1778857877832; Fri, 15 May 2026 08:11:17 -0700 (PDT) Received: from [127.0.1.1] ([151.41.223.93]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45da0a19c2dsm15262062f8f.21.2026.05.15.08.11.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2026 08:11:17 -0700 (PDT) From: Valerio Setti Date: Fri, 15 May 2026 17:10:39 +0200 Subject: [PATCH 3/4] ASoC: meson: aiu: introduce I2S output formatter Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260515-reshape-aiu-as-axg-v1-3-53b457784ff3@baylibre.com> References: <20260515-reshape-aiu-as-axg-v1-0-53b457784ff3@baylibre.com> In-Reply-To: <20260515-reshape-aiu-as-axg-v1-0-53b457784ff3@baylibre.com> To: Jerome Brunet , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Neil Armstrong , Kevin Hilman , Martin Blumenstingl Cc: linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-amlogic@lists.infradead.org, Valerio Setti X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=4421; i=vsetti@baylibre.com; h=from:subject:message-id; bh=wXLRsbmPRrk2661x1UmBAXkax+7ikv0+c3YhjvlmDR8=; b=owGbwMvMwCF2z3ty7kUrRgbG02pJDFns5hPy3xhovfLOb3TVEor+UPEoLmeizsMrXCYtob4e6 vl7llR0lLIwiHEwyIopsrBMv/e7oFTtoXHCyQKYOaxMIEMYuDgFYCKzKxkZ3t/kCix7vmv955Uh 65Rmz1sTe7T+/qO4uLANpgwSbHcOrmBkeB7h+O7ye+nJPlYCvD/vyCTP4xSazmuz6NSPsqYABYX LfAA= X-Developer-Key: i=vsetti@baylibre.com; a=openpgp; fpr=0497DEFB707526E13360C970DE4B936DD13A0100 Introduce aiu-formatter-i2s, a gx_formatter implementation for the AIU I2S playback path. This is going to replace data formatting tasks that are currently being implemented in aiu-encoder-i2s. This should ideally follow the same design pattern used on the AXG platform (see axg-tdmout), but the problem here is that all playback features (including data formatting) so far are implemented in the AIU component. Getting the full AXG design would mean introducing incompatible device-tree changes. Therefore aiu-formatter-i2s is kept very simple and it only implements the bare minimum functionalities to provide I2S playback formatting. It's not a standalone component though because this is still implemented by AIU. Signed-off-by: Valerio Setti --- sound/soc/meson/Makefile | 1 + sound/soc/meson/aiu-formatter-i2s.c | 106 ++++++++++++++++++++++++++++++++= ++++ 2 files changed, 107 insertions(+) diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index 146ec81526ba091a174a113ce3d8412ddbbfd9dd..f9ec0ebb01f048728b8f85fd8e5= 8fb90df990470 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -5,6 +5,7 @@ snd-soc-meson-aiu-y +=3D aiu-acodec-ctrl.o snd-soc-meson-aiu-y +=3D aiu-codec-ctrl.o snd-soc-meson-aiu-y +=3D aiu-encoder-i2s.o snd-soc-meson-aiu-y +=3D gx-formatter.o +snd-soc-meson-aiu-y +=3D aiu-formatter-i2s.o snd-soc-meson-aiu-y +=3D aiu-encoder-spdif.o snd-soc-meson-aiu-y +=3D aiu-fifo.o snd-soc-meson-aiu-y +=3D aiu-fifo-i2s.o diff --git a/sound/soc/meson/aiu-formatter-i2s.c b/sound/soc/meson/aiu-form= atter-i2s.c new file mode 100644 index 0000000000000000000000000000000000000000..c7eff04521de3c282f7f7986414= 3e073ff1b2f27 --- /dev/null +++ b/sound/soc/meson/aiu-formatter-i2s.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2026 BayLibre, SAS. +// Author: Valerio Setti + +#include +#include +#include + +#include "aiu.h" +#include "gx-formatter.h" + +#define AIU_I2S_SOURCE_DESC_MODE_8CH BIT(0) +#define AIU_I2S_SOURCE_DESC_MODE_24BIT BIT(5) +#define AIU_I2S_SOURCE_DESC_MODE_32BIT BIT(9) +#define AIU_I2S_SOURCE_DESC_MODE_SPLIT BIT(11) +#define AIU_RST_SOFT_I2S_FAST BIT(0) + +#define AIU_I2S_DAC_CFG_MSB_FIRST BIT(2) + +static struct snd_soc_dai * +aiu_formatter_i2s_get_be(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_path *p; + struct snd_soc_dai *be; + + snd_soc_dapm_widget_for_each_sink_path(w, p) { + if (!p->connect) + continue; + + if (p->sink->id =3D=3D snd_soc_dapm_dai_in) + return (struct snd_soc_dai *)p->sink->priv; + + be =3D aiu_formatter_i2s_get_be(p->sink); + if (be) + return be; + } + + return NULL; +} + +static struct gx_stream * +aiu_formatter_i2s_get_stream(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dai *be =3D aiu_formatter_i2s_get_be(w); + + if (!be) + return NULL; + + return snd_soc_dai_dma_data_get_playback(be); +} + +static int aiu_formatter_i2s_prepare(struct regmap *map, + const struct gx_formatter_hw *quirks, + struct gx_stream *ts) +{ + /* Always operate in split (classic interleaved) mode */ + unsigned int desc =3D AIU_I2S_SOURCE_DESC_MODE_SPLIT; + unsigned int tmp; + + /* Reset required to update the pipeline */ + regmap_write(map, AIU_RST_SOFT, AIU_RST_SOFT_I2S_FAST); + regmap_read(map, AIU_I2S_SYNC, &tmp); + + switch (ts->physical_width) { + case 16: /* Nothing to do */ + break; + + case 32: + desc |=3D (AIU_I2S_SOURCE_DESC_MODE_24BIT | + AIU_I2S_SOURCE_DESC_MODE_32BIT); + break; + + default: + return -EINVAL; + } + + switch (ts->channels) { + case 2: /* Nothing to do */ + break; + case 8: + desc |=3D AIU_I2S_SOURCE_DESC_MODE_8CH; + break; + default: + return -EINVAL; + } + + regmap_update_bits(map, AIU_I2S_SOURCE_DESC, + AIU_I2S_SOURCE_DESC_MODE_8CH | + AIU_I2S_SOURCE_DESC_MODE_24BIT | + AIU_I2S_SOURCE_DESC_MODE_32BIT | + AIU_I2S_SOURCE_DESC_MODE_SPLIT, + desc); + + /* Send data MSB first */ + regmap_update_bits(map, AIU_I2S_DAC_CFG, + AIU_I2S_DAC_CFG_MSB_FIRST, + AIU_I2S_DAC_CFG_MSB_FIRST); + + return 0; +} + +const struct gx_formatter_ops aiu_formatter_i2s_ops =3D { + .get_stream =3D aiu_formatter_i2s_get_stream, + .prepare =3D aiu_formatter_i2s_prepare, +}; --=20 2.39.5 From nobody Mon May 25 08:13:47 2026 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 614E848C3E6 for ; Fri, 15 May 2026 15:11:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778857888; cv=none; b=W6vg9J5Xdj+OgYR2SB9pe+eTu7O/waRKrK2iNLcQvyupy4yDRIjl2eFN+30/S9lySmOON6YzlVg+6bmH/Hpw+QflKV+SdLcsCZ3DSfBDLox0wdXH6nKU8GlGWafC8ggtNcPeK6UhLDbfFODDwT7MmDXqCf+pnMyheWjUFreAsVU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778857888; c=relaxed/simple; bh=QAXbc3wWqSC9H0GdnYojichQpjbJWMTmLX6rrahyWPc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=coCZsMcKYYUOn+3b7dUZT5SoUgIPyT4pQhxDlmo9LCFd+lLY54UN4iTasUWg1X62u9+xu69YOtHUMG6PhqVEok/N4UXpV+u0eaIV1D8c1GS6xwOepSUHsd4GkqltccO0HzgUWgg0X01h/JqFUChq+RP3xN5EuYS3r/CIAS5oDrs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.b=oQW+A0sK; arc=none smtp.client-ip=209.85.128.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.b="oQW+A0sK" Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-4891c00e7aeso76304055e9.2 for ; Fri, 15 May 2026 08:11:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20251104.gappssmtp.com; s=20251104; t=1778857880; x=1779462680; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=C6mWlulhIjJ+KVaCp0+AQJ0i2SOXLwY0ch+ls2yqanI=; b=oQW+A0sK4SrCM/mh8pHP3toTvCgWgMMfGoZqD2qBH71UkbtimNHmwjk9U2K/VE8wLv hUoMO72gl4y8DUjNVR0zHnsznAWMHJyKU9SvwatSVF4gnqlj+KpodRDE7xjlxniIdSym NGN1jZOA9peLoLM8FfQEl/PwRS7gy/NOqBw9O9P2WRtflIWSD3ghqAZW+AJv80wHvnS0 o4+U+jVByKDCY8TD7GOCmxXHEgP4Ojd9iJ8JO0qwDZiPio/M6QmvccXLrA5y0aYPsY40 VHBugzDfvU9JiQx+qUtaq3F6zadQcioKeYA0X6KGX3apW/w/egzE8tp4CfegblaLjoAt 33zQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778857880; x=1779462680; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=C6mWlulhIjJ+KVaCp0+AQJ0i2SOXLwY0ch+ls2yqanI=; b=LnRjWT8bN55/OmcHHgIA1iba7E0s2Yo88Tlr1T+Uh1vFlvLmqPQ/SuCwpYPFoffQ3P qVRD6jpe0uzapRnZhdLq2BN3EW1SV9sZffIDjECFP7HBKlHOxb07d8eZJ1D3YqO2gPe/ ejQLjsyn7pD2kK1hmG+LKps5p+2v+3tprKvSlpPt3Op895barSfPtR/lrMmG5hEQO+g+ bAVkU+IQIjMUZuuzLfyTjQhwyxTK9cq5xsI+XY5zL1AMav5lTVJhz1IxrGm0Her839E2 NvgNTNG1UINCh2f2GSUGmnxiQ/HstH0ZIje4LjnAzGj4XxxlxCqdv7qidfpIfWFlwSz1 FaEQ== X-Gm-Message-State: AOJu0YydBnqqrIJsQI46WDjiQA1fAGv11GC6aMYCV9zu2duYvJ03v6yT H10SoQQwt6dG+YD4oGnhZgYEwE1tu6oFbCqvZNL76T7sJijnLJMQGmjAKJknbteywZQ= X-Gm-Gg: Acq92OHrWPEzjXNhsCxjKerIZlO1xZ3NbwHwWMA7l6DDtRBoP1WybTBK6dZb2ThpE3e 4DArktW9+ctf522zZQ0Z3d7K2mM+srefU6oLhxM5XrWft79O97nZZETbmQwEtrNeXsdtEzLWM9R WjQu+3f1F6ywPHOoXg96Ep+wyYwpoGUfLa73/MPrHq7HsEc6LhMGe+PEBbRo5d760ZqB788r+Ny SZsGHr94B6byORfp1lwuwDNj+i7Wku9/RgsxEorWw8JwljockxNETGrEJWOhqd5L+ynH6bb06m1 VTv/ZrXtksEWbEIoOHjleKaNkAxZ+6iRozEIoQpGepBqQCE2bwxP+IeJ6sDscVWXAswjx3HEPs0 zgGtWFT9iANR5EllM+kvapzrzD3yTZ5WR37NLBT/5iMf0yhU5YmMkXMUXs2/ZelIX/wHxI0u4GJ nuwaX8ovIJg4SqEWrnPZQYwGmO7CRoNHQ= X-Received: by 2002:a05:600c:6992:b0:48e:6f39:f7be with SMTP id 5b1f17b1804b1-48fe60ea533mr59171235e9.10.1778857879891; Fri, 15 May 2026 08:11:19 -0700 (PDT) Received: from [127.0.1.1] ([151.41.223.93]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45da0a19c2dsm15262062f8f.21.2026.05.15.08.11.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2026 08:11:18 -0700 (PDT) From: Valerio Setti Date: Fri, 15 May 2026 17:10:40 +0200 Subject: [PATCH 4/4] ASoC: meson: aiu: use aiu-formatter-i2s to format I2S output data Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260515-reshape-aiu-as-axg-v1-4-53b457784ff3@baylibre.com> References: <20260515-reshape-aiu-as-axg-v1-0-53b457784ff3@baylibre.com> In-Reply-To: <20260515-reshape-aiu-as-axg-v1-0-53b457784ff3@baylibre.com> To: Jerome Brunet , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Neil Armstrong , Kevin Hilman , Martin Blumenstingl Cc: linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-amlogic@lists.infradead.org, Valerio Setti X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6060; i=vsetti@baylibre.com; h=from:subject:message-id; bh=QAXbc3wWqSC9H0GdnYojichQpjbJWMTmLX6rrahyWPc=; b=owGbwMvMwCF2z3ty7kUrRgbG02pJDFns5hO+L3dLkz56L3furj2Jsw65ZDWbeb8TihIUiDF6n TT3bf2pjlIWBjEOBlkxRRaW6fd+F5SqPTROOFkAM4eVCWQIAxenAExEUpLhr1i2b8Ud/8nHa6Qe pel9PSH3erOa49tdG7a4r3pygP39BhuGv+Lldy7t2Hp9pv5+Ri/mzxrxuq6eOjfv1rK+ETu4+dr KNdwA X-Developer-Key: i=vsetti@baylibre.com; a=openpgp; fpr=0497DEFB707526E13360C970DE4B936DD13A0100 Create a new DAPM widget for "I2S formatter" and place it on the path between FIFO and output DAI interface. Remove I2S output formatting code from aiu-encoder-i2s since it's now implemented from aiu-formatter-i2s. Signed-off-by: Valerio Setti --- sound/soc/meson/aiu-encoder-i2s.c | 56 -----------------------------------= ---- sound/soc/meson/aiu.c | 30 ++++++++++++++++++--- sound/soc/meson/aiu.h | 1 + 3 files changed, 27 insertions(+), 60 deletions(-) diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encode= r-i2s.c index 39accd396affb8beb49fa7cca394244730b24574..9f935a93aeab7a27f880fbde2d2= 9041a4802e3a3 100644 --- a/sound/soc/meson/aiu-encoder-i2s.c +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -13,13 +13,6 @@ #include "gx-formatter.h" #include "gx-interface.h" =20 -#define AIU_I2S_SOURCE_DESC_MODE_8CH BIT(0) -#define AIU_I2S_SOURCE_DESC_MODE_24BIT BIT(5) -#define AIU_I2S_SOURCE_DESC_MODE_32BIT BIT(9) -#define AIU_I2S_SOURCE_DESC_MODE_SPLIT BIT(11) -#define AIU_RST_SOFT_I2S_FAST BIT(0) - -#define AIU_I2S_DAC_CFG_MSB_FIRST BIT(2) #define AIU_CLK_CTRL_I2S_DIV_EN BIT(0) #define AIU_CLK_CTRL_I2S_DIV GENMASK(3, 2) #define AIU_CLK_CTRL_AOCLK_INVERT BIT(6) @@ -37,49 +30,6 @@ static void aiu_encoder_i2s_divider_enable(struct snd_so= c_component *component, enable ? AIU_CLK_CTRL_I2S_DIV_EN : 0); } =20 -static int aiu_encoder_i2s_setup_desc(struct snd_soc_component *component, - struct snd_pcm_hw_params *params) -{ - /* Always operate in split (classic interleaved) mode */ - unsigned int desc =3D AIU_I2S_SOURCE_DESC_MODE_SPLIT; - - /* Reset required to update the pipeline */ - snd_soc_component_write(component, AIU_RST_SOFT, AIU_RST_SOFT_I2S_FAST); - snd_soc_component_read(component, AIU_I2S_SYNC); - - switch (params_physical_width(params)) { - case 16: /* Nothing to do */ - break; - - case 32: - desc |=3D (AIU_I2S_SOURCE_DESC_MODE_24BIT | - AIU_I2S_SOURCE_DESC_MODE_32BIT); - break; - - default: - return -EINVAL; - } - - switch (params_channels(params)) { - case 2: /* Nothing to do */ - break; - case 8: - desc |=3D AIU_I2S_SOURCE_DESC_MODE_8CH; - break; - default: - return -EINVAL; - } - - snd_soc_component_update_bits(component, AIU_I2S_SOURCE_DESC, - AIU_I2S_SOURCE_DESC_MODE_8CH | - AIU_I2S_SOURCE_DESC_MODE_24BIT | - AIU_I2S_SOURCE_DESC_MODE_32BIT | - AIU_I2S_SOURCE_DESC_MODE_SPLIT, - desc); - - return 0; -} - static int aiu_encoder_i2s_set_legacy_div(struct snd_soc_component *compon= ent, struct gx_stream *ts, unsigned int bs) @@ -201,12 +151,6 @@ static int aiu_encoder_i2s_hw_params(struct snd_pcm_su= bstream *substream, ts->width =3D params_width(params); ts->channels =3D params_channels(params); =20 - ret =3D aiu_encoder_i2s_setup_desc(component, params); - if (ret) { - dev_err(dai->dev, "setting i2s desc failed: %d\n", ret); - return ret; - } - ret =3D aiu_encoder_i2s_set_clocks(component, ts); if (ret) { dev_err(dai->dev, "setting i2s clocks failed: %d\n", ret); diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index f2890111c1d2cfa2213bf01849957a796744b9ae..b09c2058eacaf2998d0d3cd6682= 910f94ec89912 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -29,13 +29,22 @@ static SOC_ENUM_SINGLE_DECL(aiu_spdif_encode_sel_enum, = AIU_I2S_MISC, static const struct snd_kcontrol_new aiu_spdif_encode_mux =3D SOC_DAPM_ENUM("SPDIF Buffer Src", aiu_spdif_encode_sel_enum); =20 -static const struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] =3D { - SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0, - &aiu_spdif_encode_mux), +#define AIU_WIDGET_SPDIF_SRC_SEL 0 +#define AIU_WIDGET_I2S_FORMATTER 1 + +static struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] =3D { + [AIU_WIDGET_SPDIF_SRC_SEL] =3D + SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0, + &aiu_spdif_encode_mux), + [AIU_WIDGET_I2S_FORMATTER] =3D + SND_SOC_DAPM_PGA_E("I2S Formatter", SND_SOC_NOPM, 0, 0, NULL, 0, + gx_formatter_event, + (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD)), }; =20 static const struct snd_soc_dapm_route aiu_cpu_dapm_routes[] =3D { - { "I2S Encoder Playback", NULL, "I2S FIFO Playback" }, + { "I2S Formatter", NULL, "I2S FIFO Playback" }, + { "I2S Encoder Playback", NULL, "I2S Formatter" }, { "SPDIF SRC SEL", "SPDIF", "SPDIF FIFO Playback" }, { "SPDIF SRC SEL", "I2S", "I2S FIFO Playback" }, { "SPDIF Encoder Playback", NULL, "SPDIF SRC SEL" }, @@ -172,6 +181,11 @@ static const struct regmap_config aiu_regmap_cfg =3D { .max_register =3D 0x2ac, }; =20 +const struct gx_formatter_driver aiu_formatter_i2s_drv =3D { + .regmap_cfg =3D &aiu_regmap_cfg, + .ops =3D &aiu_formatter_i2s_ops, +}; + static int aiu_clk_bulk_get(struct device *dev, const char * const *ids, unsigned int num, @@ -291,6 +305,14 @@ static int aiu_probe(struct platform_device *pdev) return ret; } =20 + /* Allocate the aiu-formatter into its widget */ + ret =3D gx_formatter_create(dev, &aiu_cpu_dapm_widgets[AIU_WIDGET_I2S_FOR= MATTER], + &aiu_formatter_i2s_drv, map); + if (ret) { + dev_err(dev, "Failed to allocate aiu formatter\n"); + goto err; + } + /* Register the hdmi codec control component */ ret =3D aiu_hdmi_ctrl_register_component(dev); if (ret) { diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h index 68310de0bdf7a97d8de2ff306c159248ee9b0ede..7d0b98c1f351b3c526ca06c43a4= c04ee5f4b6dfa 100644 --- a/sound/soc/meson/aiu.h +++ b/sound/soc/meson/aiu.h @@ -61,6 +61,7 @@ extern const struct snd_soc_dai_ops aiu_fifo_i2s_dai_ops; extern const struct snd_soc_dai_ops aiu_fifo_spdif_dai_ops; extern const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops; extern const struct snd_soc_dai_ops aiu_encoder_spdif_dai_ops; +extern const struct gx_formatter_ops aiu_formatter_i2s_ops; =20 #define AIU_IEC958_BPF 0x000 #define AIU_958_MISC 0x010 --=20 2.39.5