[PATCH v2 0/8] Add RZ/G2L Sound support
This patch series aims to add ASoC support on RZ/G2L SoC's.
It is based on the work done by Chris Brandt for RZ/A ASoC driver.
Biju Das (8): ASoC: dt-bindings: Document RZ/G2L bindings sound: soc: sh: Add RZ/G2L SSIF-2 driver arm64: dts: renesas: r9a07g044: Add external audio clock nodes arm64: dts: renesas: r9a07g044: Add SSI support arm64: defconfig: Enable ASoC sound support for RZ/G2L SoC ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support sound: sh: rz-ssi: Add SSI DMAC support arm64: dts: renesas: r9a07g044: Add SSI DMA support
.../bindings/sound/renesas,rz-ssi.yaml | 100 ++ arch/arm64/boot/dts/renesas/r9a07g044.dtsi | 105 ++ arch/arm64/configs/defconfig | 1 + sound/soc/sh/Kconfig | 10 + sound/soc/sh/Makefile | 4 + sound/soc/sh/rz-ssi.c | 1078 +++++++++++++++++ 6 files changed, 1298 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml create mode 100644 sound/soc/sh/rz-ssi.c
Document RZ/G2L ASoC serial sound interface bindings.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- v1->v2: * Rebased to latest mainline rc branch. --- .../bindings/sound/renesas,rz-ssi.yaml | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml new file mode 100644 index 000000000000..891f381ee5b8 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/renesas,rz-ssi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RZ/G2L ASoC Sound Serial Interface (SSIF-2) + +maintainers: + - Biju Das biju.das.jz@bp.renesas.com + +properties: + compatible: + items: + - enum: + - renesas,r9a07g044-ssi # RZ/G2{L,LC} + - const: renesas,rz-ssi + + reg: + maxItems: 1 + + interrupts: + maxItems: 4 + + interrupt-names: + items: + - const: int_req + - const: dma_rx + - const: dma_tx + - const: dma_rt + + clocks: + maxItems: 4 + + clock-names: + items: + - const: ssi + - const: ssi_sfr + - const: audio_clk1 + - const: audio_clk2 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + - interrupts + - interrupt-names + - clocks + - clock-names + - resets + - '#sound-dai-cells' + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/clock/r9a07g044-cpg.h> + + ssi0: ssi@10049c00 { + compatible = "renesas,r9a07g044-ssi", + "renesas,rz-ssi"; + reg = <0x10049c00 0x400>; + interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt"; + clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>, + <&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>, + <&audio_clk1>, + <&audio_clk2>; + clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_SSI0_RST_M2_REG>; + #sound-dai-cells = <0>; + };
On Mon, 19 Jul 2021 14:40:33 +0100, Biju Das wrote:
Document RZ/G2L ASoC serial sound interface bindings.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
v1->v2:
- Rebased to latest mainline rc branch.
.../bindings/sound/renesas,rz-ssi.yaml | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check' on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
dtschema/dtc warnings/errors: Error: Documentation/devicetree/bindings/sound/renesas,rz-ssi.example.dts:31.34-35 syntax error FATAL ERROR: Unable to parse input tree make[1]: *** [scripts/Makefile.lib:380: Documentation/devicetree/bindings/sound/renesas,rz-ssi.example.dt.yaml] Error 1 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:1418: dt_binding_check] Error 2 \ndoc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/patch/1507078
This check can fail if there are any dependencies. The base for a patch series is generally the most recent rc1.
If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date:
pip3 install dtschema --upgrade
Please check and re-submit.
Hi Rob,
The dependency patch for the below bot error is present on 5.14-rc2 but not on 5.14-rc1.
Regards, Biju
-----Original Message----- From: Rob Herring robh@kernel.org Sent: 19 July 2021 23:16 To: Biju Das biju.das.jz@bp.renesas.com Cc: Liam Girdwood lgirdwood@gmail.com; Mark Brown broonie@kernel.org; devicetree@vger.kernel.org; Biju Das biju.das@bp.renesas.com; Prabhakar Mahadev Lad prabhakar.mahadev-lad.rj@bp.renesas.com; Chris Paterson Chris.Paterson2@renesas.com; Kuninori Morimoto kuninori.morimoto.gx@renesas.com; Chris Brandt Chris.Brandt@renesas.com; alsa-devel@alsa-project.org; linux-renesas- soc@vger.kernel.org; Geert Uytterhoeven geert+renesas@glider.be; Rob Herring robh+dt@kernel.org Subject: Re: [PATCH v2 1/8] ASoC: dt-bindings: Document RZ/G2L bindings
On Mon, 19 Jul 2021 14:40:33 +0100, Biju Das wrote:
Document RZ/G2L ASoC serial sound interface bindings.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
v1->v2:
- Rebased to latest mainline rc branch.
.../bindings/sound/renesas,rz-ssi.yaml | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check' on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
dtschema/dtc warnings/errors: Error: Documentation/devicetree/bindings/sound/renesas,rz- ssi.example.dts:31.34-35 syntax error FATAL ERROR: Unable to parse input tree make[1]: *** [scripts/Makefile.lib:380: Documentation/devicetree/bindings/sound/renesas,rz-ssi.example.dt.yaml] Error 1 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:1418: dt_binding_check] Error 2 \ndoc reference errors (make refcheckdocs):
See https://jpn01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwor k.ozlabs.org%2Fpatch%2F1507078&data=04%7C01%7Cbiju.das.jz%40bp.renesas .com%7C6f79c990c61146a9789c08d94b02da61%7C53d82571da1947e49cb4625a166a4a2a %7C0%7C0%7C637623297898953993%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAi LCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=cWgOhVRwpt e4WzvogZDDv1jq%2FfD3GZyJ4XuBafYI3R8%3D&reserved=0
This check can fail if there are any dependencies. The base for a patch series is generally the most recent rc1.
If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date:
pip3 install dtschema --upgrade
Please check and re-submit.
On Mon, Jul 19, 2021 at 02:40:33PM +0100, Biju Das wrote:
Document RZ/G2L ASoC serial sound interface bindings.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
v1->v2:
- Rebased to latest mainline rc branch.
.../bindings/sound/renesas,rz-ssi.yaml | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
Reviewed-by: Rob Herring robh@kernel.org
Add serial sound interface(SSIF-2) driver support for RZ/G2L SoC.
Based on the work done by Chris Brandt for RZ/A SSI driver.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- v1->v2: * No change --- sound/soc/sh/Kconfig | 10 + sound/soc/sh/Makefile | 4 + sound/soc/sh/rz-ssi.c | 875 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 889 insertions(+) create mode 100644 sound/soc/sh/rz-ssi.c
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 346c806ba390..8aa17f2f7c03 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -45,6 +45,16 @@ config SND_SOC_RCAR help This option enables R-Car SRU/SCU/SSIU/SSI sound support
+config SND_SOC_RZ + tristate "RZ/G2L series SSIF-2 support" + depends on OF || COMPILE_TEST + depends on ARCH_R9A07G044 + select SND_SIMPLE_CARD + help + This option enables ASoC sound support for the RZ/G2L MPUs. + The simple-audio-card driver and the RZ/G2L built-in serial + sound interface (SSIF-2) driver are used. + ## ## Boards ## diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile index 51bd7c81671c..f6fd79948f6a 100644 --- a/sound/soc/sh/Makefile +++ b/sound/soc/sh/Makefile @@ -22,3 +22,7 @@ snd-soc-migor-objs := migor.o
obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o + +# RZ/G2L +snd-soc-rz-ssi-objs := rz-ssi.o +obj-$(CONFIG_SND_SOC_RZ) += snd-soc-rz-ssi.o diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c new file mode 100644 index 000000000000..51adddc406e7 --- /dev/null +++ b/sound/soc/sh/rz-ssi.c @@ -0,0 +1,875 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas RZ/G2L Serial Sound Interface (SSIF-2) Driver + * + * Copyright (C) 2021 Renesas Electronics Corp. + * Copyright (C) 2019 Chris Brandt. + */ + +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> +#include <sound/soc.h> + +/* REGISTER OFFSET */ +#define SSICR 0x000 +#define SSISR 0x004 +#define SSIFCR 0x010 +#define SSIFSR 0x014 +#define SSIFTDR 0x018 +#define SSIFRDR 0x01c +#define SSIOFR 0x020 +#define SSISCR 0x024 + +/* SSI REGISTER BITS */ +#define SSICR_DWL(x) (((x) & 0x7) << 19) +#define SSICR_SWL(x) (((x) & 0x7) << 16) +#define SSICR_MST BIT(14) +#define SSICR_CKDV(x) (((x) & 0xf) << 4) + +#define SSICR_CKS BIT(30) +#define SSICR_TUIEN BIT(29) +#define SSICR_TOIEN BIT(28) +#define SSICR_RUIEN BIT(27) +#define SSICR_ROIEN BIT(26) +#define SSICR_MST BIT(14) +#define SSICR_BCKP BIT(13) +#define SSICR_LRCKP BIT(12) +#define SSICR_CKDV(x) (((x) & 0xf) << 4) +#define SSICR_TEN BIT(1) +#define SSICR_REN BIT(0) + +#define SSISR_TUIRQ BIT(29) +#define SSISR_TOIRQ BIT(28) +#define SSISR_RUIRQ BIT(27) +#define SSISR_ROIRQ BIT(26) +#define SSISR_IIRQ BIT(25) + +#define SSIFCR_AUCKE BIT(31) +#define SSIFCR_SSIRST BIT(16) +#define SSIFCR_TIE BIT(3) +#define SSIFCR_RIE BIT(2) +#define SSIFCR_TFRST BIT(1) +#define SSIFCR_RFRST BIT(0) + +#define SSIFSR_TDC_MASK 0x3f +#define SSIFSR_TDC_SHIFT 24 +#define SSIFSR_RDC_MASK 0x3f +#define SSIFSR_RDC_SHIFT 8 + +#define SSIFSR_TDC(x) (((x) & 0x1f) << 24) +#define SSIFSR_TDE BIT(16) +#define SSIFSR_RDC(x) (((x) & 0x1f) << 8) +#define SSIFSR_RDF BIT(0) + +#define SSIOFR_LRCONT BIT(8) + +#define SSISCR_TDES(x) (((x) & 0x1f) << 8) +#define SSISCR_RDFS(x) (((x) & 0x1f) << 0) + +/* Pre allocated buffers sizes */ +#define PREALLOC_BUFFER (SZ_32K) +#define PREALLOC_BUFFER_MAX (SZ_32K) + +#define SSI_RATES SNDRV_PCM_RATE_8000_48000 /* 8k-44.1kHz */ +#define SSI_FMTS SNDRV_PCM_FMTBIT_S16_LE +#define SSI_CHAN_MIN 2 +#define SSI_CHAN_MAX 2 +#define SSI_FIFO_DEPTH 32 + +struct rz_ssi_priv; + +struct rz_ssi_stream { + struct rz_ssi_priv *priv; + struct snd_pcm_substream *substream; + int fifo_sample_size; /* sample capacity of SSI FIFO */ + int period_counter; /* for keeping track of periods transferred */ + int sample_width; + int buffer_pos; /* current frame position in the buffer */ + int running; /* 0=stopped, 1=running */ + + int uerr_num; + int oerr_num; + + int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm); +}; + +struct rz_ssi_priv { + void __iomem *base; + struct platform_device *pdev; + struct reset_control *rstc; + struct device *dev; + struct clk *sfr_clk; + struct clk *clk; + + int irq_int; + int irq_tx; + int irq_rx; + + spinlock_t lock; + + /* + * The SSI supports full-duplex transmission and reception. + * However, if an error occurs, channel reset (both transmission + * and reception reset) is required. + * So it is better to use as half-duplex (playing and recording + * should be done on separate channels). + */ + struct rz_ssi_stream playback; + struct rz_ssi_stream capture; + + /* clock */ + unsigned long audio_mck; + unsigned long audio_clk_1; + unsigned long audio_clk_2; + + bool lrckp_fsync_fall; /* LR clock polarity (SSICR.LRCKP) */ + bool bckp_rise; /* Bit clock polarity (SSICR.BCKP) */ +}; + +static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data) +{ + writel(data, (priv->base + reg)); +} + +static u32 rz_ssi_reg_readl(struct rz_ssi_priv *priv, uint reg) +{ + return readl(priv->base + reg); +} + +static void rz_ssi_reg_mask_setl(struct rz_ssi_priv __iomem *priv, uint reg, + u32 bclr, u32 bset) +{ + u32 val; + + val = readl(priv->base + reg); + val = (val & ~bclr) | bset; + writel(val, (priv->base + reg)); +} + +static inline struct snd_soc_dai * +rz_ssi_get_dai(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + + return asoc_rtd_to_cpu(rtd, 0); +} + +static inline bool rz_ssi_stream_is_play(struct rz_ssi_priv *ssi, + struct rz_ssi_stream *strm) +{ + return strm->substream->stream == SNDRV_PCM_STREAM_PLAYBACK; +} + +static inline struct rz_ssi_stream * +rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream) +{ + struct rz_ssi_stream *stream = &ssi->playback; + + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) + stream = &ssi->capture; + + return stream; +} + +static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi, + struct rz_ssi_stream *strm) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&ssi->lock, flags); + ret = !!(strm->substream && strm->substream->runtime); + spin_unlock_irqrestore(&ssi->lock, flags); + + return ret; +} + +static int rz_ssi_stream_init(struct rz_ssi_priv *ssi, + struct rz_ssi_stream *strm, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + strm->substream = substream; + + strm->sample_width = samples_to_bytes(runtime, 1); + strm->period_counter = 0; + strm->buffer_pos = 0; + + strm->oerr_num = 0; + strm->uerr_num = 0; + strm->running = 0; + + /* fifo init */ + strm->fifo_sample_size = SSI_FIFO_DEPTH; + + if (runtime->sample_bits != 16) { + dev_err(ssi->dev, "Unsupported sample width: %d\n", + runtime->sample_bits); + strm->substream = NULL; + return -EINVAL; + } + + if (runtime->frame_bits != 32) { + dev_err(ssi->dev, "Unsupported frame width: %d\n", + runtime->sample_bits); + strm->substream = NULL; + return -EINVAL; + } + + if (runtime->channels != 2) { + dev_err(ssi->dev, "Number of channels not matched\n"); + strm->substream = NULL; + return -EINVAL; + } + + return 0; +} + +static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi, + struct rz_ssi_stream *strm) +{ + struct snd_soc_dai *dai = rz_ssi_get_dai(strm->substream); + unsigned long flags; + + if (strm->oerr_num > 0) + dev_info(dai->dev, "overrun = %d\n", strm->oerr_num); + + if (strm->uerr_num > 0) + dev_info(dai->dev, "underrun = %d\n", strm->uerr_num); + + spin_lock_irqsave(&ssi->lock, flags); + strm->substream = NULL; + spin_unlock_irqrestore(&ssi->lock, flags); +} + +static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate, + unsigned int channels) +{ + static s8 ckdv[16] = { 1, 2, 4, 8, 16, 32, 64, 128, + 6, 12, 24, 48, 96, -1, -1, -1 }; + unsigned int channel_bits = 32; /* System Word Length */ + unsigned long bclk_rate = rate * channels * channel_bits; + unsigned int div; + u32 ssicr = 0; + u32 clk_ckdv; + int i; + + /* Clear AUCKE so we can set MST */ + rz_ssi_reg_writel(ssi, SSIFCR, 0); + + /* Continue to output LRCK pin even when idle */ + rz_ssi_reg_writel(ssi, SSIOFR, SSIOFR_LRCONT); + if (ssi->audio_clk_1 && ssi->audio_clk_2) { + if (ssi->audio_clk_1 % bclk_rate) + ssi->audio_mck = ssi->audio_clk_2; + else + ssi->audio_mck = ssi->audio_clk_1; + } + + /* Clock setting */ + ssicr |= SSICR_MST; + if (ssi->audio_mck == ssi->audio_clk_1) + ssicr |= SSICR_CKS; + if (ssi->bckp_rise) + ssicr |= SSICR_BCKP; + if (ssi->lrckp_fsync_fall) + ssicr |= SSICR_LRCKP; + + /* Determine the clock divider */ + clk_ckdv = 0; + div = ssi->audio_mck / bclk_rate; + /* try to find an match */ + for (i = 0; i < ARRAY_SIZE(ckdv); i++) { + if (ckdv[i] == div) { + clk_ckdv = i; + break; + } + } + + if (i == ARRAY_SIZE(ckdv)) { + dev_err(ssi->dev, "Rate not divisible by audio clock source\n"); + return -EINVAL; + } + + /* + * DWL: Data Word Length = 16 bits + * SWL: System Word Length = 32 bits + */ + ssicr |= SSICR_CKDV(clk_ckdv); + ssicr |= SSICR_DWL(1) | SSICR_SWL(3); + rz_ssi_reg_writel(ssi, SSICR, ssicr); + rz_ssi_reg_writel(ssi, SSIFCR, + (SSIFCR_AUCKE | SSIFCR_TFRST | SSIFCR_RFRST)); + + return 0; +} + +static int rz_ssi_start_stop(struct rz_ssi_priv *ssi, + struct rz_ssi_stream *strm, + int start) +{ + u32 ssicr, ssifcr; + int timeout; + + if (start) { + ssicr = rz_ssi_reg_readl(ssi, SSICR); + ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF; + + /* FIFO interrupt thresholds */ + rz_ssi_reg_writel(ssi, SSISCR, + SSISCR_TDES(strm->fifo_sample_size / 2 - 1) | + SSISCR_RDFS(0)); + + /* enable IRQ */ + if (rz_ssi_stream_is_play(ssi, strm)) { + ssicr |= SSICR_TUIEN | SSICR_TOIEN; + ssifcr |= SSIFCR_TIE | SSIFCR_RFRST; + } else { + ssicr |= SSICR_RUIEN | SSICR_ROIEN; + ssifcr |= SSIFCR_RIE | SSIFCR_TFRST; + } + + rz_ssi_reg_writel(ssi, SSICR, ssicr); + rz_ssi_reg_writel(ssi, SSIFCR, ssifcr); + + /* Clear all error flags */ + rz_ssi_reg_mask_setl(ssi, SSISR, + (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ | + SSISR_RUIRQ), 0); + + strm->running = 1; + ssicr |= rz_ssi_stream_is_play(ssi, strm) ? SSICR_TEN : SSICR_REN; + rz_ssi_reg_writel(ssi, SSICR, ssicr); + + } else { + strm->running = 0; + + /* Disable irqs */ + rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN | + SSICR_RUIEN | SSICR_ROIEN, 0); + rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_TIE | SSIFCR_RIE, 0); + + /* Clear all error flags */ + rz_ssi_reg_mask_setl(ssi, SSISR, + (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ | + SSISR_RUIRQ), 0); + + /* Wait for idle */ + timeout = 100; + while (--timeout) { + if (rz_ssi_reg_readl(ssi, SSISR) | SSISR_IIRQ) + break; + udelay(1); + } + + if (!timeout) + dev_info(ssi->dev, "timeout waiting for SSI idle\n"); + + /* Disable TX/RX */ + rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0); + + /* Hold FIFOs in reset */ + rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, + SSIFCR_TFRST | SSIFCR_RFRST); + } + + return 0; +} + +static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int frames) +{ + struct snd_pcm_runtime *runtime = strm->substream->runtime; + int current_period; + + strm->buffer_pos += frames; + WARN_ON(strm->buffer_pos > runtime->buffer_size); + + /* ring buffer */ + if (strm->buffer_pos == runtime->buffer_size) + strm->buffer_pos = 0; + + current_period = strm->buffer_pos / runtime->period_size; + if (strm->period_counter != current_period) { + snd_pcm_period_elapsed(strm->substream); + strm->period_counter = current_period; + } +} + +static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) +{ + struct snd_pcm_substream *substream = strm->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + u16 *buf; + int fifo_samples; + int frames_left; + int samples = 0; + int i; + + if (!rz_ssi_stream_is_valid(ssi, strm)) + return -EINVAL; + + /* frames left in this period */ + frames_left = runtime->period_size - (strm->buffer_pos % + runtime->period_size); + if (frames_left == 0) + frames_left = runtime->period_size; + + /* Samples in RX FIFO */ + fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >> + SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK; + + /* Only read full frames at a time */ + while (frames_left && (fifo_samples >= runtime->channels)) { + samples += runtime->channels; + fifo_samples -= runtime->channels; + frames_left--; + } + + /* not enough samples yet */ + if (samples == 0) + return 0; + + /* calculate new buffer index */ + buf = (u16 *)(strm->substream->runtime->dma_area); + buf += strm->buffer_pos * runtime->channels; + + /* Note, only supports 16-bit samples */ + for (i = 0; i < samples; i++) + *buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16); + + rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); + rz_ssi_pointer_update(strm, samples / runtime->channels); + + /* + * If we finished this period, but there are more samples in + * the RX FIFO, call this function again + */ + if (frames_left == 0 && fifo_samples >= runtime->channels) + rz_ssi_pio_recv(ssi, strm); + + return 0; +} + +static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) +{ + struct snd_pcm_substream *substream = strm->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + int sample_space; + int samples = 0; + int frames_left; + int i; + u32 ssifsr; + u16 *buf; + + if (!rz_ssi_stream_is_valid(ssi, strm)) + return -EINVAL; + + /* frames left in this period */ + frames_left = runtime->period_size - (strm->buffer_pos % + runtime->period_size); + if (frames_left == 0) + frames_left = runtime->period_size; + + sample_space = strm->fifo_sample_size; + ssifsr = rz_ssi_reg_readl(ssi, SSIFSR); + sample_space -= (ssifsr >> SSIFSR_TDC_SHIFT) & SSIFSR_TDC_MASK; + + /* Only add full frames at a time */ + while (frames_left && (sample_space >= runtime->channels)) { + samples += runtime->channels; + sample_space -= runtime->channels; + frames_left--; + } + + /* no space to send anything right now */ + if (samples == 0) + return 0; + + /* calculate new buffer index */ + buf = (u16 *)(strm->substream->runtime->dma_area); + buf += strm->buffer_pos * runtime->channels; + + /* Note, only supports 16-bit samples */ + for (i = 0; i < samples; i++) + rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16)); + + rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_TDE, 0); + rz_ssi_pointer_update(strm, samples / runtime->channels); + + return 0; +} + +static irqreturn_t rz_ssi_interrupt(int irq, void *data) +{ + struct rz_ssi_stream *strm = NULL; + struct rz_ssi_priv *ssi = data; + u32 ssisr = rz_ssi_reg_readl(ssi, SSISR); + + if (ssi->playback.substream) + strm = &ssi->playback; + else if (ssi->capture.substream) + strm = &ssi->capture; + else + return IRQ_HANDLED; /* Left over TX/RX interrupt */ + + if (irq == ssi->irq_int) { /* error or idle */ + if (ssisr & SSISR_TUIRQ) + strm->uerr_num++; + if (ssisr & SSISR_TOIRQ) + strm->oerr_num++; + if (ssisr & SSISR_RUIRQ) + strm->uerr_num++; + if (ssisr & SSISR_ROIRQ) + strm->oerr_num++; + + if (ssisr & (SSISR_TUIRQ | SSISR_TOIRQ | SSISR_RUIRQ | + SSISR_ROIRQ)) { + /* Error handling */ + /* You must reset (stop/restart) after each interrupt */ + rz_ssi_start_stop(ssi, strm, 0); + + /* Clear all flags */ + rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ | + SSISR_TUIRQ | SSISR_ROIRQ | + SSISR_RUIRQ, 0); + + /* Add/remove more data */ + strm->transfer(ssi, strm); + + /* Resume */ + rz_ssi_start_stop(ssi, strm, 1); + } + } + + if (!strm->running) + return IRQ_HANDLED; + + /* tx data empty */ + if (irq == ssi->irq_tx) + strm->transfer(ssi, &ssi->playback); + + /* rx data full */ + if (irq == ssi->irq_rx) { + strm->transfer(ssi, &ssi->capture); + rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); + } + + return IRQ_HANDLED; +} + +static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); + struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream); + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + /* Soft Reset */ + rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST); + rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0); + udelay(5); + + ret = rz_ssi_stream_init(ssi, strm, substream); + if (ret) + goto done; + + ret = strm->transfer(ssi, strm); + if (ret) + goto done; + + ret = rz_ssi_start_stop(ssi, strm, 1); + break; + case SNDRV_PCM_TRIGGER_STOP: + rz_ssi_start_stop(ssi, strm, 0); + rz_ssi_stream_quit(ssi, strm); + break; + } + +done: + return ret; +} + +static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + asm("nop"); /* codec is slave */ + break; + default: + dev_err(ssi->dev, "Only master mode is supported.\n"); + return -EINVAL; + } + + /* + * set clock polarity + * + * "normal" BCLK = Signal is available at rising edge of BCLK + * "normal" FSYNC = (I2S) Left ch starts with falling FSYNC edge + */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + ssi->bckp_rise = false; + ssi->lrckp_fsync_fall = false; + break; + case SND_SOC_DAIFMT_NB_IF: + ssi->bckp_rise = false; + ssi->lrckp_fsync_fall = true; + break; + case SND_SOC_DAIFMT_IB_NF: + ssi->bckp_rise = true; + ssi->lrckp_fsync_fall = false; + break; + case SND_SOC_DAIFMT_IB_IF: + ssi->bckp_rise = true; + ssi->lrckp_fsync_fall = true; + break; + default: + return -EINVAL; + } + + /* only i2s support */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + default: + dev_err(ssi->dev, "Only I2S mode is supported.\n"); + return -EINVAL; + } + + return 0; +} + +static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); + + return rz_ssi_clk_setup(ssi, params_rate(params), + params_channels(params)); +} + +static const struct snd_soc_dai_ops rz_ssi_dai_ops = { + .trigger = rz_ssi_dai_trigger, + .set_fmt = rz_ssi_dai_set_fmt, + .hw_params = rz_ssi_dai_hw_params, +}; + +static const struct snd_pcm_hardware rz_ssi_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID, + .buffer_bytes_max = PREALLOC_BUFFER, + .period_bytes_min = 32, + .period_bytes_max = 8192, + .channels_min = SSI_CHAN_MIN, + .channels_max = SSI_CHAN_MAX, + .periods_min = 1, + .periods_max = 32, + .fifo_size = 32 * 2, +}; + +static int rz_ssi_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + snd_soc_set_runtime_hwparams(substream, &rz_ssi_pcm_hardware); + + return snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); +} + +static snd_pcm_uframes_t rz_ssi_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_dai *dai = rz_ssi_get_dai(substream); + struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); + struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream); + + return strm->buffer_pos; +} + +static int rz_ssi_pcm_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + rtd->card->snd_card->dev, + PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); + return 0; +} + +static struct snd_soc_dai_driver rz_ssi_soc_dai[] = { + { + .name = "rz-ssi-dai", + .playback = { + .rates = SSI_RATES, + .formats = SSI_FMTS, + .channels_min = SSI_CHAN_MIN, + .channels_max = SSI_CHAN_MAX, + }, + .capture = { + .rates = SSI_RATES, + .formats = SSI_FMTS, + .channels_min = SSI_CHAN_MIN, + .channels_max = SSI_CHAN_MAX, + }, + .ops = &rz_ssi_dai_ops, + }, +}; + +static const struct snd_soc_component_driver rz_ssi_soc_component = { + .name = "rz-ssi", + .open = rz_ssi_pcm_open, + .pointer = rz_ssi_pcm_pointer, + .pcm_construct = rz_ssi_pcm_new, +}; + +static int rz_ssi_probe(struct platform_device *pdev) +{ + struct rz_ssi_priv *ssi; + struct clk *audio_clk; + int ret = 0; + + ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); + if (!ssi) + return -ENOMEM; + + ssi->pdev = pdev; + ssi->dev = &pdev->dev; + ssi->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ssi->base)) + return PTR_ERR(ssi->base); + + ssi->clk = devm_clk_get(&pdev->dev, "ssi"); + if (IS_ERR(ssi->clk)) + return PTR_ERR(ssi->clk); + + ssi->sfr_clk = devm_clk_get(&pdev->dev, "ssi_sfr"); + if (IS_ERR(ssi->sfr_clk)) + return PTR_ERR(ssi->sfr_clk); + + audio_clk = devm_clk_get(&pdev->dev, "audio_clk1"); + if (IS_ERR(audio_clk)) { + ret |= PTR_ERR(audio_clk); + ssi->audio_clk_1 = 0; + } else { + ssi->audio_clk_1 = clk_get_rate(audio_clk); + } + + audio_clk = devm_clk_get(&pdev->dev, "audio_clk2"); + if (IS_ERR(audio_clk)) { + ret |= PTR_ERR(audio_clk); + ssi->audio_clk_2 = 0; + } else { + ssi->audio_clk_2 = clk_get_rate(audio_clk); + } + + if (!(ssi->audio_clk_1 || ssi->audio_clk_2)) + return dev_err_probe(&pdev->dev, ret, + "no audio clk1 or audio clk2"); + + ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2; + + /* Error Interrupt */ + ssi->irq_int = platform_get_irq_byname(pdev, "int_req"); + if (ssi->irq_int < 0) + return dev_err_probe(&pdev->dev, -ENODEV, + "Unable to get SSI int_req IRQ\n"); + + ret = devm_request_irq(&pdev->dev, ssi->irq_int, &rz_ssi_interrupt, + 0, dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (int_req)\n"); + + /* Tx and Rx interrupts (pio only) */ + ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx"); + if (ssi->irq_tx < 0) + return dev_err_probe(&pdev->dev, -ENODEV, + "Unable to get SSI dma_tx IRQ\n"); + + ret = devm_request_irq(&pdev->dev, ssi->irq_tx, &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_tx)\n"); + + ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx"); + if (ssi->irq_rx < 0) + return dev_err_probe(&pdev->dev, -ENODEV, + "Unable to get SSI dma_rx IRQ\n"); + + ret = devm_request_irq(&pdev->dev, ssi->irq_rx, &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_rx)\n"); + + ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(ssi->rstc)) + return PTR_ERR(ssi->rstc); + + reset_control_deassert(ssi->rstc); + pm_runtime_enable(&pdev->dev); + pm_runtime_resume_and_get(&pdev->dev); + + ssi->playback.transfer = rz_ssi_pio_send; + ssi->capture.transfer = rz_ssi_pio_recv; + ssi->playback.priv = ssi; + ssi->capture.priv = ssi; + + spin_lock_init(&ssi->lock); + dev_set_drvdata(&pdev->dev, ssi); + ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component, + rz_ssi_soc_dai, + ARRAY_SIZE(rz_ssi_soc_dai)); + if (ret < 0) { + pm_runtime_put(ssi->dev); + pm_runtime_disable(ssi->dev); + reset_control_assert(ssi->rstc); + dev_err(&pdev->dev, "failed to register snd component\n"); + } + + return ret; +} + +static int rz_ssi_remove(struct platform_device *pdev) +{ + struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev); + + pm_runtime_put(ssi->dev); + pm_runtime_disable(ssi->dev); + reset_control_assert(ssi->rstc); + + return 0; +} + +static const struct of_device_id rz_ssi_of_match[] = { + { .compatible = "renesas,rz-ssi", }, + {/* Sentinel */}, +}; +MODULE_DEVICE_TABLE(of, rz_ssi_of_match); + +static struct platform_driver rz_ssi_driver = { + .driver = { + .name = "rz-ssi-pcm-audio", + .of_match_table = rz_ssi_of_match, + }, + .probe = rz_ssi_probe, + .remove = rz_ssi_remove, +}; + +module_platform_driver(rz_ssi_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Renesas RZ/G2L ASoC serial sound interface driver"); +MODULE_AUTHOR("Biju Das biju.das.jz@bp.renesas.com");
Hi Biju,
On Mon, Jul 19, 2021 at 3:40 PM Biju Das biju.das.jz@bp.renesas.com wrote:
Add serial sound interface(SSIF-2) driver support for RZ/G2L SoC.
Based on the work done by Chris Brandt for RZ/A SSI driver.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
Thanks for your patch!
--- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -45,6 +45,16 @@ config SND_SOC_RCAR help This option enables R-Car SRU/SCU/SSIU/SSI sound support
+config SND_SOC_RZ
tristate "RZ/G2L series SSIF-2 support"
depends on OF || COMPILE_TEST
ARCH_R9A07G044 implies OF
depends on ARCH_R9A07G044
Is there any hard compile-time dependency on ARCH_R9A07G044?
Perhaps you meant
depends on ARCH_R9A07G044 || COMPILE_TEST
?
select SND_SIMPLE_CARD
help
This option enables ASoC sound support for the RZ/G2L MPUs.
The simple-audio-card driver and the RZ/G2L built-in serial
sound interface (SSIF-2) driver are used.
Gr{oetje,eeting}s,
Geert
Hi Geert,
Thanks for the feedback.
Subject: Re: [PATCH v2 2/8] sound: soc: sh: Add RZ/G2L SSIF-2 driver
Hi Biju,
On Mon, Jul 19, 2021 at 3:40 PM Biju Das biju.das.jz@bp.renesas.com wrote:
Add serial sound interface(SSIF-2) driver support for RZ/G2L SoC.
Based on the work done by Chris Brandt for RZ/A SSI driver.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
Thanks for your patch!
--- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -45,6 +45,16 @@ config SND_SOC_RCAR help This option enables R-Car SRU/SCU/SSIU/SSI sound support
+config SND_SOC_RZ
tristate "RZ/G2L series SSIF-2 support"
depends on OF || COMPILE_TEST
ARCH_R9A07G044 implies OF
depends on ARCH_R9A07G044
Is there any hard compile-time dependency on ARCH_R9A07G044?
Perhaps you meant
depends on ARCH_R9A07G044 || COMPILE_TEST
OK, Will update this in the next version.
Regards, Biju
?
select SND_SIMPLE_CARD
help
This option enables ASoC sound support for the RZ/G2L MPUs.
The simple-audio-card driver and the RZ/G2L built-in serial
sound interface (SSIF-2) driver are used.
Gr{oetje,eeting}s,
Geert
-- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux- m68k.org
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Document DMA support in binding document.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- v1->v2: * No change. --- .../devicetree/bindings/sound/renesas,rz-ssi.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml index 891f381ee5b8..471937cb8d05 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml @@ -45,6 +45,18 @@ properties: resets: maxItems: 1
+ dmas: + minItems: 1 + maxItems: 2 + + dma-names: + oneOf: + - items: + - const: tx + - const: rx + - items: + - const: rt + '#sound-dai-cells': const: 0
@@ -81,5 +93,8 @@ examples: clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2"; power-domains = <&cpg>; resets = <&cpg R9A07G044_SSI0_RST_M2_REG>; + dmas = <&dmac 0x255>, + <&dmac 0x256>; + dma-names = "tx", "rx"; #sound-dai-cells = <0>; };
On Mon, 19 Jul 2021 14:40:38 +0100, Biju Das wrote:
Document DMA support in binding document.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
v1->v2:
- No change.
.../devicetree/bindings/sound/renesas,rz-ssi.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
Reviewed-by: Rob Herring robh@kernel.org
Add SSI DMAC support to RZ/G2L SoC.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- v1->v2: * No change. --- sound/soc/sh/rz-ssi.c | 273 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 238 insertions(+), 35 deletions(-)
diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index 51adddc406e7..024a76a52296 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -7,6 +7,7 @@ */
#include <linux/clk.h> +#include <linux/dmaengine.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of_device.h> @@ -80,12 +81,16 @@ #define SSI_CHAN_MAX 2 #define SSI_FIFO_DEPTH 32
+#define DMA_CHCFG_TX_DEFAULT (0x11228) +#define DMA_CHCFG_RX_DEFAULT (0x11220) + struct rz_ssi_priv;
struct rz_ssi_stream { struct rz_ssi_priv *priv; struct snd_pcm_substream *substream; int fifo_sample_size; /* sample capacity of SSI FIFO */ + int dma_buffer_pos; /* The address for the next DMA descriptor */ int period_counter; /* for keeping track of periods transferred */ int sample_width; int buffer_pos; /* current frame position in the buffer */ @@ -94,6 +99,8 @@ struct rz_ssi_stream { int uerr_num; int oerr_num;
+ struct dma_chan *dma_ch; + int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm); };
@@ -105,6 +112,7 @@ struct rz_ssi_priv { struct clk *sfr_clk; struct clk *clk;
+ phys_addr_t phys; int irq_int; int irq_tx; int irq_rx; @@ -128,8 +136,11 @@ struct rz_ssi_priv {
bool lrckp_fsync_fall; /* LR clock polarity (SSICR.LRCKP) */ bool bckp_rise; /* Bit clock polarity (SSICR.BCKP) */ + bool dma_rt; };
+static void rz_ssi_dma_complete(void *data); + static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data) { writel(data, (priv->base + reg)); @@ -175,6 +186,11 @@ rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream) return stream; }
+static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi) +{ + return (ssi->playback.dma_ch || ssi->capture.dma_ch); +} + static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { @@ -197,6 +213,7 @@ static int rz_ssi_stream_init(struct rz_ssi_priv *ssi, strm->substream = substream;
strm->sample_width = samples_to_bytes(runtime, 1); + strm->dma_buffer_pos = 0; strm->period_counter = 0; strm->buffer_pos = 0;
@@ -321,9 +338,12 @@ static int rz_ssi_start_stop(struct rz_ssi_priv *ssi, ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF;
/* FIFO interrupt thresholds */ - rz_ssi_reg_writel(ssi, SSISCR, - SSISCR_TDES(strm->fifo_sample_size / 2 - 1) | - SSISCR_RDFS(0)); + if (rz_ssi_is_dma_enabled(ssi)) + rz_ssi_reg_writel(ssi, SSISCR, 0); + else + rz_ssi_reg_writel(ssi, SSISCR, + SSISCR_TDES(strm->fifo_sample_size / 2 - 1) | + SSISCR_RDFS(0));
/* enable IRQ */ if (rz_ssi_stream_is_play(ssi, strm)) { @@ -349,6 +369,10 @@ static int rz_ssi_start_stop(struct rz_ssi_priv *ssi, } else { strm->running = 0;
+ /* Cancel all remaining DMA transactions */ + if (rz_ssi_is_dma_enabled(ssi)) + dmaengine_terminate_sync(strm->dma_ch); + /* Disable irqs */ rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN | SSICR_RUIEN | SSICR_ROIEN, 0); @@ -562,12 +586,153 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data) return IRQ_HANDLED; }
+static int rz_ssi_dma_slave_config(struct rz_ssi_priv *ssi, + struct dma_chan *dma_ch, bool is_play) +{ + struct dma_slave_config cfg; + static u32 chcfg; + + memset(&cfg, 0, sizeof(cfg)); + + if (is_play) { + cfg.direction = DMA_MEM_TO_DEV; + cfg.dst_addr = ssi->phys + SSIFTDR; + chcfg = DMA_CHCFG_TX_DEFAULT; + } else { + cfg.direction = DMA_DEV_TO_MEM; + cfg.src_addr = ssi->phys + SSIFRDR; + chcfg = DMA_CHCFG_RX_DEFAULT; + } + + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + cfg.peripheral_config = &chcfg; + + return dmaengine_slave_config(dma_ch, &cfg); +} + +static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi, + struct rz_ssi_stream *strm) +{ + struct dma_async_tx_descriptor *desc; + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; + enum dma_transfer_direction dir; + u32 dma_paddr, dma_size; + int amount; + + if (!rz_ssi_stream_is_valid(ssi, strm)) + return -EINVAL; + + substream = strm->substream; + runtime = substream->runtime; + + if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) + /* + * Stream is ending, so do not queue up any more DMA + * transfers otherwise we play partial sound clips + * because we can't shut off the DMA quick enough. + */ + return 0; + + dir = rz_ssi_stream_is_play(ssi, strm) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; + + /* Always transfer 1 period */ + amount = runtime->period_size; + + /* DMA physical address and size */ + dma_paddr = runtime->dma_addr + frames_to_bytes(runtime, + strm->dma_buffer_pos); + dma_size = frames_to_bytes(runtime, amount); + desc = dmaengine_prep_slave_single(strm->dma_ch, dma_paddr, dma_size, + dir, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) { + dev_err(ssi->dev, "dmaengine_prep_slave_single() fail\n"); + return -ENOMEM; + } + + desc->callback = rz_ssi_dma_complete; + desc->callback_param = strm; + + if (dmaengine_submit(desc) < 0) { + dev_err(ssi->dev, "dmaengine_submit() fail\n"); + return -EIO; + } + + /* Update DMA pointer */ + strm->dma_buffer_pos += amount; + if (strm->dma_buffer_pos >= runtime->buffer_size) + strm->dma_buffer_pos = 0; + + /* Start DMA */ + dma_async_issue_pending(strm->dma_ch); + + return 0; +} + +static void rz_ssi_dma_complete(void *data) +{ + struct rz_ssi_stream *strm = (struct rz_ssi_stream *)data; + + if (!strm->running) + return; + + /* Note that next DMA transaction has probably already started */ + rz_ssi_pointer_update(strm, strm->substream->runtime->period_size); + + /* Queue up another DMA transaction */ + rz_ssi_dma_transfer(strm->priv, strm); +} + +static void rz_ssi_release_dma_channels(struct rz_ssi_priv *ssi) +{ + if (ssi->playback.dma_ch) { + dma_release_channel(ssi->playback.dma_ch); + ssi->playback.dma_ch = NULL; + if (ssi->dma_rt) + ssi->dma_rt = false; + } + + if (ssi->capture.dma_ch) { + dma_release_channel(ssi->capture.dma_ch); + ssi->capture.dma_ch = NULL; + } +} + +static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev) +{ + ssi->playback.dma_ch = dma_request_slave_channel(dev, "tx"); + ssi->capture.dma_ch = dma_request_slave_channel(dev, "rx"); + if (!ssi->playback.dma_ch || !ssi->capture.dma_ch) { + ssi->playback.dma_ch = dma_request_slave_channel(dev, "rt"); + if (!ssi->playback.dma_ch) + goto no_dma; + + ssi->dma_rt = true; + } + + if (ssi->playback.dma_ch && + (rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, true) < 0)) + goto no_dma; + + if (ssi->capture.dma_ch && + (rz_ssi_dma_slave_config(ssi, ssi->capture.dma_ch, false) < 0)) + goto no_dma; + + return 0; + +no_dma: + rz_ssi_release_dma_channels(ssi); + + return -ENODEV; +} + static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream); - int ret = 0; + int ret = 0, i, num_transfer = 1;
switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -580,9 +745,26 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ret) goto done;
- ret = strm->transfer(ssi, strm); - if (ret) - goto done; + if (ssi->dma_rt) { + ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, + rz_ssi_stream_is_play(ssi, strm)); + /* Fallback to pio */ + if (ret < 0) { + ssi->playback.transfer = rz_ssi_pio_send; + ssi->capture.transfer = rz_ssi_pio_recv; + rz_ssi_release_dma_channels(ssi); + } + } + + /* For DMA, queue up multiple DMA descriptors */ + if (rz_ssi_is_dma_enabled(ssi)) + num_transfer = 4; + + for (i = 0; i < num_transfer; i++) { + ret = strm->transfer(ssi, strm); + if (ret) + goto done; + }
ret = rz_ssi_start_stop(ssi, strm, 1); break; @@ -737,6 +919,7 @@ static int rz_ssi_probe(struct platform_device *pdev) { struct rz_ssi_priv *ssi; struct clk *audio_clk; + struct resource *res; int ret = 0;
ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); @@ -745,10 +928,12 @@ static int rz_ssi_probe(struct platform_device *pdev)
ssi->pdev = pdev; ssi->dev = &pdev->dev; - ssi->base = devm_platform_ioremap_resource(pdev, 0); + ssi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(ssi->base)) return PTR_ERR(ssi->base);
+ ssi->phys = res->start; + ssi->clk = devm_clk_get(&pdev->dev, "ssi"); if (IS_ERR(ssi->clk)) return PTR_ERR(ssi->clk); @@ -779,6 +964,21 @@ static int rz_ssi_probe(struct platform_device *pdev)
ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2;
+ /* Detect DMA support */ + ret = rz_ssi_dma_request(ssi, &pdev->dev); + if (ret < 0) { + dev_warn(&pdev->dev, "DMA not available, using PIO\n"); + ssi->playback.transfer = rz_ssi_pio_send; + ssi->capture.transfer = rz_ssi_pio_recv; + } else { + dev_info(&pdev->dev, "DMA enabled"); + ssi->playback.transfer = rz_ssi_dma_transfer; + ssi->capture.transfer = rz_ssi_dma_transfer; + } + + ssi->playback.priv = ssi; + ssi->capture.priv = ssi; + /* Error Interrupt */ ssi->irq_int = platform_get_irq_byname(pdev, "int_req"); if (ssi->irq_int < 0) @@ -791,28 +991,32 @@ static int rz_ssi_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, ret, "irq request error (int_req)\n");
- /* Tx and Rx interrupts (pio only) */ - ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx"); - if (ssi->irq_tx < 0) - return dev_err_probe(&pdev->dev, -ENODEV, - "Unable to get SSI dma_tx IRQ\n"); - - ret = devm_request_irq(&pdev->dev, ssi->irq_tx, &rz_ssi_interrupt, 0, - dev_name(&pdev->dev), ssi); - if (ret < 0) - return dev_err_probe(&pdev->dev, ret, - "irq request error (dma_tx)\n"); - - ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx"); - if (ssi->irq_rx < 0) - return dev_err_probe(&pdev->dev, -ENODEV, - "Unable to get SSI dma_rx IRQ\n"); - - ret = devm_request_irq(&pdev->dev, ssi->irq_rx, &rz_ssi_interrupt, 0, - dev_name(&pdev->dev), ssi); - if (ret < 0) - return dev_err_probe(&pdev->dev, ret, - "irq request error (dma_rx)\n"); + if (!rz_ssi_is_dma_enabled(ssi)) { + /* Tx and Rx interrupts (pio only) */ + ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx"); + if (ssi->irq_tx < 0) + return dev_err_probe(&pdev->dev, -ENODEV, + "Unable to get SSI dma_tx IRQ\n"); + + ret = devm_request_irq(&pdev->dev, ssi->irq_tx, + &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_tx)\n"); + + ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx"); + if (ssi->irq_rx < 0) + return dev_err_probe(&pdev->dev, -ENODEV, + "Unable to get SSI dma_rx IRQ\n"); + + ret = devm_request_irq(&pdev->dev, ssi->irq_rx, + &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_rx)\n"); + }
ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(ssi->rstc)) @@ -822,17 +1026,14 @@ static int rz_ssi_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_resume_and_get(&pdev->dev);
- ssi->playback.transfer = rz_ssi_pio_send; - ssi->capture.transfer = rz_ssi_pio_recv; - ssi->playback.priv = ssi; - ssi->capture.priv = ssi; - spin_lock_init(&ssi->lock); dev_set_drvdata(&pdev->dev, ssi); ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component, rz_ssi_soc_dai, ARRAY_SIZE(rz_ssi_soc_dai)); if (ret < 0) { + rz_ssi_release_dma_channels(ssi); + pm_runtime_put(ssi->dev); pm_runtime_disable(ssi->dev); reset_control_assert(ssi->rstc); @@ -846,6 +1047,8 @@ static int rz_ssi_remove(struct platform_device *pdev) { struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev);
+ rz_ssi_release_dma_channels(ssi); + pm_runtime_put(ssi->dev); pm_runtime_disable(ssi->dev); reset_control_assert(ssi->rstc);
On Mon, 19 Jul 2021 14:40:32 +0100, Biju Das wrote:
This patch series aims to add ASoC support on RZ/G2L SoC's.
It is based on the work done by Chris Brandt for RZ/A ASoC driver.
Biju Das (8): ASoC: dt-bindings: Document RZ/G2L bindings sound: soc: sh: Add RZ/G2L SSIF-2 driver arm64: dts: renesas: r9a07g044: Add external audio clock nodes arm64: dts: renesas: r9a07g044: Add SSI support arm64: defconfig: Enable ASoC sound support for RZ/G2L SoC ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support sound: sh: rz-ssi: Add SSI DMAC support arm64: dts: renesas: r9a07g044: Add SSI DMA support
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/8] ASoC: dt-bindings: Document RZ/G2L bindings commit: 2b761f476f3a6e0a212c8c88e7855f66edb177e0 [6/8] ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support commit: 5df6dfbb6de815ba3a75c788a916865212fd5221
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
Hi Mark,
-----Original Message----- From: Mark Brown broonie@kernel.org Sent: 30 July 2021 20:04 To: Takashi Iwai tiwai@suse.com; Liam Girdwood lgirdwood@gmail.com; Rob Herring robh+dt@kernel.org; Jaroslav Kysela perex@perex.cz; Philipp Zabel p.zabel@pengutronix.de; Biju Das biju.das.jz@bp.renesas.com Cc: Mark Brown broonie@kernel.org; Prabhakar Mahadev Lad prabhakar.mahadev-lad.rj@bp.renesas.com; Kuninori Morimoto kuninori.morimoto.gx@renesas.com; Chris Brandt Chris.Brandt@renesas.com; Chris Paterson Chris.Paterson2@renesas.com; Geert Uytterhoeven geert+renesas@glider.be; alsa-devel@alsa- project.org; linux-renesas-soc@vger.kernel.org; Biju Das biju.das@bp.renesas.com; devicetree@vger.kernel.org Subject: Re: (subset) [PATCH v2 0/8] Add RZ/G2L Sound support
On Mon, 19 Jul 2021 14:40:32 +0100, Biju Das wrote:
This patch series aims to add ASoC support on RZ/G2L SoC's.
It is based on the work done by Chris Brandt for RZ/A ASoC driver.
Biju Das (8): ASoC: dt-bindings: Document RZ/G2L bindings sound: soc: sh: Add RZ/G2L SSIF-2 driver arm64: dts: renesas: r9a07g044: Add external audio clock nodes arm64: dts: renesas: r9a07g044: Add SSI support arm64: defconfig: Enable ASoC sound support for RZ/G2L SoC ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support sound: sh: rz-ssi: Add SSI DMAC support arm64: dts: renesas: r9a07g044: Add SSI DMA support
[...]
Applied to
https://jpn01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel... Fkernel%2Fgit%2Fbroonie%2Fsound.git&data=04%7C01%7Cprabhakar.mahadev- lad.rj%40bp.renesas.com%7C60c047db42e149eacdb808d9538ccc7e%7C53d82571da1947e49cb4625a166a4a2a%7C0%7C0% 7C637632686468564246%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXV CI6Mn0%3D%7C1000&sdata=Rdyi2vXY9i%2Fly%2FOTWVFmc8k0rVbpM75FthJn7rijxwU%3D&reserved=0 for-next
Thanks!
[1/8] ASoC: dt-bindings: Document RZ/G2L bindings commit: 2b761f476f3a6e0a212c8c88e7855f66edb177e0 [6/8] ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support commit: 5df6dfbb6de815ba3a75c788a916865212fd5221
There is a updated version of the patch [1] which was posted yesterday due to change in handling DMA slave channel configuration [2]. Both the queued patches need to dropped.
[1] https://patchwork.kernel.org/project/linux-renesas-soc/patch/20210729172311.... [2] https://patchwork.kernel.org/project/linux-renesas-soc/patch/20210729082520....
Cheers, Prabhakar
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
Hi Mark and Prabhakar,
+ Vinod.
The first binding patch is for SSI support in interrupt mode. so it is ok.
The second binding patch is for adding DMA support in ssi. The example value in #dma-cells need to be updated. Earlier it was just MID/RID value.
Based on recent discussion with Vinod and Geert, It needs to updated with encoded values of MID/RID value and legacy channel configuration parameters, as passing the later to driver using slave_config is not recommended.
So either drop the second patch or Will send a follow up patch fixing the example
+ dmas = <&dmac 0x2655>, + <&dmac 0x2656>;
Please let me know.
Regards, Biju
-----Original Message----- From: Prabhakar Mahadev Lad prabhakar.mahadev-lad.rj@bp.renesas.com Sent: 30 July 2021 20:13 To: Mark Brown broonie@kernel.org; Takashi Iwai tiwai@suse.com; Liam Girdwood lgirdwood@gmail.com; Rob Herring robh+dt@kernel.org; Jaroslav Kysela perex@perex.cz; Philipp Zabel p.zabel@pengutronix.de; Biju Das biju.das.jz@bp.renesas.com Cc: Kuninori Morimoto kuninori.morimoto.gx@renesas.com; Chris Brandt Chris.Brandt@renesas.com; Chris Paterson Chris.Paterson2@renesas.com; Geert Uytterhoeven geert+renesas@glider.be; alsa-devel@alsa-project.org; linux-renesas-soc@vger.kernel.org; Biju Das biju.das@bp.renesas.com; devicetree@vger.kernel.org Subject: RE: (subset) [PATCH v2 0/8] Add RZ/G2L Sound support
Hi Mark,
-----Original Message----- From: Mark Brown broonie@kernel.org Sent: 30 July 2021 20:04 To: Takashi Iwai tiwai@suse.com; Liam Girdwood lgirdwood@gmail.com; Rob Herring robh+dt@kernel.org; Jaroslav Kysela perex@perex.cz; Philipp Zabel p.zabel@pengutronix.de; Biju Das biju.das.jz@bp.renesas.com Cc: Mark Brown broonie@kernel.org; Prabhakar Mahadev Lad prabhakar.mahadev-lad.rj@bp.renesas.com; Kuninori Morimoto kuninori.morimoto.gx@renesas.com; Chris Brandt Chris.Brandt@renesas.com; Chris Paterson Chris.Paterson2@renesas.com; Geert Uytterhoeven geert+renesas@glider.be; alsa-devel@alsa- project.org; linux-renesas-soc@vger.kernel.org; Biju Das biju.das@bp.renesas.com; devicetree@vger.kernel.org Subject: Re: (subset) [PATCH v2 0/8] Add RZ/G2L Sound support
On Mon, 19 Jul 2021 14:40:32 +0100, Biju Das wrote:
This patch series aims to add ASoC support on RZ/G2L SoC's.
It is based on the work done by Chris Brandt for RZ/A ASoC driver.
Biju Das (8): ASoC: dt-bindings: Document RZ/G2L bindings sound: soc: sh: Add RZ/G2L SSIF-2 driver arm64: dts: renesas: r9a07g044: Add external audio clock nodes arm64: dts: renesas: r9a07g044: Add SSI support arm64: defconfig: Enable ASoC sound support for RZ/G2L SoC ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support sound: sh: rz-ssi: Add SSI DMAC support arm64: dts: renesas: r9a07g044: Add SSI DMA support
[...]
Applied to
https://jpn01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit. kernel.org%2Fpub%2Fscm%2Flinux%2 Fkernel%2Fgit%2Fbroonie%2Fsound.git&data=04%7C01%7Cprabhakar.mahad ev- lad.rj%40bp.renesas.com%7C60c047db42e149eacdb808d9538ccc7e%7C53d82571d a1947e49cb4625a166a4a2a%7C0%7C0% 7C637632686468564246%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQI joiV2luMzIiLCJBTiI6Ik1haWwiLCJXV CI6Mn0%3D%7C1000&sdata=Rdyi2vXY9i%2Fly%2FOTWVFmc8k0rVbpM75FthJn7ri jxwU%3D&reserved=0 for-next
Thanks!
[1/8] ASoC: dt-bindings: Document RZ/G2L bindings commit: 2b761f476f3a6e0a212c8c88e7855f66edb177e0 [6/8] ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support commit: 5df6dfbb6de815ba3a75c788a916865212fd5221
There is a updated version of the patch [1] which was posted yesterday due to change in handling DMA slave channel configuration [2]. Both the queued patches need to dropped.
[1] https://patchwork.kernel.org/project/linux-renesas- soc/patch/20210729172311.31111-2-biju.das.jz@bp.renesas.com/ [2] https://patchwork.kernel.org/project/linux-renesas- soc/patch/20210729082520.26186-2-biju.das.jz@bp.renesas.com/
Cheers, Prabhakar
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix),
however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if
needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks, Mark
On Fri, Jul 30, 2021 at 07:13:24PM +0000, Prabhakar Mahadev Lad wrote:
There is a updated version of the patch [1] which was posted yesterday due to change in handling DMA slave channel configuration [2]. Both the queued patches need to dropped.
Can you send a revert or incremental patch for this explaining the issue please?
Please fix your mail client to word wrap within paragraphs at something substantially less than 80 columns. Doing this makes your messages much easier to read and reply to.
Hi Mark,
On Mon, Aug 2, 2021 at 1:17 PM Mark Brown broonie@kernel.org wrote:
On Fri, Jul 30, 2021 at 07:13:24PM +0000, Prabhakar Mahadev Lad wrote:
There is a updated version of the patch [1] which was posted yesterday due to change in handling DMA slave channel configuration [2]. Both the queued patches need to dropped.
Can you send a revert or incremental patch for this explaining the issue please?
Sure, Biju will send an incremental patch explaining the issue.
Please fix your mail client to word wrap within paragraphs at something substantially less than 80 columns. Doing this makes your messages much easier to read and reply to.
Sorry for the inconvenience, I have fixed it now.
Cheers, Prabhakar
participants (6)
-
Biju Das
-
Geert Uytterhoeven
-
Lad, Prabhakar
-
Mark Brown
-
Prabhakar Mahadev Lad
-
Rob Herring