summaryrefslogtreecommitdiff
path: root/sound/soc/sh/rcar
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sh/rcar')
-rw-r--r--sound/soc/sh/rcar/Makefile3
-rw-r--r--sound/soc/sh/rcar/adg.c775
-rw-r--r--sound/soc/sh/rcar/cmd.c195
-rw-r--r--sound/soc/sh/rcar/core.c2114
-rw-r--r--sound/soc/sh/rcar/ctu.c393
-rw-r--r--sound/soc/sh/rcar/debugfs.c96
-rw-r--r--sound/soc/sh/rcar/dma.c946
-rw-r--r--sound/soc/sh/rcar/dvc.c396
-rw-r--r--sound/soc/sh/rcar/gen.c562
-rw-r--r--sound/soc/sh/rcar/mix.c360
-rw-r--r--sound/soc/sh/rcar/rsnd.h916
-rw-r--r--sound/soc/sh/rcar/src.c736
-rw-r--r--sound/soc/sh/rcar/ssi.c1260
-rw-r--r--sound/soc/sh/rcar/ssiu.c609
14 files changed, 0 insertions, 9361 deletions
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile
deleted file mode 100644
index d07eccfa3ac2..000000000000
--- a/sound/soc/sh/rcar/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o ssiu.o src.o ctu.o mix.o dvc.o cmd.o debugfs.o
-obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
deleted file mode 100644
index afd69c6eb654..000000000000
--- a/sound/soc/sh/rcar/adg.c
+++ /dev/null
@@ -1,775 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Helper routines for R-Car sound ADG.
-//
-// Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-#include "rsnd.h"
-
-#define CLKA 0
-#define CLKB 1
-#define CLKC 2
-#define CLKI 3
-#define CLKINMAX 4
-
-#define CLKOUT 0
-#define CLKOUT1 1
-#define CLKOUT2 2
-#define CLKOUT3 3
-#define CLKOUTMAX 4
-
-#define BRRx_MASK(x) (0x3FF & x)
-
-static struct rsnd_mod_ops adg_ops = {
- .name = "adg",
-};
-
-#define ADG_HZ_441 0
-#define ADG_HZ_48 1
-#define ADG_HZ_SIZE 2
-
-struct rsnd_adg {
- struct clk *clkin[CLKINMAX];
- struct clk *clkout[CLKOUTMAX];
- struct clk *null_clk;
- struct clk_onecell_data onecell;
- struct rsnd_mod mod;
- int clkin_rate[CLKINMAX];
- int clkin_size;
- int clkout_size;
- u32 ckr;
- u32 brga;
- u32 brgb;
-
- int brg_rate[ADG_HZ_SIZE]; /* BRGA / BRGB */
-};
-
-#define for_each_rsnd_clkin(pos, adg, i) \
- for (i = 0; \
- (i < adg->clkin_size) && \
- ((pos) = adg->clkin[i]); \
- i++)
-#define for_each_rsnd_clkout(pos, adg, i) \
- for (i = 0; \
- (i < adg->clkout_size) && \
- ((pos) = adg->clkout[i]); \
- i++)
-#define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
-
-static const char * const clkin_name_gen4[] = {
- [CLKA] = "clkin",
-};
-
-static const char * const clkin_name_gen2[] = {
- [CLKA] = "clk_a",
- [CLKB] = "clk_b",
- [CLKC] = "clk_c",
- [CLKI] = "clk_i",
-};
-
-static const char * const clkout_name_gen2[] = {
- [CLKOUT] = "audio_clkout",
- [CLKOUT1] = "audio_clkout1",
- [CLKOUT2] = "audio_clkout2",
- [CLKOUT3] = "audio_clkout3",
-};
-
-static u32 rsnd_adg_calculate_brgx(unsigned long div)
-{
- int i;
-
- if (!div)
- return 0;
-
- for (i = 3; i >= 0; i--) {
- int ratio = 2 << (i * 2);
- if (0 == (div % ratio))
- return (u32)((i << 8) | ((div / ratio) - 1));
- }
-
- return ~0;
-}
-
-static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
-{
- struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- int id = rsnd_mod_id(ssi_mod);
- int ws = id;
-
- if (rsnd_ssi_is_pin_sharing(io)) {
- switch (id) {
- case 1:
- case 2:
- case 9:
- ws = 0;
- break;
- case 4:
- ws = 3;
- break;
- case 8:
- ws = 7;
- break;
- }
- } else {
- /*
- * SSI8 is not connected to ADG.
- * Thus SSI9 is using ws = 8
- */
- if (id == 9)
- ws = 8;
- }
-
- return (0x6 + ws) << 8;
-}
-
-static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- unsigned int target_rate,
- unsigned int *target_val,
- unsigned int *target_en)
-{
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- int sel;
- unsigned int val, en;
- unsigned int min, diff;
- unsigned int sel_rate[] = {
- adg->clkin_rate[CLKA], /* 0000: CLKA */
- adg->clkin_rate[CLKB], /* 0001: CLKB */
- adg->clkin_rate[CLKC], /* 0010: CLKC */
- adg->brg_rate[ADG_HZ_441], /* 0011: BRGA */
- adg->brg_rate[ADG_HZ_48], /* 0100: BRGB */
- };
-
- min = ~0;
- val = 0;
- en = 0;
- for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) {
- int idx = 0;
- int step = 2;
- int div;
-
- if (!sel_rate[sel])
- continue;
-
- for (div = 2; div <= 98304; div += step) {
- diff = abs(target_rate - sel_rate[sel] / div);
- if (min > diff) {
- val = (sel << 8) | idx;
- min = diff;
- en = 1 << (sel + 1); /* fixme */
- }
-
- /*
- * step of 0_0000 / 0_0001 / 0_1101
- * are out of order
- */
- if ((idx > 2) && (idx % 2))
- step *= 2;
- if (idx == 0x1c) {
- div += step;
- step *= 2;
- }
- idx++;
- }
- }
-
- if (min == ~0) {
- dev_err(dev, "no Input clock\n");
- return;
- }
-
- *target_val = val;
- if (target_en)
- *target_en = en;
-}
-
-static void rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- unsigned int in_rate,
- unsigned int out_rate,
- u32 *in, u32 *out, u32 *en)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- unsigned int target_rate;
- u32 *target_val;
- u32 _in;
- u32 _out;
- u32 _en;
-
- /* default = SSI WS */
- _in =
- _out = rsnd_adg_ssi_ws_timing_gen2(io);
-
- target_rate = 0;
- target_val = NULL;
- _en = 0;
- if (runtime->rate != in_rate) {
- target_rate = out_rate;
- target_val = &_out;
- } else if (runtime->rate != out_rate) {
- target_rate = in_rate;
- target_val = &_in;
- }
-
- if (target_rate)
- __rsnd_adg_get_timesel_ratio(priv, io,
- target_rate,
- target_val, &_en);
-
- if (in)
- *in = _in;
- if (out)
- *out = _out;
- if (en)
- *en = _en;
-}
-
-int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(cmd_mod);
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- int id = rsnd_mod_id(cmd_mod);
- int shift = (id % 2) ? 16 : 0;
- u32 mask, val;
-
- rsnd_adg_get_timesel_ratio(priv, io,
- rsnd_src_get_in_rate(priv, io),
- rsnd_src_get_out_rate(priv, io),
- NULL, &val, NULL);
-
- val = val << shift;
- mask = 0x0f1f << shift;
-
- rsnd_mod_bset(adg_mod, CMDOUT_TIMSEL, mask, val);
-
- return 0;
-}
-
-int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,
- struct rsnd_dai_stream *io,
- unsigned int in_rate,
- unsigned int out_rate)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(src_mod);
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- u32 in, out;
- u32 mask, en;
- int id = rsnd_mod_id(src_mod);
- int shift = (id % 2) ? 16 : 0;
-
- rsnd_mod_confirm_src(src_mod);
-
- rsnd_adg_get_timesel_ratio(priv, io,
- in_rate, out_rate,
- &in, &out, &en);
-
- in = in << shift;
- out = out << shift;
- mask = 0x0f1f << shift;
-
- rsnd_mod_bset(adg_mod, SRCIN_TIMSEL(id / 2), mask, in);
- rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL(id / 2), mask, out);
-
- if (en)
- rsnd_mod_bset(adg_mod, DIV_EN, en, en);
-
- return 0;
-}
-
-static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- struct device *dev = rsnd_priv_to_dev(priv);
- int id = rsnd_mod_id(ssi_mod);
- int shift = (id % 4) * 8;
- u32 mask = 0xFF << shift;
-
- rsnd_mod_confirm_ssi(ssi_mod);
-
- val = val << shift;
-
- /*
- * SSI 8 is not connected to ADG.
- * it works with SSI 7
- */
- if (id == 8)
- return;
-
- rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL(id / 4), mask, val);
-
- dev_dbg(dev, "AUDIO_CLK_SEL is 0x%x\n", val);
-}
-
-int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
-{
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct clk *clk;
- int i;
- int sel_table[] = {
- [CLKA] = 0x1,
- [CLKB] = 0x2,
- [CLKC] = 0x3,
- [CLKI] = 0x0,
- };
-
- /*
- * find suitable clock from
- * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
- */
- for_each_rsnd_clkin(clk, adg, i)
- if (rate == adg->clkin_rate[i])
- return sel_table[i];
-
- /*
- * find divided clock from BRGA/BRGB
- */
- if (rate == adg->brg_rate[ADG_HZ_441])
- return 0x10;
-
- if (rate == adg->brg_rate[ADG_HZ_48])
- return 0x20;
-
- return -EIO;
-}
-
-int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod)
-{
- rsnd_adg_set_ssi_clk(ssi_mod, 0);
-
- return 0;
-}
-
-int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- int data;
- u32 ckr = 0;
-
- data = rsnd_adg_clk_query(priv, rate);
- if (data < 0)
- return data;
-
- rsnd_adg_set_ssi_clk(ssi_mod, data);
-
- if (0 == (rate % 8000))
- ckr = 0x80000000; /* BRGB output = 48kHz */
-
- rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr);
-
- dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n",
- (ckr) ? 'B' : 'A',
- (ckr) ? adg->brg_rate[ADG_HZ_48] :
- adg->brg_rate[ADG_HZ_441]);
-
- return 0;
-}
-
-void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
-{
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- struct clk *clk;
- int i;
-
- if (enable) {
- rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr);
- rsnd_mod_write(adg_mod, BRRA, adg->brga);
- rsnd_mod_write(adg_mod, BRRB, adg->brgb);
- }
-
- for_each_rsnd_clkin(clk, adg, i) {
- if (enable) {
- clk_prepare_enable(clk);
-
- /*
- * We shouldn't use clk_get_rate() under
- * atomic context. Let's keep it when
- * rsnd_adg_clk_enable() was called
- */
- adg->clkin_rate[i] = clk_get_rate(clk);
- } else {
- clk_disable_unprepare(clk);
- }
- }
-}
-
-static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,
- const char * const name,
- const char *parent)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct clk *clk;
-
- clk = clk_register_fixed_rate(dev, name, parent, 0, 0);
- if (IS_ERR_OR_NULL(clk)) {
- dev_err(dev, "create null clk error\n");
- return ERR_CAST(clk);
- }
-
- return clk;
-}
-
-static struct clk *rsnd_adg_null_clk_get(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg = priv->adg;
-
- if (!adg->null_clk) {
- static const char * const name = "rsnd_adg_null";
-
- adg->null_clk = rsnd_adg_create_null_clk(priv, name, NULL);
- }
-
- return adg->null_clk;
-}
-
-static void rsnd_adg_null_clk_clean(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg = priv->adg;
-
- if (adg->null_clk)
- clk_unregister_fixed_rate(adg->null_clk);
-}
-
-static int rsnd_adg_get_clkin(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg = priv->adg;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct clk *clk;
- const char * const *clkin_name;
- int clkin_size;
- int i;
-
- clkin_name = clkin_name_gen2;
- clkin_size = ARRAY_SIZE(clkin_name_gen2);
- if (rsnd_is_gen4(priv)) {
- clkin_name = clkin_name_gen4;
- clkin_size = ARRAY_SIZE(clkin_name_gen4);
- }
-
- for (i = 0; i < clkin_size; i++) {
- clk = devm_clk_get(dev, clkin_name[i]);
-
- if (IS_ERR_OR_NULL(clk))
- clk = rsnd_adg_null_clk_get(priv);
- if (IS_ERR_OR_NULL(clk))
- goto err;
-
- adg->clkin[i] = clk;
- }
-
- adg->clkin_size = clkin_size;
-
- return 0;
-
-err:
- dev_err(dev, "adg clock IN get failed\n");
-
- rsnd_adg_null_clk_clean(priv);
-
- return -EIO;
-}
-
-static void rsnd_adg_unregister_clkout(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg = priv->adg;
- struct clk *clk;
- int i;
-
- for_each_rsnd_clkout(clk, adg, i)
- clk_unregister_fixed_rate(clk);
-}
-
-static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg = priv->adg;
- struct clk *clk;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np = dev->of_node;
- struct property *prop;
- u32 ckr, brgx, brga, brgb;
- u32 req_rate[ADG_HZ_SIZE] = {};
- uint32_t count = 0;
- unsigned long req_Hz[ADG_HZ_SIZE];
- int clkout_size;
- int i, req_size;
- int approximate = 0;
- const char *parent_clk_name = NULL;
- const char * const *clkout_name;
- int brg_table[] = {
- [CLKA] = 0x0,
- [CLKB] = 0x1,
- [CLKC] = 0x4,
- [CLKI] = 0x2,
- };
-
- ckr = 0;
- brga = 0xff; /* default */
- brgb = 0xff; /* default */
-
- /*
- * ADG supports BRRA/BRRB output only
- * this means all clkout0/1/2/3 will be same rate
- */
- prop = of_find_property(np, "clock-frequency", NULL);
- if (!prop)
- goto rsnd_adg_get_clkout_end;
-
- req_size = prop->length / sizeof(u32);
- if (req_size > ADG_HZ_SIZE) {
- dev_err(dev, "too many clock-frequency\n");
- return -EINVAL;
- }
-
- of_property_read_u32_array(np, "clock-frequency", req_rate, req_size);
- req_Hz[ADG_HZ_48] = 0;
- req_Hz[ADG_HZ_441] = 0;
- for (i = 0; i < req_size; i++) {
- if (0 == (req_rate[i] % 44100))
- req_Hz[ADG_HZ_441] = req_rate[i];
- if (0 == (req_rate[i] % 48000))
- req_Hz[ADG_HZ_48] = req_rate[i];
- }
-
- /*
- * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC
- * have 44.1kHz or 48kHz base clocks for now.
- *
- * SSI itself can divide parent clock by 1/1 - 1/16
- * see
- * rsnd_adg_ssi_clk_try_start()
- * rsnd_ssi_master_clk_start()
- */
-
- /*
- * [APPROXIMATE]
- *
- * clk_i (internal clock) can't create accurate rate, it will be approximate rate.
- *
- * <Note>
- *
- * clk_i needs x2 of required maximum rate.
- * see
- * - Minimum division of BRRA/BRRB
- * - rsnd_ssi_clk_query()
- *
- * Sample Settings for TDM 8ch, 32bit width
- *
- * 8(ch) x 32(bit) x 44100(Hz) x 2<Note> = 22579200
- * 8(ch) x 32(bit) x 48000(Hz) x 2<Note> = 24576000
- *
- * clock-frequency = <22579200 24576000>;
- */
- for_each_rsnd_clkin(clk, adg, i) {
- u32 rate, div;
-
- rate = clk_get_rate(clk);
-
- if (0 == rate) /* not used */
- continue;
-
- /* BRGA */
-
- if (i == CLKI)
- /* see [APPROXIMATE] */
- rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_441]) * req_Hz[ADG_HZ_441];
- if (!adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441] && (0 == rate % 44100)) {
- div = rate / req_Hz[ADG_HZ_441];
- brgx = rsnd_adg_calculate_brgx(div);
- if (BRRx_MASK(brgx) == brgx) {
- brga = brgx;
- adg->brg_rate[ADG_HZ_441] = rate / div;
- ckr |= brg_table[i] << 20;
- if (req_Hz[ADG_HZ_441])
- parent_clk_name = __clk_get_name(clk);
- if (i == CLKI)
- approximate = 1;
- }
- }
-
- /* BRGB */
-
- if (i == CLKI)
- /* see [APPROXIMATE] */
- rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_48]) * req_Hz[ADG_HZ_48];
- if (!adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48] && (0 == rate % 48000)) {
- div = rate / req_Hz[ADG_HZ_48];
- brgx = rsnd_adg_calculate_brgx(div);
- if (BRRx_MASK(brgx) == brgx) {
- brgb = brgx;
- adg->brg_rate[ADG_HZ_48] = rate / div;
- ckr |= brg_table[i] << 16;
- if (req_Hz[ADG_HZ_48])
- parent_clk_name = __clk_get_name(clk);
- if (i == CLKI)
- approximate = 1;
- }
- }
- }
-
- if (!(adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48]) &&
- !(adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441]))
- goto rsnd_adg_get_clkout_end;
-
- if (approximate)
- dev_info(dev, "It uses CLK_I as approximate rate");
-
- clkout_name = clkout_name_gen2;
- clkout_size = ARRAY_SIZE(clkout_name_gen2);
- if (rsnd_is_gen4(priv))
- clkout_size = 1; /* reuse clkout_name_gen2[] */
-
- /*
- * ADG supports BRRA/BRRB output only.
- * this means all clkout0/1/2/3 will be * same rate
- */
-
- of_property_read_u32(np, "#clock-cells", &count);
- /*
- * for clkout
- */
- if (!count) {
- clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT],
- parent_clk_name, 0, req_rate[0]);
- if (IS_ERR_OR_NULL(clk))
- goto err;
-
- adg->clkout[CLKOUT] = clk;
- adg->clkout_size = 1;
- of_clk_add_provider(np, of_clk_src_simple_get, clk);
- }
- /*
- * for clkout0/1/2/3
- */
- else {
- for (i = 0; i < clkout_size; i++) {
- clk = clk_register_fixed_rate(dev, clkout_name[i],
- parent_clk_name, 0,
- req_rate[0]);
- if (IS_ERR_OR_NULL(clk))
- goto err;
-
- adg->clkout[i] = clk;
- }
- adg->onecell.clks = adg->clkout;
- adg->onecell.clk_num = clkout_size;
- adg->clkout_size = clkout_size;
- of_clk_add_provider(np, of_clk_src_onecell_get,
- &adg->onecell);
- }
-
-rsnd_adg_get_clkout_end:
- adg->ckr = ckr;
- adg->brga = brga;
- adg->brgb = brgb;
-
- return 0;
-
-err:
- dev_err(dev, "adg clock OUT get failed\n");
-
- rsnd_adg_unregister_clkout(priv);
-
- return -EIO;
-}
-
-#if defined(DEBUG) || defined(CONFIG_DEBUG_FS)
-__printf(3, 4)
-static void dbg_msg(struct device *dev, struct seq_file *m,
- const char *fmt, ...)
-{
- char msg[128];
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(msg, sizeof(msg), fmt, args);
- va_end(args);
-
- if (m)
- seq_puts(m, msg);
- else
- dev_dbg(dev, "%s", msg);
-}
-
-void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m)
-{
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct clk *clk;
- int i;
-
- for_each_rsnd_clkin(clk, adg, i)
- dbg_msg(dev, m, "%-18s : %pa : %ld\n",
- __clk_get_name(clk), clk, clk_get_rate(clk));
-
- dbg_msg(dev, m, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n",
- adg->ckr, adg->brga, adg->brgb);
- dbg_msg(dev, m, "BRGA (for 44100 base) = %d\n", adg->brg_rate[ADG_HZ_441]);
- dbg_msg(dev, m, "BRGB (for 48000 base) = %d\n", adg->brg_rate[ADG_HZ_48]);
-
- /*
- * Actual CLKOUT will be exchanged in rsnd_adg_ssi_clk_try_start()
- * by BRGCKR::BRGCKR_31
- */
- for_each_rsnd_clkout(clk, adg, i)
- dbg_msg(dev, m, "%-18s : %pa : %ld\n",
- __clk_get_name(clk), clk, clk_get_rate(clk));
-}
-#else
-#define rsnd_adg_clk_dbg_info(priv, m)
-#endif
-
-int rsnd_adg_probe(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg;
- struct device *dev = rsnd_priv_to_dev(priv);
- int ret;
-
- adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
- if (!adg)
- return -ENOMEM;
-
- ret = rsnd_mod_init(priv, &adg->mod, &adg_ops,
- NULL, 0, 0);
- if (ret)
- return ret;
-
- priv->adg = adg;
-
- ret = rsnd_adg_get_clkin(priv);
- if (ret)
- return ret;
-
- ret = rsnd_adg_get_clkout(priv);
- if (ret)
- return ret;
-
- rsnd_adg_clk_enable(priv);
- rsnd_adg_clk_dbg_info(priv, NULL);
-
- return 0;
-}
-
-void rsnd_adg_remove(struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np = dev->of_node;
-
- rsnd_adg_unregister_clkout(priv);
-
- of_clk_del_provider(np);
-
- rsnd_adg_clk_disable(priv);
-
- /* It should be called after rsnd_adg_clk_disable() */
- rsnd_adg_null_clk_clean(priv);
-}
diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c
deleted file mode 100644
index 329e6ab1b222..000000000000
--- a/sound/soc/sh/rcar/cmd.c
+++ /dev/null
@@ -1,195 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car CMD support
-//
-// Copyright (C) 2015 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-#include "rsnd.h"
-
-struct rsnd_cmd {
- struct rsnd_mod mod;
-};
-
-#define CMD_NAME "cmd"
-
-#define rsnd_cmd_nr(priv) ((priv)->cmd_nr)
-#define for_each_rsnd_cmd(pos, priv, i) \
- for ((i) = 0; \
- ((i) < rsnd_cmd_nr(priv)) && \
- ((pos) = (struct rsnd_cmd *)(priv)->cmd + i); \
- i++)
-
-static int rsnd_cmd_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
- struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- u32 data;
- static const u32 path[] = {
- [1] = 1 << 0,
- [5] = 1 << 8,
- [6] = 1 << 12,
- [9] = 1 << 15,
- };
-
- if (!mix && !dvc)
- return 0;
-
- if (ARRAY_SIZE(path) < rsnd_mod_id(mod) + 1)
- return -ENXIO;
-
- if (mix) {
- struct rsnd_dai *rdai;
- int i;
-
- /*
- * it is assuming that integrater is well understanding about
- * data path. Here doesn't check impossible connection,
- * like src2 + src5
- */
- data = 0;
- for_each_rsnd_dai(rdai, priv, i) {
- struct rsnd_dai_stream *tio = &rdai->playback;
- struct rsnd_mod *src = rsnd_io_to_mod_src(tio);
-
- if (mix == rsnd_io_to_mod_mix(tio))
- data |= path[rsnd_mod_id(src)];
-
- tio = &rdai->capture;
- src = rsnd_io_to_mod_src(tio);
- if (mix == rsnd_io_to_mod_mix(tio))
- data |= path[rsnd_mod_id(src)];
- }
-
- } else {
- struct rsnd_mod *src = rsnd_io_to_mod_src(io);
-
- static const u8 cmd_case[] = {
- [0] = 0x3,
- [1] = 0x3,
- [2] = 0x4,
- [3] = 0x1,
- [4] = 0x2,
- [5] = 0x4,
- [6] = 0x1,
- [9] = 0x2,
- };
-
- if (unlikely(!src))
- return -EIO;
-
- data = path[rsnd_mod_id(src)] |
- cmd_case[rsnd_mod_id(src)] << 16;
- }
-
- dev_dbg(dev, "ctu/mix path = 0x%08x\n", data);
-
- rsnd_mod_write(mod, CMD_ROUTE_SLCT, data);
- rsnd_mod_write(mod, CMD_BUSIF_MODE, rsnd_get_busif_shift(io, mod) | 1);
- rsnd_mod_write(mod, CMD_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
-
- rsnd_adg_set_cmd_timsel_gen2(mod, io);
-
- return 0;
-}
-
-static int rsnd_cmd_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_mod_write(mod, CMD_CTRL, 0x10);
-
- return 0;
-}
-
-static int rsnd_cmd_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_mod_write(mod, CMD_CTRL, 0);
-
- return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_cmd_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0x180 + rsnd_mod_id_raw(mod) * 0x20, 0x30);
-}
-#define DEBUG_INFO .debug_info = rsnd_cmd_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_cmd_ops = {
- .name = CMD_NAME,
- .init = rsnd_cmd_init,
- .start = rsnd_cmd_start,
- .stop = rsnd_cmd_stop,
- .get_status = rsnd_mod_get_status,
- DEBUG_INFO
-};
-
-static struct rsnd_mod *rsnd_cmd_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_cmd_nr(priv)))
- id = 0;
-
- return rsnd_mod_get((struct rsnd_cmd *)(priv->cmd) + id);
-}
-int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct rsnd_mod *mod = rsnd_cmd_mod_get(priv, id);
-
- return rsnd_dai_connect(mod, io, mod->type);
-}
-
-int rsnd_cmd_probe(struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_cmd *cmd;
- int i, nr;
-
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
- /* same number as DVC */
- nr = priv->dvc_nr;
- if (!nr)
- return 0;
-
- cmd = devm_kcalloc(dev, nr, sizeof(*cmd), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
-
- priv->cmd_nr = nr;
- priv->cmd = cmd;
-
- for_each_rsnd_cmd(cmd, priv, i) {
- int ret = rsnd_mod_init(priv, rsnd_mod_get(cmd),
- &rsnd_cmd_ops, NULL,
- RSND_MOD_CMD, i);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-void rsnd_cmd_remove(struct rsnd_priv *priv)
-{
- struct rsnd_cmd *cmd;
- int i;
-
- for_each_rsnd_cmd(cmd, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(cmd));
- }
-}
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
deleted file mode 100644
index 0b1aa23c1189..000000000000
--- a/sound/soc/sh/rcar/core.c
+++ /dev/null
@@ -1,2114 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car SRU/SCU/SSIU/SSI support
-//
-// Copyright (C) 2013 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-//
-// Based on fsi.c
-// Kuninori Morimoto <morimoto.kuninori@renesas.com>
-
-/*
- * Renesas R-Car sound device structure
- *
- * Gen1
- *
- * SRU : Sound Routing Unit
- * - SRC : Sampling Rate Converter
- * - CMD
- * - CTU : Channel Count Conversion Unit
- * - MIX : Mixer
- * - DVC : Digital Volume and Mute Function
- * - SSI : Serial Sound Interface
- *
- * Gen2
- *
- * SCU : Sampling Rate Converter Unit
- * - SRC : Sampling Rate Converter
- * - CMD
- * - CTU : Channel Count Conversion Unit
- * - MIX : Mixer
- * - DVC : Digital Volume and Mute Function
- * SSIU : Serial Sound Interface Unit
- * - SSI : Serial Sound Interface
- */
-
-/*
- * driver data Image
- *
- * rsnd_priv
- * |
- * | ** this depends on Gen1/Gen2
- * |
- * +- gen
- * |
- * | ** these depend on data path
- * | ** gen and platform data control it
- * |
- * +- rdai[0]
- * | | sru ssiu ssi
- * | +- playback -> [mod] -> [mod] -> [mod] -> ...
- * | |
- * | | sru ssiu ssi
- * | +- capture -> [mod] -> [mod] -> [mod] -> ...
- * |
- * +- rdai[1]
- * | | sru ssiu ssi
- * | +- playback -> [mod] -> [mod] -> [mod] -> ...
- * | |
- * | | sru ssiu ssi
- * | +- capture -> [mod] -> [mod] -> [mod] -> ...
- * ...
- * |
- * | ** these control ssi
- * |
- * +- ssi
- * | |
- * | +- ssi[0]
- * | +- ssi[1]
- * | +- ssi[2]
- * | ...
- * |
- * | ** these control src
- * |
- * +- src
- * |
- * +- src[0]
- * +- src[1]
- * +- src[2]
- * ...
- *
- *
- * for_each_rsnd_dai(xx, priv, xx)
- * rdai[0] => rdai[1] => rdai[2] => ...
- *
- * for_each_rsnd_mod(xx, rdai, xx)
- * [mod] => [mod] => [mod] => ...
- *
- * rsnd_dai_call(xxx, fn )
- * [mod]->fn() -> [mod]->fn() -> [mod]->fn()...
- *
- */
-
-#include <linux/pm_runtime.h>
-#include <linux/of_graph.h>
-#include "rsnd.h"
-
-#define RSND_RATES SNDRV_PCM_RATE_8000_192000
-#define RSND_FMTS (SNDRV_PCM_FMTBIT_S8 |\
- SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S24_LE)
-
-static const struct of_device_id rsnd_of_match[] = {
- { .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 },
- { .compatible = "renesas,rcar_sound-gen2", .data = (void *)RSND_GEN2 },
- { .compatible = "renesas,rcar_sound-gen3", .data = (void *)RSND_GEN3 },
- { .compatible = "renesas,rcar_sound-gen4", .data = (void *)RSND_GEN4 },
- /* Special Handling */
- { .compatible = "renesas,rcar_sound-r8a77990", .data = (void *)(RSND_GEN3 | RSND_SOC_E) },
- {},
-};
-MODULE_DEVICE_TABLE(of, rsnd_of_match);
-
-/*
- * rsnd_mod functions
- */
-void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type)
-{
- if (mod->type != type) {
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_warn(dev, "%s is not your expected module\n",
- rsnd_mod_name(mod));
- }
-}
-
-struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- if (!mod || !mod->ops || !mod->ops->dma_req)
- return NULL;
-
- return mod->ops->dma_req(io, mod);
-}
-
-#define MOD_NAME_NUM 5
-#define MOD_NAME_SIZE 16
-char *rsnd_mod_name(struct rsnd_mod *mod)
-{
- static char names[MOD_NAME_NUM][MOD_NAME_SIZE];
- static int num;
- char *name = names[num];
-
- num++;
- if (num >= MOD_NAME_NUM)
- num = 0;
-
- /*
- * Let's use same char to avoid pointlessness memory
- * Thus, rsnd_mod_name() should be used immediately
- * Don't keep pointer
- */
- if ((mod)->ops->id_sub) {
- snprintf(name, MOD_NAME_SIZE, "%s[%d%d]",
- mod->ops->name,
- rsnd_mod_id(mod),
- rsnd_mod_id_sub(mod));
- } else {
- snprintf(name, MOD_NAME_SIZE, "%s[%d]",
- mod->ops->name,
- rsnd_mod_id(mod));
- }
-
- return name;
-}
-
-u32 *rsnd_mod_get_status(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type)
-{
- return &mod->status;
-}
-
-int rsnd_mod_id_raw(struct rsnd_mod *mod)
-{
- return mod->id;
-}
-
-int rsnd_mod_id(struct rsnd_mod *mod)
-{
- if ((mod)->ops->id)
- return (mod)->ops->id(mod);
-
- return rsnd_mod_id_raw(mod);
-}
-
-int rsnd_mod_id_sub(struct rsnd_mod *mod)
-{
- if ((mod)->ops->id_sub)
- return (mod)->ops->id_sub(mod);
-
- return 0;
-}
-
-int rsnd_mod_init(struct rsnd_priv *priv,
- struct rsnd_mod *mod,
- struct rsnd_mod_ops *ops,
- struct clk *clk,
- enum rsnd_mod_type type,
- int id)
-{
- int ret = clk_prepare(clk);
-
- if (ret)
- return ret;
-
- mod->id = id;
- mod->ops = ops;
- mod->type = type;
- mod->clk = clk;
- mod->priv = priv;
-
- return 0;
-}
-
-void rsnd_mod_quit(struct rsnd_mod *mod)
-{
- clk_unprepare(mod->clk);
- mod->clk = NULL;
-}
-
-void rsnd_mod_interrupt(struct rsnd_mod *mod,
- void (*callback)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io))
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dai *rdai;
- int i;
-
- for_each_rsnd_dai(rdai, priv, i) {
- struct rsnd_dai_stream *io = &rdai->playback;
-
- if (mod == io->mod[mod->type])
- callback(mod, io);
-
- io = &rdai->capture;
- if (mod == io->mod[mod->type])
- callback(mod, io);
- }
-}
-
-int rsnd_io_is_working(struct rsnd_dai_stream *io)
-{
- /* see rsnd_dai_stream_init/quit() */
- if (io->substream)
- return snd_pcm_running(io->substream);
-
- return 0;
-}
-
-int rsnd_runtime_channel_original_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
-
- /*
- * params will be added when refine
- * see
- * __rsnd_soc_hw_rule_rate()
- * __rsnd_soc_hw_rule_channels()
- */
- if (params)
- return params_channels(params);
- else if (runtime)
- return runtime->channels;
- return 0;
-}
-
-int rsnd_runtime_channel_after_ctu_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params)
-{
- int chan = rsnd_runtime_channel_original_with_params(io, params);
- struct rsnd_mod *ctu_mod = rsnd_io_to_mod_ctu(io);
-
- if (ctu_mod) {
- u32 converted_chan = rsnd_io_converted_chan(io);
-
- /*
- * !! Note !!
- *
- * converted_chan will be used for CTU,
- * or TDM Split mode.
- * User shouldn't use CTU with TDM Split mode.
- */
- if (rsnd_runtime_is_tdm_split(io)) {
- struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io));
-
- dev_err(dev, "CTU and TDM Split should be used\n");
- }
-
- if (converted_chan)
- return converted_chan;
- }
-
- return chan;
-}
-
-int rsnd_channel_normalization(int chan)
-{
- if (WARN_ON((chan > 8) || (chan < 0)))
- return 0;
-
- /* TDM Extend Mode needs 8ch */
- if (chan == 6)
- chan = 8;
-
- return chan;
-}
-
-int rsnd_runtime_channel_for_ssi_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- int chan = rsnd_io_is_play(io) ?
- rsnd_runtime_channel_after_ctu_with_params(io, params) :
- rsnd_runtime_channel_original_with_params(io, params);
-
- /* Use Multi SSI */
- if (rsnd_runtime_is_multi_ssi(io))
- chan /= rsnd_rdai_ssi_lane_get(rdai);
-
- return rsnd_channel_normalization(chan);
-}
-
-int rsnd_runtime_is_multi_ssi(struct rsnd_dai_stream *io)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- int lane = rsnd_rdai_ssi_lane_get(rdai);
- int chan = rsnd_io_is_play(io) ?
- rsnd_runtime_channel_after_ctu(io) :
- rsnd_runtime_channel_original(io);
-
- return (chan > 2) && (lane > 1);
-}
-
-int rsnd_runtime_is_tdm(struct rsnd_dai_stream *io)
-{
- return rsnd_runtime_channel_for_ssi(io) >= 6;
-}
-
-int rsnd_runtime_is_tdm_split(struct rsnd_dai_stream *io)
-{
- return !!rsnd_flags_has(io, RSND_STREAM_TDM_SPLIT);
-}
-
-/*
- * ADINR function
- */
-u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- switch (snd_pcm_format_width(runtime->format)) {
- case 8:
- return 16 << 16;
- case 16:
- return 8 << 16;
- case 24:
- return 0 << 16;
- }
-
- dev_warn(dev, "not supported sample bits\n");
-
- return 0;
-}
-
-/*
- * DALIGN function
- */
-u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
-{
- static const u32 dalign_values[8] = {
- 0x76543210, 0x00000032, 0x00007654, 0x00000076,
- 0xfedcba98, 0x000000ba, 0x0000fedc, 0x000000fe,
- };
- int id = 0;
- struct rsnd_mod *ssiu = rsnd_io_to_mod_ssiu(io);
- struct rsnd_mod *target;
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- u32 dalign;
-
- /*
- * *Hardware* L/R and *Software* L/R are inverted for 16bit data.
- * 31..16 15...0
- * HW: [L ch] [R ch]
- * SW: [R ch] [L ch]
- * We need to care about inversion timing to control
- * Playback/Capture correctly.
- * The point is [DVC] needs *Hardware* L/R, [MEM] needs *Software* L/R
- *
- * sL/R : software L/R
- * hL/R : hardware L/R
- * (*) : conversion timing
- *
- * Playback
- * sL/R (*) hL/R hL/R hL/R hL/R hL/R
- * [MEM] -> [SRC] -> [DVC] -> [CMD] -> [SSIU] -> [SSI] -> codec
- *
- * Capture
- * hL/R hL/R hL/R hL/R hL/R (*) sL/R
- * codec -> [SSI] -> [SSIU] -> [SRC] -> [DVC] -> [CMD] -> [MEM]
- */
- if (rsnd_io_is_play(io)) {
- struct rsnd_mod *src = rsnd_io_to_mod_src(io);
-
- target = src ? src : ssiu;
- } else {
- struct rsnd_mod *cmd = rsnd_io_to_mod_cmd(io);
-
- target = cmd ? cmd : ssiu;
- }
-
- if (mod == ssiu)
- id = rsnd_mod_id_sub(mod);
-
- dalign = dalign_values[id];
-
- if (mod == target && snd_pcm_format_width(runtime->format) == 16) {
- /* Target mod needs inverted DALIGN when 16bit */
- dalign = (dalign & 0xf0f0f0f0) >> 4 |
- (dalign & 0x0f0f0f0f) << 4;
- }
-
- return dalign;
-}
-
-u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod)
-{
- static const enum rsnd_mod_type playback_mods[] = {
- RSND_MOD_SRC,
- RSND_MOD_CMD,
- RSND_MOD_SSIU,
- };
- static const enum rsnd_mod_type capture_mods[] = {
- RSND_MOD_CMD,
- RSND_MOD_SRC,
- RSND_MOD_SSIU,
- };
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_mod *tmod = NULL;
- const enum rsnd_mod_type *mods =
- rsnd_io_is_play(io) ?
- playback_mods : capture_mods;
- int i;
-
- /*
- * This is needed for 24bit data
- * We need to shift 8bit
- *
- * Linux 24bit data is located as 0x00******
- * HW 24bit data is located as 0x******00
- *
- */
- if (snd_pcm_format_width(runtime->format) != 24)
- return 0;
-
- for (i = 0; i < ARRAY_SIZE(playback_mods); i++) {
- tmod = rsnd_io_to_mod(io, mods[i]);
- if (tmod)
- break;
- }
-
- if (tmod != mod)
- return 0;
-
- if (rsnd_io_is_play(io))
- return (0 << 20) | /* shift to Left */
- (8 << 16); /* 8bit */
- else
- return (1 << 20) | /* shift to Right */
- (8 << 16); /* 8bit */
-}
-
-/*
- * rsnd_dai functions
- */
-struct rsnd_mod *rsnd_mod_next(int *iterator,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type *array,
- int array_size)
-{
- int max = array ? array_size : RSND_MOD_MAX;
-
- for (; *iterator < max; (*iterator)++) {
- enum rsnd_mod_type type = (array) ? array[*iterator] : *iterator;
- struct rsnd_mod *mod = rsnd_io_to_mod(io, type);
-
- if (mod)
- return mod;
- }
-
- return NULL;
-}
-
-static enum rsnd_mod_type rsnd_mod_sequence[][RSND_MOD_MAX] = {
- {
- /* CAPTURE */
- RSND_MOD_AUDMAPP,
- RSND_MOD_AUDMA,
- RSND_MOD_DVC,
- RSND_MOD_MIX,
- RSND_MOD_CTU,
- RSND_MOD_CMD,
- RSND_MOD_SRC,
- RSND_MOD_SSIU,
- RSND_MOD_SSIM3,
- RSND_MOD_SSIM2,
- RSND_MOD_SSIM1,
- RSND_MOD_SSIP,
- RSND_MOD_SSI,
- }, {
- /* PLAYBACK */
- RSND_MOD_AUDMAPP,
- RSND_MOD_AUDMA,
- RSND_MOD_SSIM3,
- RSND_MOD_SSIM2,
- RSND_MOD_SSIM1,
- RSND_MOD_SSIP,
- RSND_MOD_SSI,
- RSND_MOD_SSIU,
- RSND_MOD_DVC,
- RSND_MOD_MIX,
- RSND_MOD_CTU,
- RSND_MOD_CMD,
- RSND_MOD_SRC,
- },
-};
-
-static int rsnd_status_update(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod, enum rsnd_mod_type type,
- int shift, int add, int timing)
-{
- u32 *status = mod->ops->get_status(mod, io, type);
- u32 mask = 0xF << shift;
- u8 val = (*status >> shift) & 0xF;
- u8 next_val = (val + add) & 0xF;
- int func_call = (val == timing);
-
- /* no status update */
- if (add == 0 || shift == 28)
- return 1;
-
- if (next_val == 0xF) /* underflow case */
- func_call = -1;
- else
- *status = (*status & ~mask) + (next_val << shift);
-
- return func_call;
-}
-
-#define rsnd_dai_call(fn, io, param...) \
-({ \
- struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io)); \
- struct rsnd_mod *mod; \
- int is_play = rsnd_io_is_play(io); \
- int ret = 0, i; \
- enum rsnd_mod_type *types = rsnd_mod_sequence[is_play]; \
- for_each_rsnd_mod_arrays(i, mod, io, types, RSND_MOD_MAX) { \
- int tmp = 0; \
- int func_call = rsnd_status_update(io, mod, types[i], \
- __rsnd_mod_shift_##fn, \
- __rsnd_mod_add_##fn, \
- __rsnd_mod_call_##fn); \
- if (func_call > 0 && (mod)->ops->fn) \
- tmp = (mod)->ops->fn(mod, io, param); \
- if (unlikely(func_call < 0) || \
- unlikely(tmp && (tmp != -EPROBE_DEFER))) \
- dev_err(dev, "%s : %s error (%d, %d)\n", \
- rsnd_mod_name(mod), #fn, tmp, func_call);\
- ret |= tmp; \
- } \
- ret; \
-})
-
-int rsnd_dai_connect(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type)
-{
- struct rsnd_priv *priv;
- struct device *dev;
-
- if (!mod)
- return -EIO;
-
- if (io->mod[type] == mod)
- return 0;
-
- if (io->mod[type])
- return -EINVAL;
-
- priv = rsnd_mod_to_priv(mod);
- dev = rsnd_priv_to_dev(priv);
-
- io->mod[type] = mod;
-
- dev_dbg(dev, "%s is connected to io (%s)\n",
- rsnd_mod_name(mod),
- rsnd_io_is_play(io) ? "Playback" : "Capture");
-
- return 0;
-}
-
-static void rsnd_dai_disconnect(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type)
-{
- io->mod[type] = NULL;
-}
-
-int rsnd_rdai_channels_ctrl(struct rsnd_dai *rdai,
- int max_channels)
-{
- if (max_channels > 0)
- rdai->max_channels = max_channels;
-
- return rdai->max_channels;
-}
-
-int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai,
- int ssi_lane)
-{
- if (ssi_lane > 0)
- rdai->ssi_lane = ssi_lane;
-
- return rdai->ssi_lane;
-}
-
-int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width)
-{
- if (width > 0)
- rdai->chan_width = width;
-
- return rdai->chan_width;
-}
-
-struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id)
-{
- if ((id < 0) || (id >= rsnd_rdai_nr(priv)))
- return NULL;
-
- return priv->rdai + id;
-}
-
-static struct snd_soc_dai_driver
-*rsnd_daidrv_get(struct rsnd_priv *priv, int id)
-{
- if ((id < 0) || (id >= rsnd_rdai_nr(priv)))
- return NULL;
-
- return priv->daidrv + id;
-}
-
-#define rsnd_dai_to_priv(dai) snd_soc_dai_get_drvdata(dai)
-static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai)
-{
- struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
-
- return rsnd_rdai_get(priv, dai->id);
-}
-
-/*
- * rsnd_soc_dai functions
- */
-void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io)
-{
- struct snd_pcm_substream *substream = io->substream;
-
- /*
- * this function should be called...
- *
- * - if rsnd_dai_pointer_update() returns true
- * - without spin lock
- */
-
- snd_pcm_period_elapsed(substream);
-}
-
-static void rsnd_dai_stream_init(struct rsnd_dai_stream *io,
- struct snd_pcm_substream *substream)
-{
- io->substream = substream;
-}
-
-static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io)
-{
- io->substream = NULL;
-}
-
-static
-struct snd_soc_dai *rsnd_substream_to_dai(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
-
- return snd_soc_rtd_to_cpu(rtd, 0);
-}
-
-static
-struct rsnd_dai_stream *rsnd_rdai_to_io(struct rsnd_dai *rdai,
- struct snd_pcm_substream *substream)
-{
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- return &rdai->playback;
- else
- return &rdai->capture;
-}
-
-static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- ret = rsnd_dai_call(init, io, priv);
- if (ret < 0)
- goto dai_trigger_end;
-
- ret = rsnd_dai_call(start, io, priv);
- if (ret < 0)
- goto dai_trigger_end;
-
- ret = rsnd_dai_call(irq, io, priv, 1);
- if (ret < 0)
- goto dai_trigger_end;
-
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- ret = rsnd_dai_call(irq, io, priv, 0);
-
- ret |= rsnd_dai_call(stop, io, priv);
-
- ret |= rsnd_dai_call(quit, io, priv);
-
- break;
- default:
- ret = -EINVAL;
- }
-
-dai_trigger_end:
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return ret;
-}
-
-static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
-
- /* set clock master for audio interface */
- switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
- case SND_SOC_DAIFMT_BC_FC:
- rdai->clk_master = 0;
- break;
- case SND_SOC_DAIFMT_BP_FP:
- rdai->clk_master = 1; /* cpu is master */
- break;
- default:
- return -EINVAL;
- }
-
- /* set format */
- rdai->bit_clk_inv = 0;
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- rdai->sys_delay = 0;
- rdai->data_alignment = 0;
- rdai->frm_clk_inv = 0;
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- case SND_SOC_DAIFMT_DSP_B:
- rdai->sys_delay = 1;
- rdai->data_alignment = 0;
- rdai->frm_clk_inv = 1;
- break;
- case SND_SOC_DAIFMT_RIGHT_J:
- rdai->sys_delay = 1;
- rdai->data_alignment = 1;
- rdai->frm_clk_inv = 1;
- break;
- case SND_SOC_DAIFMT_DSP_A:
- rdai->sys_delay = 0;
- rdai->data_alignment = 0;
- rdai->frm_clk_inv = 1;
- break;
- }
-
- /* set clock inversion */
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_IF:
- rdai->frm_clk_inv = !rdai->frm_clk_inv;
- break;
- case SND_SOC_DAIFMT_IB_NF:
- rdai->bit_clk_inv = !rdai->bit_clk_inv;
- break;
- case SND_SOC_DAIFMT_IB_IF:
- rdai->bit_clk_inv = !rdai->bit_clk_inv;
- rdai->frm_clk_inv = !rdai->frm_clk_inv;
- break;
- case SND_SOC_DAIFMT_NB_NF:
- default:
- break;
- }
-
- return 0;
-}
-
-static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
- u32 tx_mask, u32 rx_mask,
- int slots, int slot_width)
-{
- struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- switch (slot_width) {
- case 16:
- case 24:
- case 32:
- break;
- default:
- /* use default */
- /*
- * Indicate warning if DT has "dai-tdm-slot-width"
- * but the value was not expected.
- */
- if (slot_width)
- dev_warn(dev, "unsupported TDM slot width (%d), force to use default 32\n",
- slot_width);
- slot_width = 32;
- }
-
- switch (slots) {
- case 2:
- /* TDM Split Mode */
- case 6:
- case 8:
- /* TDM Extend Mode */
- rsnd_rdai_channels_set(rdai, slots);
- rsnd_rdai_ssi_lane_set(rdai, 1);
- rsnd_rdai_width_set(rdai, slot_width);
- break;
- default:
- dev_err(dev, "unsupported TDM slots (%d)\n", slots);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static unsigned int rsnd_soc_hw_channels_list[] = {
- 2, 6, 8,
-};
-
-static unsigned int rsnd_soc_hw_rate_list[] = {
- 8000,
- 11025,
- 16000,
- 22050,
- 32000,
- 44100,
- 48000,
- 64000,
- 88200,
- 96000,
- 176400,
- 192000,
-};
-
-static int rsnd_soc_hw_rule(struct rsnd_dai *rdai,
- unsigned int *list, int list_num,
- struct snd_interval *baseline, struct snd_interval *iv,
- struct rsnd_dai_stream *io, char *unit)
-{
- struct snd_interval p;
- unsigned int rate;
- int i;
-
- snd_interval_any(&p);
- p.min = UINT_MAX;
- p.max = 0;
-
- for (i = 0; i < list_num; i++) {
-
- if (!snd_interval_test(iv, list[i]))
- continue;
-
- rate = rsnd_ssi_clk_query(rdai,
- baseline->min, list[i], NULL);
- if (rate > 0) {
- p.min = min(p.min, list[i]);
- p.max = max(p.max, list[i]);
- }
-
- rate = rsnd_ssi_clk_query(rdai,
- baseline->max, list[i], NULL);
- if (rate > 0) {
- p.min = min(p.min, list[i]);
- p.max = max(p.max, list[i]);
- }
- }
-
- /* Indicate error once if it can't handle */
- if (!rsnd_flags_has(io, RSND_HW_RULE_ERR) && (p.min > p.max)) {
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_warn(dev, "It can't handle %d %s <-> %d %s\n",
- baseline->min, unit, baseline->max, unit);
- rsnd_flags_set(io, RSND_HW_RULE_ERR);
- }
-
- return snd_interval_refine(iv, &p);
-}
-
-static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
- struct snd_interval ic;
- struct rsnd_dai_stream *io = rule->private;
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
-
- /*
- * possible sampling rate limitation is same as
- * 2ch if it supports multi ssi
- * and same as 8ch if TDM 6ch (see rsnd_ssi_config_init())
- */
- ic = *ic_;
- ic.min =
- ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params);
-
- return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_rate_list,
- ARRAY_SIZE(rsnd_soc_hw_rate_list),
- &ic, ir, io, "ch");
-}
-
-static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
- struct snd_interval ic;
- struct rsnd_dai_stream *io = rule->private;
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
-
- /*
- * possible sampling rate limitation is same as
- * 2ch if it supports multi ssi
- * and same as 8ch if TDM 6ch (see rsnd_ssi_config_init())
- */
- ic = *ic_;
- ic.min =
- ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params);
-
- return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_channels_list,
- ARRAY_SIZE(rsnd_soc_hw_channels_list),
- ir, &ic, io, "Hz");
-}
-
-static const struct snd_pcm_hardware rsnd_pcm_hardware = {
- .info = SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID,
- .buffer_bytes_max = 64 * 1024,
- .period_bytes_min = 32,
- .period_bytes_max = 8192,
- .periods_min = 1,
- .periods_max = 32,
- .fifo_size = 256,
-};
-
-static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- struct snd_pcm_hw_constraint_list *constraint = &rdai->constraint;
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned int max_channels = rsnd_rdai_channels_get(rdai);
- int i;
-
- rsnd_flags_del(io, RSND_HW_RULE_ERR);
-
- rsnd_dai_stream_init(io, substream);
-
- /*
- * Channel Limitation
- * It depends on Platform design
- */
- constraint->list = rsnd_soc_hw_channels_list;
- constraint->count = 0;
- constraint->mask = 0;
-
- for (i = 0; i < ARRAY_SIZE(rsnd_soc_hw_channels_list); i++) {
- if (rsnd_soc_hw_channels_list[i] > max_channels)
- break;
- constraint->count = i + 1;
- }
-
- snd_soc_set_runtime_hwparams(substream, &rsnd_pcm_hardware);
-
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS, constraint);
-
- snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
-
- /*
- * Sampling Rate / Channel Limitation
- * It depends on Clock Master Mode
- */
- if (rsnd_rdai_is_clk_master(rdai)) {
- int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-
- snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- rsnd_soc_hw_rule_rate,
- is_play ? &rdai->playback : &rdai->capture,
- SNDRV_PCM_HW_PARAM_CHANNELS, -1);
- snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
- rsnd_soc_hw_rule_channels,
- is_play ? &rdai->playback : &rdai->capture,
- SNDRV_PCM_HW_PARAM_RATE, -1);
- }
-
- return 0;
-}
-
-static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
-
- /*
- * call rsnd_dai_call without spinlock
- */
- rsnd_dai_call(cleanup, io, priv);
-
- rsnd_dai_stream_quit(io);
-}
-
-static int rsnd_soc_dai_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
-
- return rsnd_dai_call(prepare, io, priv);
-}
-
-static u64 rsnd_soc_dai_formats[] = {
- /*
- * 1st Priority
- *
- * Well tested formats.
- * Select below from Sound Card, not auto
- * SND_SOC_DAIFMT_CBC_CFC
- * SND_SOC_DAIFMT_CBP_CFP
- */
- SND_SOC_POSSIBLE_DAIFMT_I2S |
- SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
- SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
- SND_SOC_POSSIBLE_DAIFMT_NB_NF |
- SND_SOC_POSSIBLE_DAIFMT_NB_IF |
- SND_SOC_POSSIBLE_DAIFMT_IB_NF |
- SND_SOC_POSSIBLE_DAIFMT_IB_IF,
- /*
- * 2nd Priority
- *
- * Supported, but not well tested
- */
- SND_SOC_POSSIBLE_DAIFMT_DSP_A |
- SND_SOC_POSSIBLE_DAIFMT_DSP_B,
-};
-
-static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- struct device_node *dai_np)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *ssiu_np = rsnd_ssiu_of_node(priv);
- struct device_node *np;
- int is_play = rsnd_io_is_play(io);
- int i;
-
- if (!ssiu_np)
- return;
-
- /*
- * This driver assumes that it is TDM Split mode
- * if it includes ssiu node
- */
- for (i = 0;; i++) {
- struct device_node *node = is_play ?
- of_parse_phandle(dai_np, "playback", i) :
- of_parse_phandle(dai_np, "capture", i);
-
- if (!node)
- break;
-
- for_each_child_of_node(ssiu_np, np) {
- if (np == node) {
- rsnd_flags_set(io, RSND_STREAM_TDM_SPLIT);
- dev_dbg(dev, "%s is part of TDM Split\n", io->name);
- }
- }
-
- of_node_put(node);
- }
-
- of_node_put(ssiu_np);
-}
-
-static void rsnd_parse_connect_simple(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- struct device_node *dai_np)
-{
- if (!rsnd_io_to_mod_ssi(io))
- return;
-
- rsnd_parse_tdm_split_mode(priv, io, dai_np);
-}
-
-static void rsnd_parse_connect_graph(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- struct device_node *endpoint)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *remote_node;
-
- if (!rsnd_io_to_mod_ssi(io))
- return;
-
- remote_node = of_graph_get_remote_port_parent(endpoint);
-
- /* HDMI0 */
- if (strstr(remote_node->full_name, "hdmi@fead0000")) {
- rsnd_flags_set(io, RSND_STREAM_HDMI0);
- dev_dbg(dev, "%s connected to HDMI0\n", io->name);
- }
-
- /* HDMI1 */
- if (strstr(remote_node->full_name, "hdmi@feae0000")) {
- rsnd_flags_set(io, RSND_STREAM_HDMI1);
- dev_dbg(dev, "%s connected to HDMI1\n", io->name);
- }
-
- rsnd_parse_tdm_split_mode(priv, io, endpoint);
-
- of_node_put(remote_node);
-}
-
-void rsnd_parse_connect_common(struct rsnd_dai *rdai, char *name,
- struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id),
- struct device_node *node,
- struct device_node *playback,
- struct device_node *capture)
-{
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np;
- int i;
-
- if (!node)
- return;
-
- i = 0;
- for_each_child_of_node(node, np) {
- struct rsnd_mod *mod;
-
- i = rsnd_node_fixed_index(dev, np, name, i);
- if (i < 0) {
- of_node_put(np);
- break;
- }
-
- mod = mod_get(priv, i);
-
- if (np == playback)
- rsnd_dai_connect(mod, &rdai->playback, mod->type);
- if (np == capture)
- rsnd_dai_connect(mod, &rdai->capture, mod->type);
- i++;
- }
-
- of_node_put(node);
-}
-
-int rsnd_node_fixed_index(struct device *dev, struct device_node *node, char *name, int idx)
-{
- char node_name[16];
-
- /*
- * rsnd is assuming each device nodes are sequential numbering,
- * but some of them are not.
- * This function adjusts index for it.
- *
- * ex)
- * Normal case, special case
- * ssi-0
- * ssi-1
- * ssi-2
- * ssi-3 ssi-3
- * ssi-4 ssi-4
- * ...
- *
- * assume Max 64 node
- */
- for (; idx < 64; idx++) {
- snprintf(node_name, sizeof(node_name), "%s-%d", name, idx);
-
- if (strncmp(node_name, of_node_full_name(node), sizeof(node_name)) == 0)
- return idx;
- }
-
- dev_err(dev, "strange node numbering (%s)",
- of_node_full_name(node));
- return -EINVAL;
-}
-
-int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np;
- int i;
-
- i = 0;
- for_each_child_of_node(node, np) {
- i = rsnd_node_fixed_index(dev, np, name, i);
- if (i < 0) {
- of_node_put(np);
- return 0;
- }
- i++;
- }
-
- return i;
-}
-
-static int rsnd_dai_of_node(struct rsnd_priv *priv, int *is_graph)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np = dev->of_node;
- struct device_node *ports, *node;
- int nr = 0;
- int i = 0;
-
- *is_graph = 0;
-
- /*
- * parse both previous dai (= rcar_sound,dai), and
- * graph dai (= ports/port)
- */
-
- /*
- * Simple-Card
- */
- node = of_get_child_by_name(np, RSND_NODE_DAI);
- if (!node)
- goto audio_graph;
-
- of_node_put(node);
-
- for_each_child_of_node(np, node) {
- if (!of_node_name_eq(node, RSND_NODE_DAI))
- continue;
-
- priv->component_dais[i] = of_get_child_count(node);
- nr += priv->component_dais[i];
- i++;
- if (i >= RSND_MAX_COMPONENT) {
- dev_info(dev, "reach to max component\n");
- of_node_put(node);
- break;
- }
- }
-
- return nr;
-
-audio_graph:
- /*
- * Audio-Graph-Card
- */
- for_each_child_of_node(np, ports) {
- if (!of_node_name_eq(ports, "ports") &&
- !of_node_name_eq(ports, "port"))
- continue;
- priv->component_dais[i] = of_graph_get_endpoint_count(ports);
- nr += priv->component_dais[i];
- i++;
- if (i >= RSND_MAX_COMPONENT) {
- dev_info(dev, "reach to max component\n");
- of_node_put(ports);
- break;
- }
- }
-
- *is_graph = 1;
-
- return nr;
-}
-
-
-#define PREALLOC_BUFFER (32 * 1024)
-#define PREALLOC_BUFFER_MAX (32 * 1024)
-
-static int rsnd_preallocate_pages(struct snd_soc_pcm_runtime *rtd,
- struct rsnd_dai_stream *io,
- int stream)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct snd_pcm_substream *substream;
-
- /*
- * use Audio-DMAC dev if we can use IPMMU
- * see
- * rsnd_dmaen_attach()
- */
- if (io->dmac_dev)
- dev = io->dmac_dev;
-
- for (substream = rtd->pcm->streams[stream].substream;
- substream;
- substream = substream->next) {
- snd_pcm_set_managed_buffer(substream,
- SNDRV_DMA_TYPE_DEV,
- dev,
- PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
- }
-
- return 0;
-}
-
-static int rsnd_soc_dai_pcm_new(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
-{
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- int ret;
-
- ret = rsnd_dai_call(pcm_new, &rdai->playback, rtd);
- if (ret)
- return ret;
-
- ret = rsnd_dai_call(pcm_new, &rdai->capture, rtd);
- if (ret)
- return ret;
-
- ret = rsnd_preallocate_pages(rtd, &rdai->playback,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- return ret;
-
- ret = rsnd_preallocate_pages(rtd, &rdai->capture,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
- .pcm_new = rsnd_soc_dai_pcm_new,
- .startup = rsnd_soc_dai_startup,
- .shutdown = rsnd_soc_dai_shutdown,
- .trigger = rsnd_soc_dai_trigger,
- .set_fmt = rsnd_soc_dai_set_fmt,
- .set_tdm_slot = rsnd_soc_set_dai_tdm_slot,
- .prepare = rsnd_soc_dai_prepare,
- .auto_selectable_formats = rsnd_soc_dai_formats,
- .num_auto_selectable_formats = ARRAY_SIZE(rsnd_soc_dai_formats),
-};
-
-static void __rsnd_dai_probe(struct rsnd_priv *priv,
- struct device_node *dai_np,
- struct device_node *node_np,
- uint32_t node_arg,
- int dai_i)
-{
- struct rsnd_dai_stream *io_playback;
- struct rsnd_dai_stream *io_capture;
- struct snd_soc_dai_driver *drv;
- struct rsnd_dai *rdai;
- struct device *dev = rsnd_priv_to_dev(priv);
- int playback_exist = 0, capture_exist = 0;
- int io_i;
-
- rdai = rsnd_rdai_get(priv, dai_i);
- drv = rsnd_daidrv_get(priv, dai_i);
- io_playback = &rdai->playback;
- io_capture = &rdai->capture;
-
- snprintf(rdai->name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", dai_i);
-
- /* for multi Component */
- rdai->dai_args.np = node_np;
- rdai->dai_args.args_count = 1;
- rdai->dai_args.args[0] = node_arg;
-
- rdai->priv = priv;
- drv->name = rdai->name;
- drv->ops = &rsnd_soc_dai_ops;
- drv->id = dai_i;
- drv->dai_args = &rdai->dai_args;
-
- io_playback->rdai = rdai;
- io_capture->rdai = rdai;
- rsnd_rdai_channels_set(rdai, 2); /* default 2ch */
- rsnd_rdai_ssi_lane_set(rdai, 1); /* default 1lane */
- rsnd_rdai_width_set(rdai, 32); /* default 32bit width */
-
- for (io_i = 0;; io_i++) {
- struct device_node *playback = of_parse_phandle(dai_np, "playback", io_i);
- struct device_node *capture = of_parse_phandle(dai_np, "capture", io_i);
-
- if (!playback && !capture)
- break;
-
- if (io_i == 0) {
- /* check whether playback/capture property exists */
- if (playback)
- playback_exist = 1;
- if (capture)
- capture_exist = 1;
- }
-
- rsnd_parse_connect_ssi(rdai, playback, capture);
- rsnd_parse_connect_ssiu(rdai, playback, capture);
- rsnd_parse_connect_src(rdai, playback, capture);
- rsnd_parse_connect_ctu(rdai, playback, capture);
- rsnd_parse_connect_mix(rdai, playback, capture);
- rsnd_parse_connect_dvc(rdai, playback, capture);
-
- of_node_put(playback);
- of_node_put(capture);
- }
-
- if (playback_exist) {
- snprintf(io_playback->name, RSND_DAI_NAME_SIZE, "DAI%d Playback", dai_i);
- drv->playback.rates = RSND_RATES;
- drv->playback.formats = RSND_FMTS;
- drv->playback.channels_min = 2;
- drv->playback.channels_max = 8;
- drv->playback.stream_name = io_playback->name;
- }
- if (capture_exist) {
- snprintf(io_capture->name, RSND_DAI_NAME_SIZE, "DAI%d Capture", dai_i);
- drv->capture.rates = RSND_RATES;
- drv->capture.formats = RSND_FMTS;
- drv->capture.channels_min = 2;
- drv->capture.channels_max = 8;
- drv->capture.stream_name = io_capture->name;
- }
-
- if (rsnd_ssi_is_pin_sharing(io_capture) ||
- rsnd_ssi_is_pin_sharing(io_playback)) {
- /* should have symmetric_rate if pin sharing */
- drv->symmetric_rate = 1;
- }
-
- dev_dbg(dev, "%s (%s/%s)\n", rdai->name,
- rsnd_io_to_mod_ssi(io_playback) ? "play" : " -- ",
- rsnd_io_to_mod_ssi(io_capture) ? "capture" : " -- ");
-}
-
-static int rsnd_dai_probe(struct rsnd_priv *priv)
-{
- struct snd_soc_dai_driver *rdrv;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np = dev->of_node;
- struct rsnd_dai *rdai;
- int nr = 0;
- int is_graph;
- int dai_i;
-
- nr = rsnd_dai_of_node(priv, &is_graph);
- if (!nr)
- return -EINVAL;
-
- rdrv = devm_kcalloc(dev, nr, sizeof(*rdrv), GFP_KERNEL);
- rdai = devm_kcalloc(dev, nr, sizeof(*rdai), GFP_KERNEL);
- if (!rdrv || !rdai)
- return -ENOMEM;
-
- priv->rdai_nr = nr;
- priv->daidrv = rdrv;
- priv->rdai = rdai;
-
- /*
- * parse all dai
- */
- dai_i = 0;
- if (is_graph) {
- struct device_node *ports;
- struct device_node *dai_np;
-
- for_each_child_of_node(np, ports) {
- if (!of_node_name_eq(ports, "ports") &&
- !of_node_name_eq(ports, "port"))
- continue;
- for_each_endpoint_of_node(ports, dai_np) {
- __rsnd_dai_probe(priv, dai_np, dai_np, 0, dai_i);
- if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
- rdai = rsnd_rdai_get(priv, dai_i);
-
- rsnd_parse_connect_graph(priv, &rdai->playback, dai_np);
- rsnd_parse_connect_graph(priv, &rdai->capture, dai_np);
- }
- dai_i++;
- }
- }
- } else {
- struct device_node *node;
- struct device_node *dai_np;
-
- for_each_child_of_node(np, node) {
- if (!of_node_name_eq(node, RSND_NODE_DAI))
- continue;
-
- for_each_child_of_node(node, dai_np) {
- __rsnd_dai_probe(priv, dai_np, np, dai_i, dai_i);
- if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
- rdai = rsnd_rdai_get(priv, dai_i);
-
- rsnd_parse_connect_simple(priv, &rdai->playback, dai_np);
- rsnd_parse_connect_simple(priv, &rdai->capture, dai_np);
- }
- dai_i++;
- }
- }
- }
-
- return 0;
-}
-
-/*
- * pcm ops
- */
-static int rsnd_hw_update(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&priv->lock, flags);
- if (hw_params)
- ret = rsnd_dai_call(hw_params, io, substream, hw_params);
- else
- ret = rsnd_dai_call(hw_free, io, substream);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return ret;
-}
-
-static int rsnd_hw_params(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- struct snd_soc_pcm_runtime *fe = snd_soc_substream_to_rtd(substream);
-
- /*
- * rsnd assumes that it might be used under DPCM if user want to use
- * channel / rate convert. Then, rsnd should be FE.
- * And then, this function will be called *after* BE settings.
- * this means, each BE already has fixuped hw_params.
- * see
- * dpcm_fe_dai_hw_params()
- * dpcm_be_dai_hw_params()
- */
- io->converted_rate = 0;
- io->converted_chan = 0;
- if (fe->dai_link->dynamic) {
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct snd_soc_dpcm *dpcm;
- int stream = substream->stream;
-
- for_each_dpcm_be(fe, stream, dpcm) {
- struct snd_soc_pcm_runtime *be = dpcm->be;
- struct snd_pcm_hw_params *be_params = &be->dpcm[stream].hw_params;
-
- if (params_channels(hw_params) != params_channels(be_params))
- io->converted_chan = params_channels(be_params);
- if (params_rate(hw_params) != params_rate(be_params))
- io->converted_rate = params_rate(be_params);
- }
- if (io->converted_chan)
- dev_dbg(dev, "convert channels = %d\n", io->converted_chan);
- if (io->converted_rate) {
- /*
- * SRC supports convert rates from params_rate(hw_params)/k_down
- * to params_rate(hw_params)*k_up, where k_up is always 6, and
- * k_down depends on number of channels and SRC unit.
- * So all SRC units can upsample audio up to 6 times regardless
- * its number of channels. And all SRC units can downsample
- * 2 channel audio up to 6 times too.
- */
- int k_up = 6;
- int k_down = 6;
- int channel;
- struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
-
- dev_dbg(dev, "convert rate = %d\n", io->converted_rate);
-
- channel = io->converted_chan ? io->converted_chan :
- params_channels(hw_params);
-
- switch (rsnd_mod_id(src_mod)) {
- /*
- * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times.
- * SRC1, SRC3 and SRC4 can downsample 4 channel audio
- * up to 4 times.
- * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio
- * no more than twice.
- */
- case 1:
- case 3:
- case 4:
- if (channel > 4) {
- k_down = 2;
- break;
- }
- fallthrough;
- case 0:
- if (channel > 2)
- k_down = 4;
- break;
-
- /* Other SRC units do not support more than 2 channels */
- default:
- if (channel > 2)
- return -EINVAL;
- }
-
- if (params_rate(hw_params) > io->converted_rate * k_down) {
- hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
- io->converted_rate * k_down;
- hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
- io->converted_rate * k_down;
- hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
- } else if (params_rate(hw_params) * k_up < io->converted_rate) {
- hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
- DIV_ROUND_UP(io->converted_rate, k_up);
- hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
- DIV_ROUND_UP(io->converted_rate, k_up);
- hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
- }
-
- /*
- * TBD: Max SRC input and output rates also depend on number
- * of channels and SRC unit:
- * SRC1, SRC3 and SRC4 do not support more than 128kHz
- * for 6 channel and 96kHz for 8 channel audio.
- * Perhaps this function should return EINVAL if the input or
- * the output rate exceeds the limitation.
- */
- }
- }
-
- return rsnd_hw_update(substream, hw_params);
-}
-
-static int rsnd_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- return rsnd_hw_update(substream, NULL);
-}
-
-static snd_pcm_uframes_t rsnd_pointer(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- snd_pcm_uframes_t pointer = 0;
-
- rsnd_dai_call(pointer, io, &pointer);
-
- return pointer;
-}
-
-/*
- * snd_kcontrol
- */
-static int rsnd_kctrl_info(struct snd_kcontrol *kctrl,
- struct snd_ctl_elem_info *uinfo)
-{
- struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
-
- if (cfg->texts) {
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = cfg->size;
- uinfo->value.enumerated.items = cfg->max;
- if (uinfo->value.enumerated.item >= cfg->max)
- uinfo->value.enumerated.item = cfg->max - 1;
- strscpy(uinfo->value.enumerated.name,
- cfg->texts[uinfo->value.enumerated.item],
- sizeof(uinfo->value.enumerated.name));
- } else {
- uinfo->count = cfg->size;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = cfg->max;
- uinfo->type = (cfg->max == 1) ?
- SNDRV_CTL_ELEM_TYPE_BOOLEAN :
- SNDRV_CTL_ELEM_TYPE_INTEGER;
- }
-
- return 0;
-}
-
-static int rsnd_kctrl_get(struct snd_kcontrol *kctrl,
- struct snd_ctl_elem_value *uc)
-{
- struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
- int i;
-
- for (i = 0; i < cfg->size; i++)
- if (cfg->texts)
- uc->value.enumerated.item[i] = cfg->val[i];
- else
- uc->value.integer.value[i] = cfg->val[i];
-
- return 0;
-}
-
-static int rsnd_kctrl_put(struct snd_kcontrol *kctrl,
- struct snd_ctl_elem_value *uc)
-{
- struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
- int i, change = 0;
-
- if (!cfg->accept(cfg->io))
- return 0;
-
- for (i = 0; i < cfg->size; i++) {
- if (cfg->texts) {
- change |= (uc->value.enumerated.item[i] != cfg->val[i]);
- cfg->val[i] = uc->value.enumerated.item[i];
- } else {
- change |= (uc->value.integer.value[i] != cfg->val[i]);
- cfg->val[i] = uc->value.integer.value[i];
- }
- }
-
- if (change && cfg->update)
- cfg->update(cfg->io, cfg->mod);
-
- return change;
-}
-
-int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io)
-{
- return 1;
-}
-
-int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- if (!runtime) {
- dev_warn(dev, "Can't update kctrl when idle\n");
- return 0;
- }
-
- return 1;
-}
-
-struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg)
-{
- cfg->cfg.val = cfg->val;
-
- return &cfg->cfg;
-}
-
-struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg)
-{
- cfg->cfg.val = &cfg->val;
-
- return &cfg->cfg;
-}
-
-const char * const volume_ramp_rate[] = {
- "128 dB/1 step", /* 00000 */
- "64 dB/1 step", /* 00001 */
- "32 dB/1 step", /* 00010 */
- "16 dB/1 step", /* 00011 */
- "8 dB/1 step", /* 00100 */
- "4 dB/1 step", /* 00101 */
- "2 dB/1 step", /* 00110 */
- "1 dB/1 step", /* 00111 */
- "0.5 dB/1 step", /* 01000 */
- "0.25 dB/1 step", /* 01001 */
- "0.125 dB/1 step", /* 01010 = VOLUME_RAMP_MAX_MIX */
- "0.125 dB/2 steps", /* 01011 */
- "0.125 dB/4 steps", /* 01100 */
- "0.125 dB/8 steps", /* 01101 */
- "0.125 dB/16 steps", /* 01110 */
- "0.125 dB/32 steps", /* 01111 */
- "0.125 dB/64 steps", /* 10000 */
- "0.125 dB/128 steps", /* 10001 */
- "0.125 dB/256 steps", /* 10010 */
- "0.125 dB/512 steps", /* 10011 */
- "0.125 dB/1024 steps", /* 10100 */
- "0.125 dB/2048 steps", /* 10101 */
- "0.125 dB/4096 steps", /* 10110 */
- "0.125 dB/8192 steps", /* 10111 = VOLUME_RAMP_MAX_DVC */
-};
-
-int rsnd_kctrl_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd,
- const unsigned char *name,
- int (*accept)(struct rsnd_dai_stream *io),
- void (*update)(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod),
- struct rsnd_kctrl_cfg *cfg,
- const char * const *texts,
- int size,
- u32 max)
-{
- struct snd_card *card = rtd->card->snd_card;
- struct snd_kcontrol *kctrl;
- struct snd_kcontrol_new knew = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = name,
- .info = rsnd_kctrl_info,
- .index = rtd->num,
- .get = rsnd_kctrl_get,
- .put = rsnd_kctrl_put,
- };
- int ret;
-
- /*
- * 1) Avoid duplicate register for DVC with MIX case
- * 2) Allow duplicate register for MIX
- * 3) re-register if card was rebinded
- */
- list_for_each_entry(kctrl, &card->controls, list) {
- struct rsnd_kctrl_cfg *c = kctrl->private_data;
-
- if (c == cfg)
- return 0;
- }
-
- if (size > RSND_MAX_CHANNELS)
- return -EINVAL;
-
- kctrl = snd_ctl_new1(&knew, cfg);
- if (!kctrl)
- return -ENOMEM;
-
- ret = snd_ctl_add(card, kctrl);
- if (ret < 0)
- return ret;
-
- cfg->texts = texts;
- cfg->max = max;
- cfg->size = size;
- cfg->accept = accept;
- cfg->update = update;
- cfg->card = card;
- cfg->kctrl = kctrl;
- cfg->io = io;
- cfg->mod = mod;
-
- return 0;
-}
-
-/*
- * snd_soc_component
- */
-static const struct snd_soc_component_driver rsnd_soc_component = {
- .name = "rsnd",
- .probe = rsnd_debugfs_probe,
- .hw_params = rsnd_hw_params,
- .hw_free = rsnd_hw_free,
- .pointer = rsnd_pointer,
- .legacy_dai_naming = 1,
-};
-
-static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io)
-{
- int ret;
-
- ret = rsnd_dai_call(probe, io, priv);
- if (ret == -EAGAIN) {
- struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_mod *mod;
- int i;
-
- /*
- * Fallback to PIO mode
- */
-
- /*
- * call "remove" for SSI/SRC/DVC
- * SSI will be switch to PIO mode if it was DMA mode
- * see
- * rsnd_dma_init()
- * rsnd_ssi_fallback()
- */
- rsnd_dai_call(remove, io, priv);
-
- /*
- * remove all mod from io
- * and, re connect ssi
- */
- for_each_rsnd_mod(i, mod, io)
- rsnd_dai_disconnect(mod, io, i);
- rsnd_dai_connect(ssi_mod, io, RSND_MOD_SSI);
-
- /*
- * fallback
- */
- rsnd_dai_call(fallback, io, priv);
-
- /*
- * retry to "probe".
- * DAI has SSI which is PIO mode only now.
- */
- ret = rsnd_dai_call(probe, io, priv);
- }
-
- return ret;
-}
-
-/*
- * rsnd probe
- */
-static int rsnd_probe(struct platform_device *pdev)
-{
- struct rsnd_priv *priv;
- struct device *dev = &pdev->dev;
- struct rsnd_dai *rdai;
- int (*probe_func[])(struct rsnd_priv *priv) = {
- rsnd_gen_probe,
- rsnd_dma_probe,
- rsnd_ssi_probe,
- rsnd_ssiu_probe,
- rsnd_src_probe,
- rsnd_ctu_probe,
- rsnd_mix_probe,
- rsnd_dvc_probe,
- rsnd_cmd_probe,
- rsnd_adg_probe,
- rsnd_dai_probe,
- };
- int ret, i;
- int ci;
-
- /*
- * init priv data
- */
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENODEV;
-
- priv->pdev = pdev;
- priv->flags = (unsigned long)of_device_get_match_data(dev);
- spin_lock_init(&priv->lock);
-
- /*
- * init each module
- */
- for (i = 0; i < ARRAY_SIZE(probe_func); i++) {
- ret = probe_func[i](priv);
- if (ret)
- return ret;
- }
-
- for_each_rsnd_dai(rdai, priv, i) {
- ret = rsnd_rdai_continuance_probe(priv, &rdai->playback);
- if (ret)
- goto exit_snd_probe;
-
- ret = rsnd_rdai_continuance_probe(priv, &rdai->capture);
- if (ret)
- goto exit_snd_probe;
- }
-
- dev_set_drvdata(dev, priv);
-
- /*
- * asoc register
- */
- ci = 0;
- for (i = 0; priv->component_dais[i] > 0; i++) {
- int nr = priv->component_dais[i];
-
- ret = devm_snd_soc_register_component(dev, &rsnd_soc_component,
- priv->daidrv + ci, nr);
- if (ret < 0) {
- dev_err(dev, "cannot snd component register\n");
- goto exit_snd_probe;
- }
-
- ci += nr;
- }
-
- pm_runtime_enable(dev);
-
- dev_info(dev, "probed\n");
- return ret;
-
-exit_snd_probe:
- for_each_rsnd_dai(rdai, priv, i) {
- rsnd_dai_call(remove, &rdai->playback, priv);
- rsnd_dai_call(remove, &rdai->capture, priv);
- }
-
- /*
- * adg is very special mod which can't use rsnd_dai_call(remove),
- * and it registers ADG clock on probe.
- * It should be unregister if probe failed.
- * Mainly it is assuming -EPROBE_DEFER case
- */
- rsnd_adg_remove(priv);
-
- return ret;
-}
-
-static void rsnd_remove(struct platform_device *pdev)
-{
- struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev);
- struct rsnd_dai *rdai;
- void (*remove_func[])(struct rsnd_priv *priv) = {
- rsnd_ssi_remove,
- rsnd_ssiu_remove,
- rsnd_src_remove,
- rsnd_ctu_remove,
- rsnd_mix_remove,
- rsnd_dvc_remove,
- rsnd_cmd_remove,
- rsnd_adg_remove,
- };
- int i;
-
- pm_runtime_disable(&pdev->dev);
-
- for_each_rsnd_dai(rdai, priv, i) {
- int ret;
-
- ret = rsnd_dai_call(remove, &rdai->playback, priv);
- if (ret)
- dev_warn(&pdev->dev, "Failed to remove playback dai #%d\n", i);
-
- ret = rsnd_dai_call(remove, &rdai->capture, priv);
- if (ret)
- dev_warn(&pdev->dev, "Failed to remove capture dai #%d\n", i);
- }
-
- for (i = 0; i < ARRAY_SIZE(remove_func); i++)
- remove_func[i](priv);
-}
-
-static int __maybe_unused rsnd_suspend(struct device *dev)
-{
- struct rsnd_priv *priv = dev_get_drvdata(dev);
-
- rsnd_adg_clk_disable(priv);
-
- return 0;
-}
-
-static int __maybe_unused rsnd_resume(struct device *dev)
-{
- struct rsnd_priv *priv = dev_get_drvdata(dev);
-
- rsnd_adg_clk_enable(priv);
-
- return 0;
-}
-
-static const struct dev_pm_ops rsnd_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(rsnd_suspend, rsnd_resume)
-};
-
-static struct platform_driver rsnd_driver = {
- .driver = {
- .name = "rcar_sound",
- .pm = &rsnd_pm_ops,
- .of_match_table = rsnd_of_match,
- },
- .probe = rsnd_probe,
- .remove_new = rsnd_remove,
-};
-module_platform_driver(rsnd_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Renesas R-Car audio driver");
-MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
-MODULE_ALIAS("platform:rcar-pcm-audio");
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c
deleted file mode 100644
index e39eb2ac7e95..000000000000
--- a/sound/soc/sh/rcar/ctu.c
+++ /dev/null
@@ -1,393 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// ctu.c
-//
-// Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-#include "rsnd.h"
-
-#define CTU_NAME_SIZE 16
-#define CTU_NAME "ctu"
-
-/*
- * User needs to setup CTU by amixer, and its settings are
- * based on below registers
- *
- * CTUn_CPMDR : amixser set "CTU Pass"
- * CTUn_SV0xR : amixser set "CTU SV0"
- * CTUn_SV1xR : amixser set "CTU SV1"
- * CTUn_SV2xR : amixser set "CTU SV2"
- * CTUn_SV3xR : amixser set "CTU SV3"
- *
- * [CTU Pass]
- * 0000: default
- * 0001: Connect input data of channel 0
- * 0010: Connect input data of channel 1
- * 0011: Connect input data of channel 2
- * 0100: Connect input data of channel 3
- * 0101: Connect input data of channel 4
- * 0110: Connect input data of channel 5
- * 0111: Connect input data of channel 6
- * 1000: Connect input data of channel 7
- * 1001: Connect calculated data by scale values of matrix row 0
- * 1010: Connect calculated data by scale values of matrix row 1
- * 1011: Connect calculated data by scale values of matrix row 2
- * 1100: Connect calculated data by scale values of matrix row 3
- *
- * [CTU SVx]
- * [Output0] = [SV00, SV01, SV02, SV03, SV04, SV05, SV06, SV07]
- * [Output1] = [SV10, SV11, SV12, SV13, SV14, SV15, SV16, SV17]
- * [Output2] = [SV20, SV21, SV22, SV23, SV24, SV25, SV26, SV27]
- * [Output3] = [SV30, SV31, SV32, SV33, SV34, SV35, SV36, SV37]
- * [Output4] = [ 0, 0, 0, 0, 0, 0, 0, 0 ]
- * [Output5] = [ 0, 0, 0, 0, 0, 0, 0, 0 ]
- * [Output6] = [ 0, 0, 0, 0, 0, 0, 0, 0 ]
- * [Output7] = [ 0, 0, 0, 0, 0, 0, 0, 0 ]
- *
- * [SVxx]
- * Plus Minus
- * value time dB value time dB
- * -----------------------------------------------------------------------
- * H'7F_FFFF 2 6 H'80_0000 2 6
- * ...
- * H'40_0000 1 0 H'C0_0000 1 0
- * ...
- * H'00_0001 2.38 x 10^-7 -132
- * H'00_0000 0 Mute H'FF_FFFF 2.38 x 10^-7 -132
- *
- *
- * Ex) Input ch -> Output ch
- * 1ch -> 0ch
- * 0ch -> 1ch
- *
- * amixer set "CTU Reset" on
- * amixer set "CTU Pass" 9,10
- * amixer set "CTU SV0" 0,4194304
- * amixer set "CTU SV1" 4194304,0
- * or
- * amixer set "CTU Reset" on
- * amixer set "CTU Pass" 2,1
- */
-
-struct rsnd_ctu {
- struct rsnd_mod mod;
- struct rsnd_kctrl_cfg_m pass;
- struct rsnd_kctrl_cfg_m sv[4];
- struct rsnd_kctrl_cfg_s reset;
- int channels;
- u32 flags;
-};
-
-#define KCTRL_INITIALIZED (1 << 0)
-
-#define rsnd_ctu_nr(priv) ((priv)->ctu_nr)
-#define for_each_rsnd_ctu(pos, priv, i) \
- for ((i) = 0; \
- ((i) < rsnd_ctu_nr(priv)) && \
- ((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \
- i++)
-
-#define rsnd_mod_to_ctu(_mod) \
- container_of((_mod), struct rsnd_ctu, mod)
-
-#define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id)
-
-static void rsnd_ctu_activation(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, CTU_SWRSR, 0);
- rsnd_mod_write(mod, CTU_SWRSR, 1);
-}
-
-static void rsnd_ctu_halt(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, CTU_CTUIR, 1);
- rsnd_mod_write(mod, CTU_SWRSR, 0);
-}
-
-static int rsnd_ctu_probe_(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- return rsnd_cmd_attach(io, rsnd_mod_id(mod));
-}
-
-static void rsnd_ctu_value_init(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
- u32 cpmdr = 0;
- u32 scmdr = 0;
- int i, j;
-
- for (i = 0; i < RSND_MAX_CHANNELS; i++) {
- u32 val = rsnd_kctrl_valm(ctu->pass, i);
-
- cpmdr |= val << (28 - (i * 4));
-
- if ((val > 0x8) && (scmdr < (val - 0x8)))
- scmdr = val - 0x8;
- }
-
- rsnd_mod_write(mod, CTU_CTUIR, 1);
-
- rsnd_mod_write(mod, CTU_ADINR, rsnd_runtime_channel_original(io));
-
- rsnd_mod_write(mod, CTU_CPMDR, cpmdr);
-
- rsnd_mod_write(mod, CTU_SCMDR, scmdr);
-
- for (i = 0; i < 4; i++) {
-
- if (i >= scmdr)
- break;
-
- for (j = 0; j < RSND_MAX_CHANNELS; j++)
- rsnd_mod_write(mod, CTU_SVxxR(i, j), rsnd_kctrl_valm(ctu->sv[i], j));
- }
-
- rsnd_mod_write(mod, CTU_CTUIR, 0);
-}
-
-static void rsnd_ctu_value_reset(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
- int i;
-
- if (!rsnd_kctrl_vals(ctu->reset))
- return;
-
- for (i = 0; i < RSND_MAX_CHANNELS; i++) {
- rsnd_kctrl_valm(ctu->pass, i) = 0;
- rsnd_kctrl_valm(ctu->sv[0], i) = 0;
- rsnd_kctrl_valm(ctu->sv[1], i) = 0;
- rsnd_kctrl_valm(ctu->sv[2], i) = 0;
- rsnd_kctrl_valm(ctu->sv[3], i) = 0;
- }
- rsnd_kctrl_vals(ctu->reset) = 0;
-}
-
-static int rsnd_ctu_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- ret = rsnd_mod_power_on(mod);
- if (ret < 0)
- return ret;
-
- rsnd_ctu_activation(mod);
-
- rsnd_ctu_value_init(io, mod);
-
- return 0;
-}
-
-static int rsnd_ctu_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_ctu_halt(mod);
-
- rsnd_mod_power_off(mod);
-
- return 0;
-}
-
-static int rsnd_ctu_pcm_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd)
-{
- struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
- int ret;
-
- if (rsnd_flags_has(ctu, KCTRL_INITIALIZED))
- return 0;
-
- /* CTU Pass */
- ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass",
- rsnd_kctrl_accept_anytime,
- NULL,
- &ctu->pass, RSND_MAX_CHANNELS,
- 0xC);
- if (ret < 0)
- return ret;
-
- /* ROW0 */
- ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0",
- rsnd_kctrl_accept_anytime,
- NULL,
- &ctu->sv[0], RSND_MAX_CHANNELS,
- 0x00FFFFFF);
- if (ret < 0)
- return ret;
-
- /* ROW1 */
- ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV1",
- rsnd_kctrl_accept_anytime,
- NULL,
- &ctu->sv[1], RSND_MAX_CHANNELS,
- 0x00FFFFFF);
- if (ret < 0)
- return ret;
-
- /* ROW2 */
- ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV2",
- rsnd_kctrl_accept_anytime,
- NULL,
- &ctu->sv[2], RSND_MAX_CHANNELS,
- 0x00FFFFFF);
- if (ret < 0)
- return ret;
-
- /* ROW3 */
- ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV3",
- rsnd_kctrl_accept_anytime,
- NULL,
- &ctu->sv[3], RSND_MAX_CHANNELS,
- 0x00FFFFFF);
- if (ret < 0)
- return ret;
-
- /* Reset */
- ret = rsnd_kctrl_new_s(mod, io, rtd, "CTU Reset",
- rsnd_kctrl_accept_anytime,
- rsnd_ctu_value_reset,
- &ctu->reset, 1);
-
- rsnd_flags_set(ctu, KCTRL_INITIALIZED);
-
- return ret;
-}
-
-static int rsnd_ctu_id(struct rsnd_mod *mod)
-{
- /*
- * ctu00: -> 0, ctu01: -> 0, ctu02: -> 0, ctu03: -> 0
- * ctu10: -> 1, ctu11: -> 1, ctu12: -> 1, ctu13: -> 1
- */
- return mod->id / 4;
-}
-
-static int rsnd_ctu_id_sub(struct rsnd_mod *mod)
-{
- /*
- * ctu00: -> 0, ctu01: -> 1, ctu02: -> 2, ctu03: -> 3
- * ctu10: -> 0, ctu11: -> 1, ctu12: -> 2, ctu13: -> 3
- */
- return mod->id % 4;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_ctu_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0x500 + rsnd_mod_id_raw(mod) * 0x100, 0x100);
-}
-#define DEBUG_INFO .debug_info = rsnd_ctu_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_ctu_ops = {
- .name = CTU_NAME,
- .probe = rsnd_ctu_probe_,
- .init = rsnd_ctu_init,
- .quit = rsnd_ctu_quit,
- .pcm_new = rsnd_ctu_pcm_new,
- .get_status = rsnd_mod_get_status,
- .id = rsnd_ctu_id,
- .id_sub = rsnd_ctu_id_sub,
- .id_cmd = rsnd_mod_id_raw,
- DEBUG_INFO
-};
-
-struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
- id = 0;
-
- return rsnd_mod_get(rsnd_ctu_get(priv, id));
-}
-
-int rsnd_ctu_probe(struct rsnd_priv *priv)
-{
- struct device_node *node;
- struct device_node *np;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_ctu *ctu;
- struct clk *clk;
- char name[CTU_NAME_SIZE];
- int i, nr, ret;
-
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
- node = rsnd_ctu_of_node(priv);
- if (!node)
- return 0; /* not used is not error */
-
- nr = of_get_child_count(node);
- if (!nr) {
- ret = -EINVAL;
- goto rsnd_ctu_probe_done;
- }
-
- ctu = devm_kcalloc(dev, nr, sizeof(*ctu), GFP_KERNEL);
- if (!ctu) {
- ret = -ENOMEM;
- goto rsnd_ctu_probe_done;
- }
-
- priv->ctu_nr = nr;
- priv->ctu = ctu;
-
- i = 0;
- ret = 0;
- for_each_child_of_node(node, np) {
- ctu = rsnd_ctu_get(priv, i);
-
- /*
- * CTU00, CTU01, CTU02, CTU03 => CTU0
- * CTU10, CTU11, CTU12, CTU13 => CTU1
- */
- snprintf(name, CTU_NAME_SIZE, "%s.%d",
- CTU_NAME, i / 4);
-
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- of_node_put(np);
- goto rsnd_ctu_probe_done;
- }
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
- clk, RSND_MOD_CTU, i);
- if (ret) {
- of_node_put(np);
- goto rsnd_ctu_probe_done;
- }
-
- i++;
- }
-
-
-rsnd_ctu_probe_done:
- of_node_put(node);
-
- return ret;
-}
-
-void rsnd_ctu_remove(struct rsnd_priv *priv)
-{
- struct rsnd_ctu *ctu;
- int i;
-
- for_each_rsnd_ctu(ctu, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(ctu));
- }
-}
diff --git a/sound/soc/sh/rcar/debugfs.c b/sound/soc/sh/rcar/debugfs.c
deleted file mode 100644
index 26d3b310b9db..000000000000
--- a/sound/soc/sh/rcar/debugfs.c
+++ /dev/null
@@ -1,96 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// // Renesas R-Car debugfs support
-//
-// Copyright (c) 2021 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-//
-// > mount -t debugfs none /sys/kernel/debug
-// > cd /sys/kernel/debug/asoc/rcar-sound/ec500000.sound/rdai{N}/
-// > cat playback/xxx
-// > cat capture/xxx
-//
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/debugfs.h>
-#include "rsnd.h"
-
-static int rsnd_debugfs_show(struct seq_file *m, void *v)
-{
- struct rsnd_dai_stream *io = m->private;
- struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- int i;
-
- /* adg is out of mods */
- rsnd_adg_clk_dbg_info(priv, m);
-
- for_each_rsnd_mod(i, mod, io) {
- u32 *status = mod->ops->get_status(mod, io, mod->type);
-
- seq_printf(m, "name: %s\n", rsnd_mod_name(mod));
- seq_printf(m, "status: %08x\n", *status);
-
- if (mod->ops->debug_info)
- mod->ops->debug_info(m, io, mod);
- }
-
- return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(rsnd_debugfs);
-
-void rsnd_debugfs_reg_show(struct seq_file *m, phys_addr_t _addr,
- void __iomem *base, int offset, int size)
-{
- int i, j;
-
- for (i = 0; i < size; i += 0x10) {
- phys_addr_t addr = _addr + offset + i;
-
- seq_printf(m, "%pa:", &addr);
- for (j = 0; j < 0x10; j += 0x4)
- seq_printf(m, " %08x", __raw_readl(base + offset + i + j));
- seq_puts(m, "\n");
- }
-}
-
-void rsnd_debugfs_mod_reg_show(struct seq_file *m, struct rsnd_mod *mod,
- int reg_id, int offset, int size)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-
- rsnd_debugfs_reg_show(m,
- rsnd_gen_get_phy_addr(priv, reg_id),
- rsnd_gen_get_base_addr(priv, reg_id),
- offset, size);
-}
-
-int rsnd_debugfs_probe(struct snd_soc_component *component)
-{
- struct rsnd_priv *priv = dev_get_drvdata(component->dev);
- struct rsnd_dai *rdai;
- struct dentry *dir;
- char name[64];
- int i;
-
- /* Gen1 is not supported */
- if (rsnd_is_gen1(priv))
- return 0;
-
- for_each_rsnd_dai(rdai, priv, i) {
- /*
- * created debugfs will be automatically
- * removed, nothing to do for _remove.
- * see
- * soc_cleanup_component_debugfs()
- */
- snprintf(name, sizeof(name), "rdai%d", i);
- dir = debugfs_create_dir(name, component->debugfs_root);
-
- debugfs_create_file("playback", 0444, dir, &rdai->playback, &rsnd_debugfs_fops);
- debugfs_create_file("capture", 0444, dir, &rdai->capture, &rsnd_debugfs_fops);
- }
-
- return 0;
-}
-
-#endif /* CONFIG_DEBUG_FS */
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
deleted file mode 100644
index 1c494e521463..000000000000
--- a/sound/soc/sh/rcar/dma.c
+++ /dev/null
@@ -1,946 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car Audio DMAC support
-//
-// Copyright (C) 2015 Renesas Electronics Corp.
-// Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-#include <linux/delay.h>
-#include <linux/of_dma.h>
-#include "rsnd.h"
-
-/*
- * Audio DMAC peri peri register
- */
-#define PDMASAR 0x00
-#define PDMADAR 0x04
-#define PDMACHCR 0x0c
-
-/* PDMACHCR */
-#define PDMACHCR_DE (1 << 0)
-
-
-struct rsnd_dmaen {
- struct dma_chan *chan;
- dma_cookie_t cookie;
- unsigned int dma_len;
-};
-
-struct rsnd_dmapp {
- int dmapp_id;
- u32 chcr;
-};
-
-struct rsnd_dma {
- struct rsnd_mod mod;
- struct rsnd_mod *mod_from;
- struct rsnd_mod *mod_to;
- dma_addr_t src_addr;
- dma_addr_t dst_addr;
- union {
- struct rsnd_dmaen en;
- struct rsnd_dmapp pp;
- } dma;
-};
-
-struct rsnd_dma_ctrl {
- void __iomem *ppbase;
- phys_addr_t ppres;
- int dmaen_num;
- int dmapp_num;
-};
-
-#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma)
-#define rsnd_mod_to_dma(_mod) container_of((_mod), struct rsnd_dma, mod)
-#define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en)
-#define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp)
-
-/* for DEBUG */
-static struct rsnd_mod_ops mem_ops = {
- .name = "mem",
-};
-
-static struct rsnd_mod mem = {
-};
-
-/*
- * Audio DMAC
- */
-static void __rsnd_dmaen_complete(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- if (rsnd_io_is_working(io))
- rsnd_dai_period_elapsed(io);
-}
-
-static void rsnd_dmaen_complete(void *data)
-{
- struct rsnd_mod *mod = data;
-
- rsnd_mod_interrupt(mod, __rsnd_dmaen_complete);
-}
-
-static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod_from,
- struct rsnd_mod *mod_to)
-{
- if ((!mod_from && !mod_to) ||
- (mod_from && mod_to))
- return NULL;
-
- if (mod_from)
- return rsnd_mod_dma_req(io, mod_from);
- else
- return rsnd_mod_dma_req(io, mod_to);
-}
-
-static int rsnd_dmaen_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
-
- if (dmaen->chan)
- dmaengine_terminate_async(dmaen->chan);
-
- return 0;
-}
-
-static int rsnd_dmaen_cleanup(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
-
- /*
- * DMAEngine release uses mutex lock.
- * Thus, it shouldn't be called under spinlock.
- * Let's call it under prepare
- */
- if (dmaen->chan)
- dma_release_channel(dmaen->chan);
-
- dmaen->chan = NULL;
-
- return 0;
-}
-
-static int rsnd_dmaen_prepare(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- /* maybe suspended */
- if (dmaen->chan)
- return 0;
-
- /*
- * DMAEngine request uses mutex lock.
- * Thus, it shouldn't be called under spinlock.
- * Let's call it under prepare
- */
- dmaen->chan = rsnd_dmaen_request_channel(io,
- dma->mod_from,
- dma->mod_to);
- if (IS_ERR_OR_NULL(dmaen->chan)) {
- dmaen->chan = NULL;
- dev_err(dev, "can't get dma channel\n");
- return -EIO;
- }
-
- return 0;
-}
-
-static int rsnd_dmaen_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
- struct snd_pcm_substream *substream = io->substream;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct dma_async_tx_descriptor *desc;
- struct dma_slave_config cfg = {};
- enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
- int is_play = rsnd_io_is_play(io);
- int ret;
-
- /*
- * in case of monaural data writing or reading through Audio-DMAC
- * data is always in Left Justified format, so both src and dst
- * DMA Bus width need to be set equal to physical data width.
- */
- if (rsnd_runtime_channel_original(io) == 1) {
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- int bits = snd_pcm_format_physical_width(runtime->format);
-
- switch (bits) {
- case 8:
- buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
- break;
- case 16:
- buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
- break;
- case 32:
- buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
- break;
- default:
- dev_err(dev, "invalid format width %d\n", bits);
- return -EINVAL;
- }
- }
-
- cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
- cfg.src_addr = dma->src_addr;
- cfg.dst_addr = dma->dst_addr;
- cfg.src_addr_width = buswidth;
- cfg.dst_addr_width = buswidth;
-
- dev_dbg(dev, "%s %pad -> %pad\n",
- rsnd_mod_name(mod),
- &cfg.src_addr, &cfg.dst_addr);
-
- ret = dmaengine_slave_config(dmaen->chan, &cfg);
- if (ret < 0)
- return ret;
-
- desc = dmaengine_prep_dma_cyclic(dmaen->chan,
- substream->runtime->dma_addr,
- snd_pcm_lib_buffer_bytes(substream),
- snd_pcm_lib_period_bytes(substream),
- is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
- if (!desc) {
- dev_err(dev, "dmaengine_prep_slave_sg() fail\n");
- return -EIO;
- }
-
- desc->callback = rsnd_dmaen_complete;
- desc->callback_param = rsnd_mod_get(dma);
-
- dmaen->dma_len = snd_pcm_lib_buffer_bytes(substream);
-
- dmaen->cookie = dmaengine_submit(desc);
- if (dmaen->cookie < 0) {
- dev_err(dev, "dmaengine_submit() fail\n");
- return -EIO;
- }
-
- dma_async_issue_pending(dmaen->chan);
-
- return 0;
-}
-
-struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, char *name,
- struct rsnd_mod *mod, char *x)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct dma_chan *chan = NULL;
- struct device_node *np;
- int i = 0;
-
- for_each_child_of_node(of_node, np) {
- i = rsnd_node_fixed_index(dev, np, name, i);
- if (i < 0) {
- chan = NULL;
- of_node_put(np);
- break;
- }
-
- if (i == rsnd_mod_id_raw(mod) && (!chan))
- chan = of_dma_request_slave_channel(np, x);
- i++;
- }
-
- /* It should call of_node_put(), since, it is rsnd_xxx_of_node() */
- of_node_put(of_node);
-
- return chan;
-}
-
-static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
- struct rsnd_dma *dma,
- struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- struct dma_chan *chan;
-
- /* try to get DMAEngine channel */
- chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
- if (IS_ERR_OR_NULL(chan)) {
- /* Let's follow when -EPROBE_DEFER case */
- if (PTR_ERR(chan) == -EPROBE_DEFER)
- return PTR_ERR(chan);
-
- /*
- * DMA failed. try to PIO mode
- * see
- * rsnd_ssi_fallback()
- * rsnd_rdai_continuance_probe()
- */
- return -EAGAIN;
- }
-
- /*
- * use it for IPMMU if needed
- * see
- * rsnd_preallocate_pages()
- */
- io->dmac_dev = chan->device->dev;
-
- dma_release_channel(chan);
-
- dmac->dmaen_num++;
-
- return 0;
-}
-
-static int rsnd_dmaen_pointer(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- snd_pcm_uframes_t *pointer)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
- struct dma_tx_state state;
- enum dma_status status;
- unsigned int pos = 0;
-
- status = dmaengine_tx_status(dmaen->chan, dmaen->cookie, &state);
- if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) {
- if (state.residue > 0 && state.residue <= dmaen->dma_len)
- pos = dmaen->dma_len - state.residue;
- }
- *pointer = bytes_to_frames(runtime, pos);
-
- return 0;
-}
-
-static struct rsnd_mod_ops rsnd_dmaen_ops = {
- .name = "audmac",
- .prepare = rsnd_dmaen_prepare,
- .cleanup = rsnd_dmaen_cleanup,
- .start = rsnd_dmaen_start,
- .stop = rsnd_dmaen_stop,
- .pointer = rsnd_dmaen_pointer,
- .get_status = rsnd_mod_get_status,
-};
-
-/*
- * Audio DMAC peri peri
- */
-static const u8 gen2_id_table_ssiu[] = {
- /* SSI00 ~ SSI07 */
- 0x00, 0x01, 0x02, 0x03, 0x39, 0x3a, 0x3b, 0x3c,
- /* SSI10 ~ SSI17 */
- 0x04, 0x05, 0x06, 0x07, 0x3d, 0x3e, 0x3f, 0x40,
- /* SSI20 ~ SSI27 */
- 0x08, 0x09, 0x0a, 0x0b, 0x41, 0x42, 0x43, 0x44,
- /* SSI30 ~ SSI37 */
- 0x0c, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
- /* SSI40 ~ SSI47 */
- 0x0d, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
- /* SSI5 */
- 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* SSI6 */
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* SSI7 */
- 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* SSI8 */
- 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* SSI90 ~ SSI97 */
- 0x12, 0x13, 0x14, 0x15, 0x53, 0x54, 0x55, 0x56,
-};
-static const u8 gen2_id_table_scu[] = {
- 0x2d, /* SCU_SRCI0 */
- 0x2e, /* SCU_SRCI1 */
- 0x2f, /* SCU_SRCI2 */
- 0x30, /* SCU_SRCI3 */
- 0x31, /* SCU_SRCI4 */
- 0x32, /* SCU_SRCI5 */
- 0x33, /* SCU_SRCI6 */
- 0x34, /* SCU_SRCI7 */
- 0x35, /* SCU_SRCI8 */
- 0x36, /* SCU_SRCI9 */
-};
-static const u8 gen2_id_table_cmd[] = {
- 0x37, /* SCU_CMD0 */
- 0x38, /* SCU_CMD1 */
-};
-
-static u32 rsnd_dmapp_get_id(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
- struct rsnd_mod *ssiu = rsnd_io_to_mod_ssiu(io);
- struct rsnd_mod *src = rsnd_io_to_mod_src(io);
- struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
- const u8 *entry = NULL;
- int id = 255;
- int size = 0;
-
- if ((mod == ssi) ||
- (mod == ssiu)) {
- int busif = rsnd_mod_id_sub(ssiu);
-
- entry = gen2_id_table_ssiu;
- size = ARRAY_SIZE(gen2_id_table_ssiu);
- id = (rsnd_mod_id(mod) * 8) + busif;
- } else if (mod == src) {
- entry = gen2_id_table_scu;
- size = ARRAY_SIZE(gen2_id_table_scu);
- id = rsnd_mod_id(mod);
- } else if (mod == dvc) {
- entry = gen2_id_table_cmd;
- size = ARRAY_SIZE(gen2_id_table_cmd);
- id = rsnd_mod_id(mod);
- }
-
- if ((!entry) || (size <= id)) {
- struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io));
-
- dev_err(dev, "unknown connection (%s)\n", rsnd_mod_name(mod));
-
- /* use non-prohibited SRS number as error */
- return 0x00; /* SSI00 */
- }
-
- return entry[id];
-}
-
-static u32 rsnd_dmapp_get_chcr(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod_from,
- struct rsnd_mod *mod_to)
-{
- return (rsnd_dmapp_get_id(io, mod_from) << 24) +
- (rsnd_dmapp_get_id(io, mod_to) << 16);
-}
-
-#define rsnd_dmapp_addr(dmac, dma, reg) \
- (dmac->ppbase + 0x20 + reg + \
- (0x10 * rsnd_dma_to_dmapp(dma)->dmapp_id))
-static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg)
-{
- struct rsnd_mod *mod = rsnd_mod_get(dma);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_dbg(dev, "w 0x%px : %08x\n", rsnd_dmapp_addr(dmac, dma, reg), data);
-
- iowrite32(data, rsnd_dmapp_addr(dmac, dma, reg));
-}
-
-static u32 rsnd_dmapp_read(struct rsnd_dma *dma, u32 reg)
-{
- struct rsnd_mod *mod = rsnd_mod_get(dma);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
-
- return ioread32(rsnd_dmapp_addr(dmac, dma, reg));
-}
-
-static void rsnd_dmapp_bset(struct rsnd_dma *dma, u32 data, u32 mask, u32 reg)
-{
- struct rsnd_mod *mod = rsnd_mod_get(dma);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- void __iomem *addr = rsnd_dmapp_addr(dmac, dma, reg);
- u32 val = ioread32(addr);
-
- val &= ~mask;
- val |= (data & mask);
-
- iowrite32(val, addr);
-}
-
-static int rsnd_dmapp_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- int i;
-
- rsnd_dmapp_bset(dma, 0, PDMACHCR_DE, PDMACHCR);
-
- for (i = 0; i < 1024; i++) {
- if (0 == (rsnd_dmapp_read(dma, PDMACHCR) & PDMACHCR_DE))
- return 0;
- udelay(1);
- }
-
- return -EIO;
-}
-
-static int rsnd_dmapp_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
-
- rsnd_dmapp_write(dma, dma->src_addr, PDMASAR);
- rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR);
- rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR);
-
- return 0;
-}
-
-static int rsnd_dmapp_attach(struct rsnd_dai_stream *io,
- struct rsnd_dma *dma,
- struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
-{
- struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dmapp->dmapp_id = dmac->dmapp_num;
- dmapp->chcr = rsnd_dmapp_get_chcr(io, mod_from, mod_to) | PDMACHCR_DE;
-
- dmac->dmapp_num++;
-
- dev_dbg(dev, "id/src/dst/chcr = %d/%pad/%pad/%08x\n",
- dmapp->dmapp_id, &dma->src_addr, &dma->dst_addr, dmapp->chcr);
-
- return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_dmapp_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
-
- rsnd_debugfs_reg_show(m, dmac->ppres, dmac->ppbase,
- 0x20 + 0x10 * dmapp->dmapp_id, 0x10);
-}
-#define DEBUG_INFO .debug_info = rsnd_dmapp_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_dmapp_ops = {
- .name = "audmac-pp",
- .start = rsnd_dmapp_start,
- .stop = rsnd_dmapp_stop,
- .quit = rsnd_dmapp_stop,
- .get_status = rsnd_mod_get_status,
- DEBUG_INFO
-};
-
-/*
- * Common DMAC Interface
- */
-
-/*
- * DMA read/write register offset
- *
- * RSND_xxx_I_N for Audio DMAC input
- * RSND_xxx_O_N for Audio DMAC output
- * RSND_xxx_I_P for Audio DMAC peri peri input
- * RSND_xxx_O_P for Audio DMAC peri peri output
- *
- * ex) R-Car H2 case
- * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
- * SSI : 0xec541000 / 0xec241008 / 0xec24100c
- * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
- * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
- * CMD : 0xec500000 / / 0xec008000 0xec308000
- */
-#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
-#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
-
-#define RDMA_SSIU_I_N(addr, i, j) (addr ##_reg - 0x00441000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
-#define RDMA_SSIU_O_N(addr, i, j) RDMA_SSIU_I_N(addr, i, j)
-
-#define RDMA_SSIU_I_P(addr, i, j) (addr ##_reg - 0x00141000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
-#define RDMA_SSIU_O_P(addr, i, j) RDMA_SSIU_I_P(addr, i, j)
-
-#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i))
-#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i))
-
-#define RDMA_SRC_I_P(addr, i) (addr ##_reg - 0x00200000 + (0x400 * i))
-#define RDMA_SRC_O_P(addr, i) (addr ##_reg - 0x001fc000 + (0x400 * i))
-
-#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i))
-#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i))
-
-static dma_addr_t
-rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod,
- int is_play, int is_from)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI);
- phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU);
- int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod) ||
- !!(rsnd_io_to_mod_ssiu(io) == mod);
- int use_src = !!rsnd_io_to_mod_src(io);
- int use_cmd = !!rsnd_io_to_mod_dvc(io) ||
- !!rsnd_io_to_mod_mix(io) ||
- !!rsnd_io_to_mod_ctu(io);
- int id = rsnd_mod_id(mod);
- int busif = rsnd_mod_id_sub(rsnd_io_to_mod_ssiu(io));
- struct dma_addr {
- dma_addr_t out_addr;
- dma_addr_t in_addr;
- } dma_addrs[3][2][3] = {
- /* SRC */
- /* Capture */
- {{{ 0, 0 },
- { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) },
- { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } },
- /* Playback */
- {{ 0, 0, },
- { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) },
- { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } }
- },
- /* SSI */
- /* Capture */
- {{{ RDMA_SSI_O_N(ssi, id), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 } },
- /* Playback */
- {{ 0, RDMA_SSI_I_N(ssi, id) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) } }
- },
- /* SSIU */
- /* Capture */
- {{{ RDMA_SSIU_O_N(ssi, id, busif), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 } },
- /* Playback */
- {{ 0, RDMA_SSIU_I_N(ssi, id, busif) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) } } },
- };
-
- /*
- * FIXME
- *
- * We can't support SSI9-4/5/6/7, because its address is
- * out of calculation rule
- */
- if ((id == 9) && (busif >= 4))
- dev_err(dev, "This driver doesn't support SSI%d-%d, so far",
- id, busif);
-
- /* it shouldn't happen */
- if (use_cmd && !use_src)
- dev_err(dev, "DVC is selected without SRC\n");
-
- /* use SSIU or SSI ? */
- if (is_ssi && rsnd_ssi_use_busif(io))
- is_ssi++;
-
- return (is_from) ?
- dma_addrs[is_ssi][is_play][use_src + use_cmd].out_addr :
- dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr;
-}
-
-/*
- * Gen4 DMA read/write register offset
- *
- * ex) R-Car V4H case
- * mod / SYS-DMAC in / SYS-DMAC out
- * SSI_SDMC: 0xec400000 / 0xec400000 / 0xec400000
- */
-#define RDMA_SSI_SDMC(addr, i) (addr + (0x8000 * i))
-static dma_addr_t
-rsnd_gen4_dma_addr(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
- int is_play, int is_from)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- phys_addr_t addr = rsnd_gen_get_phy_addr(priv, RSND_GEN4_SDMC);
- int id = rsnd_mod_id(mod);
- int busif = rsnd_mod_id_sub(mod);
-
- /*
- * SSI0 only is supported
- */
- if (id != 0) {
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_err(dev, "This driver doesn't support non SSI0");
- return -EINVAL;
- }
-
- return RDMA_SSI_SDMC(addr, busif);
-}
-
-static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod,
- int is_play, int is_from)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
-
- if (!mod)
- return 0;
-
- /*
- * gen1 uses default DMA addr
- */
- if (rsnd_is_gen1(priv))
- return 0;
- else if (rsnd_is_gen4(priv))
- return rsnd_gen4_dma_addr(io, mod, is_play, is_from);
- else
- return rsnd_gen2_dma_addr(io, mod, is_play, is_from);
-}
-
-#define MOD_MAX (RSND_MOD_MAX + 1) /* +Memory */
-static void rsnd_dma_of_path(struct rsnd_mod *this,
- struct rsnd_dai_stream *io,
- int is_play,
- struct rsnd_mod **mod_from,
- struct rsnd_mod **mod_to)
-{
- struct rsnd_mod *ssi;
- struct rsnd_mod *src = rsnd_io_to_mod_src(io);
- struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io);
- struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
- struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
- struct rsnd_mod *mod[MOD_MAX];
- struct rsnd_mod *mod_start, *mod_end;
- struct rsnd_priv *priv = rsnd_mod_to_priv(this);
- struct device *dev = rsnd_priv_to_dev(priv);
- int nr, i, idx;
-
- /*
- * It should use "rcar_sound,ssiu" on DT.
- * But, we need to keep compatibility for old version.
- *
- * If it has "rcar_sound.ssiu", it will be used.
- * If not, "rcar_sound.ssi" will be used.
- * see
- * rsnd_ssiu_dma_req()
- * rsnd_ssi_dma_req()
- */
- if (rsnd_ssiu_of_node(priv)) {
- struct rsnd_mod *ssiu = rsnd_io_to_mod_ssiu(io);
-
- /* use SSIU */
- ssi = ssiu;
- if (this == rsnd_io_to_mod_ssi(io))
- this = ssiu;
- } else {
- /* keep compatible, use SSI */
- ssi = rsnd_io_to_mod_ssi(io);
- }
-
- if (!ssi)
- return;
-
- nr = 0;
- for (i = 0; i < MOD_MAX; i++) {
- mod[i] = NULL;
- nr += !!rsnd_io_to_mod(io, i);
- }
-
- /*
- * [S] -*-> [E]
- * [S] -*-> SRC -o-> [E]
- * [S] -*-> SRC -> DVC -o-> [E]
- * [S] -*-> SRC -> CTU -> MIX -> DVC -o-> [E]
- *
- * playback [S] = mem
- * [E] = SSI
- *
- * capture [S] = SSI
- * [E] = mem
- *
- * -*-> Audio DMAC
- * -o-> Audio DMAC peri peri
- */
- mod_start = (is_play) ? NULL : ssi;
- mod_end = (is_play) ? ssi : NULL;
-
- idx = 0;
- mod[idx++] = mod_start;
- for (i = 1; i < nr; i++) {
- if (src) {
- mod[idx++] = src;
- src = NULL;
- } else if (ctu) {
- mod[idx++] = ctu;
- ctu = NULL;
- } else if (mix) {
- mod[idx++] = mix;
- mix = NULL;
- } else if (dvc) {
- mod[idx++] = dvc;
- dvc = NULL;
- }
- }
- mod[idx] = mod_end;
-
- /*
- * | SSI | SRC |
- * -------------+-----+-----+
- * is_play | o | * |
- * !is_play | * | o |
- */
- if ((this == ssi) == (is_play)) {
- *mod_from = mod[idx - 1];
- *mod_to = mod[idx];
- } else {
- *mod_from = mod[0];
- *mod_to = mod[1];
- }
-
- dev_dbg(dev, "module connection (this is %s)\n", rsnd_mod_name(this));
- for (i = 0; i <= idx; i++) {
- dev_dbg(dev, " %s%s\n",
- rsnd_mod_name(mod[i] ? mod[i] : &mem),
- (mod[i] == *mod_from) ? " from" :
- (mod[i] == *mod_to) ? " to" : "");
- }
-}
-
-static int rsnd_dma_alloc(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
- struct rsnd_mod **dma_mod)
-{
- struct rsnd_mod *mod_from = NULL;
- struct rsnd_mod *mod_to = NULL;
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_dma *dma;
- struct rsnd_mod_ops *ops;
- enum rsnd_mod_type type;
- int (*attach)(struct rsnd_dai_stream *io, struct rsnd_dma *dma,
- struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
- int is_play = rsnd_io_is_play(io);
- int ret, dma_id;
-
- /*
- * DMA failed. try to PIO mode
- * see
- * rsnd_ssi_fallback()
- * rsnd_rdai_continuance_probe()
- */
- if (!dmac)
- return -EAGAIN;
-
- rsnd_dma_of_path(mod, io, is_play, &mod_from, &mod_to);
-
- /* for Gen2 or later */
- if (mod_from && mod_to) {
- ops = &rsnd_dmapp_ops;
- attach = rsnd_dmapp_attach;
- dma_id = dmac->dmapp_num;
- type = RSND_MOD_AUDMAPP;
- } else {
- ops = &rsnd_dmaen_ops;
- attach = rsnd_dmaen_attach;
- dma_id = dmac->dmaen_num;
- type = RSND_MOD_AUDMA;
- }
-
- /* for Gen1, overwrite */
- if (rsnd_is_gen1(priv)) {
- ops = &rsnd_dmaen_ops;
- attach = rsnd_dmaen_attach;
- dma_id = dmac->dmaen_num;
- type = RSND_MOD_AUDMA;
- }
-
- dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
- if (!dma)
- return -ENOMEM;
-
- *dma_mod = rsnd_mod_get(dma);
-
- ret = rsnd_mod_init(priv, *dma_mod, ops, NULL,
- type, dma_id);
- if (ret < 0)
- return ret;
-
- dev_dbg(dev, "%s %s -> %s\n",
- rsnd_mod_name(*dma_mod),
- rsnd_mod_name(mod_from ? mod_from : &mem),
- rsnd_mod_name(mod_to ? mod_to : &mem));
-
- ret = attach(io, dma, mod_from, mod_to);
- if (ret < 0)
- return ret;
-
- dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1);
- dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0);
- dma->mod_from = mod_from;
- dma->mod_to = mod_to;
-
- return 0;
-}
-
-int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
- struct rsnd_mod **dma_mod)
-{
- if (!(*dma_mod)) {
- int ret = rsnd_dma_alloc(io, mod, dma_mod);
-
- if (ret < 0)
- return ret;
- }
-
- return rsnd_dai_connect(*dma_mod, io, (*dma_mod)->type);
-}
-
-int rsnd_dma_probe(struct rsnd_priv *priv)
-{
- struct platform_device *pdev = rsnd_priv_to_pdev(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_dma_ctrl *dmac;
- struct resource *res;
-
- /*
- * for Gen1
- */
- if (rsnd_is_gen1(priv))
- return 0;
-
- /*
- * for Gen2 or later
- */
- dmac = devm_kzalloc(dev, sizeof(*dmac), GFP_KERNEL);
- if (!dmac) {
- dev_err(dev, "dma allocate failed\n");
- return 0; /* it will be PIO mode */
- }
-
- /* for Gen4 doesn't have DMA-pp */
- if (rsnd_is_gen4(priv))
- goto audmapp_end;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audmapp");
- if (!res) {
- dev_err(dev, "lack of audmapp in DT\n");
- return 0; /* it will be PIO mode */
- }
-
- dmac->dmapp_num = 0;
- dmac->ppres = res->start;
- dmac->ppbase = devm_ioremap_resource(dev, res);
- if (IS_ERR(dmac->ppbase))
- return PTR_ERR(dmac->ppbase);
-audmapp_end:
- priv->dma = dmac;
-
- /* dummy mem mod for debug */
- return rsnd_mod_init(NULL, &mem, &mem_ops, NULL, 0, 0);
-}
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
deleted file mode 100644
index 16befcbc312c..000000000000
--- a/sound/soc/sh/rcar/dvc.c
+++ /dev/null
@@ -1,396 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car DVC support
-//
-// Copyright (C) 2014 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-/*
- * Playback Volume
- * amixer set "DVC Out" 100%
- *
- * Capture Volume
- * amixer set "DVC In" 100%
- *
- * Playback Mute
- * amixer set "DVC Out Mute" on
- *
- * Capture Mute
- * amixer set "DVC In Mute" on
- *
- * Volume Ramp
- * amixer set "DVC Out Ramp Up Rate" "0.125 dB/64 steps"
- * amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps"
- * amixer set "DVC Out Ramp" on
- * aplay xxx.wav &
- * amixer set "DVC Out" 80% // Volume Down
- * amixer set "DVC Out" 100% // Volume Up
- */
-
-#include "rsnd.h"
-
-#define RSND_DVC_NAME_SIZE 16
-
-#define DVC_NAME "dvc"
-
-struct rsnd_dvc {
- struct rsnd_mod mod;
- struct rsnd_kctrl_cfg_m volume;
- struct rsnd_kctrl_cfg_m mute;
- struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */
- struct rsnd_kctrl_cfg_s rup; /* Ramp Rate Up */
- struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */
-};
-
-#define rsnd_dvc_get(priv, id) ((struct rsnd_dvc *)(priv->dvc) + id)
-#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
-
-#define rsnd_mod_to_dvc(_mod) \
- container_of((_mod), struct rsnd_dvc, mod)
-
-#define for_each_rsnd_dvc(pos, priv, i) \
- for ((i) = 0; \
- ((i) < rsnd_dvc_nr(priv)) && \
- ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \
- i++)
-
-static void rsnd_dvc_activation(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, DVC_SWRSR, 0);
- rsnd_mod_write(mod, DVC_SWRSR, 1);
-}
-
-static void rsnd_dvc_halt(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, DVC_DVUIR, 1);
- rsnd_mod_write(mod, DVC_SWRSR, 0);
-}
-
-#define rsnd_dvc_get_vrpdr(dvc) (rsnd_kctrl_vals(dvc->rup) << 8 | \
- rsnd_kctrl_vals(dvc->rdown))
-#define rsnd_dvc_get_vrdbr(dvc) (0x3ff - (rsnd_kctrl_valm(dvc->volume, 0) >> 13))
-
-static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
- u32 val[RSND_MAX_CHANNELS];
- int i;
-
- /* Enable Ramp */
- if (rsnd_kctrl_vals(dvc->ren))
- for (i = 0; i < RSND_MAX_CHANNELS; i++)
- val[i] = rsnd_kctrl_max(dvc->volume);
- else
- for (i = 0; i < RSND_MAX_CHANNELS; i++)
- val[i] = rsnd_kctrl_valm(dvc->volume, i);
-
- /* Enable Digital Volume */
- for (i = 0; i < RSND_MAX_CHANNELS; i++)
- rsnd_mod_write(mod, DVC_VOLxR(i), val[i]);
-}
-
-static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
- u32 adinr = 0;
- u32 dvucr = 0;
- u32 vrctr = 0;
- u32 vrpdr = 0;
- u32 vrdbr = 0;
-
- adinr = rsnd_get_adinr_bit(mod, io) |
- rsnd_runtime_channel_after_ctu(io);
-
- /* Enable Digital Volume, Zero Cross Mute Mode */
- dvucr |= 0x101;
-
- /* Enable Ramp */
- if (rsnd_kctrl_vals(dvc->ren)) {
- dvucr |= 0x10;
-
- /*
- * FIXME !!
- * use scale-downed Digital Volume
- * as Volume Ramp
- * 7F FFFF -> 3FF
- */
- vrctr = 0xff;
- vrpdr = rsnd_dvc_get_vrpdr(dvc);
- vrdbr = rsnd_dvc_get_vrdbr(dvc);
- }
-
- /* Initialize operation */
- rsnd_mod_write(mod, DVC_DVUIR, 1);
-
- /* General Information */
- rsnd_mod_write(mod, DVC_ADINR, adinr);
- rsnd_mod_write(mod, DVC_DVUCR, dvucr);
-
- /* Volume Ramp Parameter */
- rsnd_mod_write(mod, DVC_VRCTR, vrctr);
- rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
- rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
-
- /* Digital Volume Function Parameter */
- rsnd_dvc_volume_parameter(io, mod);
-
- /* cancel operation */
- rsnd_mod_write(mod, DVC_DVUIR, 0);
-}
-
-static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
- u32 zcmcr = 0;
- u32 vrpdr = 0;
- u32 vrdbr = 0;
- int i;
-
- for (i = 0; i < rsnd_kctrl_size(dvc->mute); i++)
- zcmcr |= (!!rsnd_kctrl_valm(dvc->mute, i)) << i;
-
- if (rsnd_kctrl_vals(dvc->ren)) {
- vrpdr = rsnd_dvc_get_vrpdr(dvc);
- vrdbr = rsnd_dvc_get_vrdbr(dvc);
- }
-
- /* Disable DVC Register access */
- rsnd_mod_write(mod, DVC_DVUER, 0);
-
- /* Zero Cross Mute Function */
- rsnd_mod_write(mod, DVC_ZCMCR, zcmcr);
-
- /* Volume Ramp Function */
- rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
- rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
- /* add DVC_VRWTR here */
-
- /* Digital Volume Function Parameter */
- rsnd_dvc_volume_parameter(io, mod);
-
- /* Enable DVC Register access */
- rsnd_mod_write(mod, DVC_DVUER, 1);
-}
-
-static int rsnd_dvc_probe_(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- return rsnd_cmd_attach(io, rsnd_mod_id(mod));
-}
-
-static int rsnd_dvc_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- ret = rsnd_mod_power_on(mod);
- if (ret < 0)
- return ret;
-
- rsnd_dvc_activation(mod);
-
- rsnd_dvc_volume_init(io, mod);
-
- rsnd_dvc_volume_update(io, mod);
-
- return 0;
-}
-
-static int rsnd_dvc_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_dvc_halt(mod);
-
- rsnd_mod_power_off(mod);
-
- return 0;
-}
-
-static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd)
-{
- struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- int is_play = rsnd_io_is_play(io);
- int channels = rsnd_rdai_channels_get(rdai);
- int ret;
-
- /* Volume */
- ret = rsnd_kctrl_new_m(mod, io, rtd,
- is_play ?
- "DVC Out Playback Volume" : "DVC In Capture Volume",
- rsnd_kctrl_accept_anytime,
- rsnd_dvc_volume_update,
- &dvc->volume, channels,
- 0x00800000 - 1);
- if (ret < 0)
- return ret;
-
- /* Mute */
- ret = rsnd_kctrl_new_m(mod, io, rtd,
- is_play ?
- "DVC Out Mute Switch" : "DVC In Mute Switch",
- rsnd_kctrl_accept_anytime,
- rsnd_dvc_volume_update,
- &dvc->mute, channels,
- 1);
- if (ret < 0)
- return ret;
-
- /* Ramp */
- ret = rsnd_kctrl_new_s(mod, io, rtd,
- is_play ?
- "DVC Out Ramp Switch" : "DVC In Ramp Switch",
- rsnd_kctrl_accept_anytime,
- rsnd_dvc_volume_update,
- &dvc->ren, 1);
- if (ret < 0)
- return ret;
-
- ret = rsnd_kctrl_new_e(mod, io, rtd,
- is_play ?
- "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate",
- rsnd_kctrl_accept_anytime,
- rsnd_dvc_volume_update,
- &dvc->rup,
- volume_ramp_rate,
- VOLUME_RAMP_MAX_DVC);
- if (ret < 0)
- return ret;
-
- ret = rsnd_kctrl_new_e(mod, io, rtd,
- is_play ?
- "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate",
- rsnd_kctrl_accept_anytime,
- rsnd_dvc_volume_update,
- &dvc->rdown,
- volume_ramp_rate,
- VOLUME_RAMP_MAX_DVC);
-
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-
- return rsnd_dma_request_channel(rsnd_dvc_of_node(priv),
- DVC_NAME, mod, "tx");
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_dvc_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0xe00 + rsnd_mod_id(mod) * 0x100, 0x60);
-}
-#define DEBUG_INFO .debug_info = rsnd_dvc_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_dvc_ops = {
- .name = DVC_NAME,
- .dma_req = rsnd_dvc_dma_req,
- .probe = rsnd_dvc_probe_,
- .init = rsnd_dvc_init,
- .quit = rsnd_dvc_quit,
- .pcm_new = rsnd_dvc_pcm_new,
- .get_status = rsnd_mod_get_status,
- DEBUG_INFO
-};
-
-struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv)))
- id = 0;
-
- return rsnd_mod_get(rsnd_dvc_get(priv, id));
-}
-
-int rsnd_dvc_probe(struct rsnd_priv *priv)
-{
- struct device_node *node;
- struct device_node *np;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_dvc *dvc;
- struct clk *clk;
- char name[RSND_DVC_NAME_SIZE];
- int i, nr, ret;
-
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
- node = rsnd_dvc_of_node(priv);
- if (!node)
- return 0; /* not used is not error */
-
- nr = of_get_child_count(node);
- if (!nr) {
- ret = -EINVAL;
- goto rsnd_dvc_probe_done;
- }
-
- dvc = devm_kcalloc(dev, nr, sizeof(*dvc), GFP_KERNEL);
- if (!dvc) {
- ret = -ENOMEM;
- goto rsnd_dvc_probe_done;
- }
-
- priv->dvc_nr = nr;
- priv->dvc = dvc;
-
- i = 0;
- ret = 0;
- for_each_child_of_node(node, np) {
- dvc = rsnd_dvc_get(priv, i);
-
- snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d",
- DVC_NAME, i);
-
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- of_node_put(np);
- goto rsnd_dvc_probe_done;
- }
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops,
- clk, RSND_MOD_DVC, i);
- if (ret) {
- of_node_put(np);
- goto rsnd_dvc_probe_done;
- }
-
- i++;
- }
-
-rsnd_dvc_probe_done:
- of_node_put(node);
-
- return ret;
-}
-
-void rsnd_dvc_remove(struct rsnd_priv *priv)
-{
- struct rsnd_dvc *dvc;
- int i;
-
- for_each_rsnd_dvc(dvc, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(dvc));
- }
-}
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
deleted file mode 100644
index 86bdecc24956..000000000000
--- a/sound/soc/sh/rcar/gen.c
+++ /dev/null
@@ -1,562 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car Gen1 SRU/SSI support
-//
-// Copyright (C) 2013 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-/*
- * #define DEBUG
- *
- * you can also add below in
- * ${LINUX}/drivers/base/regmap/regmap.c
- * for regmap debug
- *
- * #define LOG_DEVICE "xxxx.rcar_sound"
- */
-
-#include "rsnd.h"
-
-struct rsnd_gen {
- struct rsnd_gen_ops *ops;
-
- /* RSND_BASE_MAX base */
- void __iomem *base[RSND_BASE_MAX];
- phys_addr_t res[RSND_BASE_MAX];
- struct regmap *regmap[RSND_BASE_MAX];
-
- /* RSND_REG_MAX base */
- struct regmap_field *regs[REG_MAX];
- const char *reg_name[REG_MAX];
-};
-
-#define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
-#define rsnd_reg_name(gen, id) ((gen)->reg_name[id])
-
-struct rsnd_regmap_field_conf {
- int idx;
- unsigned int reg_offset;
- unsigned int id_offset;
- const char *reg_name;
-};
-
-#define RSND_REG_SET(id, offset, _id_offset, n) \
-{ \
- .idx = id, \
- .reg_offset = offset, \
- .id_offset = _id_offset, \
- .reg_name = n, \
-}
-/* single address mapping */
-#define RSND_GEN_S_REG(id, offset) \
- RSND_REG_SET(id, offset, 0, #id)
-
-/* multi address mapping */
-#define RSND_GEN_M_REG(id, offset, _id_offset) \
- RSND_REG_SET(id, offset, _id_offset, #id)
-
-/*
- * basic function
- */
-static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
- struct rsnd_gen *gen, enum rsnd_reg reg)
-{
- if (!gen->regs[reg]) {
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_err(dev, "unsupported register access %x\n", reg);
- return 0;
- }
-
- return 1;
-}
-
-static int rsnd_mod_id_cmd(struct rsnd_mod *mod)
-{
- if (mod->ops->id_cmd)
- return mod->ops->id_cmd(mod);
-
- return rsnd_mod_id(mod);
-}
-
-u32 rsnd_mod_read(struct rsnd_mod *mod, enum rsnd_reg reg)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
- u32 val;
-
- if (!rsnd_is_accessible_reg(priv, gen, reg))
- return 0;
-
- regmap_fields_read(gen->regs[reg], rsnd_mod_id_cmd(mod), &val);
-
- dev_dbg(dev, "r %s - %-18s (%4d) : %08x\n",
- rsnd_mod_name(mod),
- rsnd_reg_name(gen, reg), reg, val);
-
- return val;
-}
-
-void rsnd_mod_write(struct rsnd_mod *mod,
- enum rsnd_reg reg, u32 data)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
- if (!rsnd_is_accessible_reg(priv, gen, reg))
- return;
-
- regmap_fields_force_write(gen->regs[reg], rsnd_mod_id_cmd(mod), data);
-
- dev_dbg(dev, "w %s - %-18s (%4d) : %08x\n",
- rsnd_mod_name(mod),
- rsnd_reg_name(gen, reg), reg, data);
-}
-
-void rsnd_mod_bset(struct rsnd_mod *mod,
- enum rsnd_reg reg, u32 mask, u32 data)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
- if (!rsnd_is_accessible_reg(priv, gen, reg))
- return;
-
- regmap_fields_force_update_bits(gen->regs[reg],
- rsnd_mod_id_cmd(mod), mask, data);
-
- dev_dbg(dev, "b %s - %-18s (%4d) : %08x/%08x\n",
- rsnd_mod_name(mod),
- rsnd_reg_name(gen, reg), reg, data, mask);
-
-}
-
-phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id)
-{
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
- return gen->res[reg_id];
-}
-
-#ifdef CONFIG_DEBUG_FS
-void __iomem *rsnd_gen_get_base_addr(struct rsnd_priv *priv, int reg_id)
-{
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
- return gen->base[reg_id];
-}
-#endif
-
-#define rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf) \
- _rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf, ARRAY_SIZE(conf))
-static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
- int id_size,
- int reg_id,
- const char *name,
- const struct rsnd_regmap_field_conf *conf,
- int conf_size)
-{
- struct platform_device *pdev = rsnd_priv_to_pdev(priv);
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct resource *res;
- struct regmap_config regc;
- struct regmap_field *regs;
- struct regmap *regmap;
- struct reg_field regf;
- void __iomem *base;
- int i;
-
- memset(&regc, 0, sizeof(regc));
- regc.reg_bits = 32;
- regc.val_bits = 32;
- regc.reg_stride = 4;
- regc.name = name;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
- if (!res)
- res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id);
- if (!res)
- return -ENODEV;
-
- base = devm_ioremap_resource(dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- regmap = devm_regmap_init_mmio(dev, base, &regc);
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
-
- /* RSND_BASE_MAX base */
- gen->base[reg_id] = base;
- gen->regmap[reg_id] = regmap;
- gen->res[reg_id] = res->start;
-
- for (i = 0; i < conf_size; i++) {
-
- regf.reg = conf[i].reg_offset;
- regf.id_offset = conf[i].id_offset;
- regf.lsb = 0;
- regf.msb = 31;
- regf.id_size = id_size;
-
- regs = devm_regmap_field_alloc(dev, regmap, regf);
- if (IS_ERR(regs))
- return PTR_ERR(regs);
-
- /* RSND_REG_MAX base */
- gen->regs[conf[i].idx] = regs;
- gen->reg_name[conf[i].idx] = conf[i].reg_name;
- }
-
- return 0;
-}
-
-/*
- * Gen4
- */
-static int rsnd_gen4_probe(struct rsnd_priv *priv)
-{
- static const struct rsnd_regmap_field_conf conf_ssiu[] = {
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898),
- RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840),
- RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848),
- RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880),
- RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888),
-
- RSND_GEN_S_REG(SSI_BUSIF0_MODE, 0x0),
- RSND_GEN_S_REG(SSI_BUSIF0_ADINR, 0x4),
- RSND_GEN_S_REG(SSI_BUSIF0_DALIGN, 0x8),
- RSND_GEN_S_REG(SSI_BUSIF1_MODE, 0x20),
- RSND_GEN_S_REG(SSI_BUSIF1_ADINR, 0x24),
- RSND_GEN_S_REG(SSI_BUSIF1_DALIGN, 0x28),
- RSND_GEN_S_REG(SSI_BUSIF2_MODE, 0x40),
- RSND_GEN_S_REG(SSI_BUSIF2_ADINR, 0x44),
- RSND_GEN_S_REG(SSI_BUSIF2_DALIGN, 0x48),
- RSND_GEN_S_REG(SSI_BUSIF3_MODE, 0x60),
- RSND_GEN_S_REG(SSI_BUSIF3_ADINR, 0x64),
- RSND_GEN_S_REG(SSI_BUSIF3_DALIGN, 0x68),
- RSND_GEN_S_REG(SSI_BUSIF4_MODE, 0x500),
- RSND_GEN_S_REG(SSI_BUSIF4_ADINR, 0x504),
- RSND_GEN_S_REG(SSI_BUSIF4_DALIGN, 0x508),
- RSND_GEN_S_REG(SSI_BUSIF5_MODE, 0x520),
- RSND_GEN_S_REG(SSI_BUSIF5_ADINR, 0x524),
- RSND_GEN_S_REG(SSI_BUSIF5_DALIGN, 0x528),
- RSND_GEN_S_REG(SSI_BUSIF6_MODE, 0x540),
- RSND_GEN_S_REG(SSI_BUSIF6_ADINR, 0x544),
- RSND_GEN_S_REG(SSI_BUSIF6_DALIGN, 0x548),
- RSND_GEN_S_REG(SSI_BUSIF7_MODE, 0x560),
- RSND_GEN_S_REG(SSI_BUSIF7_ADINR, 0x564),
- RSND_GEN_S_REG(SSI_BUSIF7_DALIGN, 0x568),
- RSND_GEN_S_REG(SSI_CTRL, 0x010),
- RSND_GEN_S_REG(SSI_INT_ENABLE, 0x018),
- RSND_GEN_S_REG(SSI_MODE, 0x00c),
- RSND_GEN_S_REG(SSI_MODE2, 0xa0c),
- };
- static const struct rsnd_regmap_field_conf conf_adg[] = {
- RSND_GEN_S_REG(BRRA, 0x00),
- RSND_GEN_S_REG(BRRB, 0x04),
- RSND_GEN_S_REG(BRGCKR, 0x08),
- RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
- };
- static const struct rsnd_regmap_field_conf conf_ssi[] = {
- RSND_GEN_S_REG(SSICR, 0x00),
- RSND_GEN_S_REG(SSISR, 0x04),
- RSND_GEN_S_REG(SSITDR, 0x08),
- RSND_GEN_S_REG(SSIRDR, 0x0c),
- RSND_GEN_S_REG(SSIWSR, 0x20),
- };
- static const struct rsnd_regmap_field_conf conf_sdmc[] = {
- RSND_GEN_M_REG(SSI_BUSIF, 0x0, 0x8000),
- };
- int ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_ADG, "adg", conf_adg);
- int ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSIU, "ssiu", conf_ssiu);
- int ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSI, "ssi", conf_ssi);
- int ret_sdmc = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SDMC, "sdmc", conf_sdmc);
-
- return ret_adg | ret_ssiu | ret_ssi | ret_sdmc;
-}
-
-/*
- * Gen2
- */
-static int rsnd_gen2_probe(struct rsnd_priv *priv)
-{
- static const struct rsnd_regmap_field_conf conf_ssiu[] = {
- RSND_GEN_S_REG(SSI_MODE0, 0x800),
- RSND_GEN_S_REG(SSI_MODE1, 0x804),
- RSND_GEN_S_REG(SSI_MODE2, 0x808),
- RSND_GEN_S_REG(SSI_CONTROL, 0x810),
- RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840),
- RSND_GEN_S_REG(SSI_SYS_STATUS1, 0x844),
- RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848),
- RSND_GEN_S_REG(SSI_SYS_STATUS3, 0x84c),
- RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880),
- RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884),
- RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888),
- RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE1, 0x854),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE3, 0x85c),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE5, 0x894),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE7, 0x89c),
- RSND_GEN_S_REG(HDMI0_SEL, 0x9e0),
- RSND_GEN_S_REG(HDMI1_SEL, 0x9e4),
-
- /* FIXME: it needs SSI_MODE2/3 in the future */
- RSND_GEN_M_REG(SSI_BUSIF0_MODE, 0x0, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF0_ADINR, 0x4, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF0_DALIGN, 0x8, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF1_MODE, 0x20, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF1_ADINR, 0x24, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF1_DALIGN, 0x28, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF2_MODE, 0x40, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF2_ADINR, 0x44, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF2_DALIGN, 0x48, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF3_MODE, 0x60, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF3_ADINR, 0x64, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF3_DALIGN, 0x68, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF4_MODE, 0x500, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF4_ADINR, 0x504, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF4_DALIGN, 0x508, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF5_MODE, 0x520, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF5_ADINR, 0x524, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF5_DALIGN, 0x528, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF6_MODE, 0x540, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF6_ADINR, 0x544, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF6_DALIGN, 0x548, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF7_MODE, 0x560, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF7_ADINR, 0x564, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF7_DALIGN, 0x568, 0x80),
- RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80),
- RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80),
- RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80),
- RSND_GEN_S_REG(SSI9_BUSIF0_MODE, 0x48c),
- RSND_GEN_S_REG(SSI9_BUSIF0_ADINR, 0x484),
- RSND_GEN_S_REG(SSI9_BUSIF0_DALIGN, 0x488),
- RSND_GEN_S_REG(SSI9_BUSIF1_MODE, 0x4a0),
- RSND_GEN_S_REG(SSI9_BUSIF1_ADINR, 0x4a4),
- RSND_GEN_S_REG(SSI9_BUSIF1_DALIGN, 0x4a8),
- RSND_GEN_S_REG(SSI9_BUSIF2_MODE, 0x4c0),
- RSND_GEN_S_REG(SSI9_BUSIF2_ADINR, 0x4c4),
- RSND_GEN_S_REG(SSI9_BUSIF2_DALIGN, 0x4c8),
- RSND_GEN_S_REG(SSI9_BUSIF3_MODE, 0x4e0),
- RSND_GEN_S_REG(SSI9_BUSIF3_ADINR, 0x4e4),
- RSND_GEN_S_REG(SSI9_BUSIF3_DALIGN, 0x4e8),
- RSND_GEN_S_REG(SSI9_BUSIF4_MODE, 0xd80),
- RSND_GEN_S_REG(SSI9_BUSIF4_ADINR, 0xd84),
- RSND_GEN_S_REG(SSI9_BUSIF4_DALIGN, 0xd88),
- RSND_GEN_S_REG(SSI9_BUSIF5_MODE, 0xda0),
- RSND_GEN_S_REG(SSI9_BUSIF5_ADINR, 0xda4),
- RSND_GEN_S_REG(SSI9_BUSIF5_DALIGN, 0xda8),
- RSND_GEN_S_REG(SSI9_BUSIF6_MODE, 0xdc0),
- RSND_GEN_S_REG(SSI9_BUSIF6_ADINR, 0xdc4),
- RSND_GEN_S_REG(SSI9_BUSIF6_DALIGN, 0xdc8),
- RSND_GEN_S_REG(SSI9_BUSIF7_MODE, 0xde0),
- RSND_GEN_S_REG(SSI9_BUSIF7_ADINR, 0xde4),
- RSND_GEN_S_REG(SSI9_BUSIF7_DALIGN, 0xde8),
- };
-
- static const struct rsnd_regmap_field_conf conf_scu[] = {
- RSND_GEN_M_REG(SRC_I_BUSIF_MODE,0x0, 0x20),
- RSND_GEN_M_REG(SRC_O_BUSIF_MODE,0x4, 0x20),
- RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20),
- RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
- RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
- RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20),
- RSND_GEN_M_REG(CMD_BUSIF_MODE, 0x184, 0x20),
- RSND_GEN_M_REG(CMD_BUSIF_DALIGN,0x188, 0x20),
- RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20),
- RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20),
- RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8),
- RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc),
- RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0),
- RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1d4),
- RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40),
- RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40),
- RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40),
- RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40),
- RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40),
- RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40),
- RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40),
- RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40),
- RSND_GEN_M_REG(CTU_SWRSR, 0x500, 0x100),
- RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100),
- RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100),
- RSND_GEN_M_REG(CTU_CPMDR, 0x510, 0x100),
- RSND_GEN_M_REG(CTU_SCMDR, 0x514, 0x100),
- RSND_GEN_M_REG(CTU_SV00R, 0x518, 0x100),
- RSND_GEN_M_REG(CTU_SV01R, 0x51c, 0x100),
- RSND_GEN_M_REG(CTU_SV02R, 0x520, 0x100),
- RSND_GEN_M_REG(CTU_SV03R, 0x524, 0x100),
- RSND_GEN_M_REG(CTU_SV04R, 0x528, 0x100),
- RSND_GEN_M_REG(CTU_SV05R, 0x52c, 0x100),
- RSND_GEN_M_REG(CTU_SV06R, 0x530, 0x100),
- RSND_GEN_M_REG(CTU_SV07R, 0x534, 0x100),
- RSND_GEN_M_REG(CTU_SV10R, 0x538, 0x100),
- RSND_GEN_M_REG(CTU_SV11R, 0x53c, 0x100),
- RSND_GEN_M_REG(CTU_SV12R, 0x540, 0x100),
- RSND_GEN_M_REG(CTU_SV13R, 0x544, 0x100),
- RSND_GEN_M_REG(CTU_SV14R, 0x548, 0x100),
- RSND_GEN_M_REG(CTU_SV15R, 0x54c, 0x100),
- RSND_GEN_M_REG(CTU_SV16R, 0x550, 0x100),
- RSND_GEN_M_REG(CTU_SV17R, 0x554, 0x100),
- RSND_GEN_M_REG(CTU_SV20R, 0x558, 0x100),
- RSND_GEN_M_REG(CTU_SV21R, 0x55c, 0x100),
- RSND_GEN_M_REG(CTU_SV22R, 0x560, 0x100),
- RSND_GEN_M_REG(CTU_SV23R, 0x564, 0x100),
- RSND_GEN_M_REG(CTU_SV24R, 0x568, 0x100),
- RSND_GEN_M_REG(CTU_SV25R, 0x56c, 0x100),
- RSND_GEN_M_REG(CTU_SV26R, 0x570, 0x100),
- RSND_GEN_M_REG(CTU_SV27R, 0x574, 0x100),
- RSND_GEN_M_REG(CTU_SV30R, 0x578, 0x100),
- RSND_GEN_M_REG(CTU_SV31R, 0x57c, 0x100),
- RSND_GEN_M_REG(CTU_SV32R, 0x580, 0x100),
- RSND_GEN_M_REG(CTU_SV33R, 0x584, 0x100),
- RSND_GEN_M_REG(CTU_SV34R, 0x588, 0x100),
- RSND_GEN_M_REG(CTU_SV35R, 0x58c, 0x100),
- RSND_GEN_M_REG(CTU_SV36R, 0x590, 0x100),
- RSND_GEN_M_REG(CTU_SV37R, 0x594, 0x100),
- RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40),
- RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40),
- RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40),
- RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40),
- RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40),
- RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40),
- RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40),
- RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40),
- RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40),
- RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40),
- RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100),
- RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100),
- RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100),
- RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100),
- RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100),
- RSND_GEN_M_REG(DVC_VRCTR, 0xe18, 0x100),
- RSND_GEN_M_REG(DVC_VRPDR, 0xe1c, 0x100),
- RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100),
- RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100),
- RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100),
- RSND_GEN_M_REG(DVC_VOL2R, 0xe30, 0x100),
- RSND_GEN_M_REG(DVC_VOL3R, 0xe34, 0x100),
- RSND_GEN_M_REG(DVC_VOL4R, 0xe38, 0x100),
- RSND_GEN_M_REG(DVC_VOL5R, 0xe3c, 0x100),
- RSND_GEN_M_REG(DVC_VOL6R, 0xe40, 0x100),
- RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100),
- RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100),
- };
- static const struct rsnd_regmap_field_conf conf_adg[] = {
- RSND_GEN_S_REG(BRRA, 0x00),
- RSND_GEN_S_REG(BRRB, 0x04),
- RSND_GEN_S_REG(BRGCKR, 0x08),
- RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
- RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
- RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14),
- RSND_GEN_S_REG(DIV_EN, 0x30),
- RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34),
- RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38),
- RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c),
- RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40),
- RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44),
- RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48),
- RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c),
- RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50),
- RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54),
- RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58),
- RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c),
- };
- static const struct rsnd_regmap_field_conf conf_ssi[] = {
- RSND_GEN_M_REG(SSICR, 0x00, 0x40),
- RSND_GEN_M_REG(SSISR, 0x04, 0x40),
- RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
- RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40),
- RSND_GEN_M_REG(SSIWSR, 0x20, 0x40),
- };
- int ret_ssiu;
- int ret_scu;
- int ret_adg;
- int ret_ssi;
-
- ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, "ssiu", conf_ssiu);
- ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, "scu", conf_scu);
- ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG, "adg", conf_adg);
- ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, "ssi", conf_ssi);
- if (ret_ssiu < 0 ||
- ret_scu < 0 ||
- ret_adg < 0 ||
- ret_ssi < 0)
- return ret_ssiu | ret_scu | ret_adg | ret_ssi;
-
- return 0;
-}
-
-/*
- * Gen1
- */
-
-static int rsnd_gen1_probe(struct rsnd_priv *priv)
-{
- static const struct rsnd_regmap_field_conf conf_adg[] = {
- RSND_GEN_S_REG(BRRA, 0x00),
- RSND_GEN_S_REG(BRRB, 0x04),
- RSND_GEN_S_REG(BRGCKR, 0x08),
- RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
- RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
- };
- static const struct rsnd_regmap_field_conf conf_ssi[] = {
- RSND_GEN_M_REG(SSICR, 0x00, 0x40),
- RSND_GEN_M_REG(SSISR, 0x04, 0x40),
- RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
- RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40),
- RSND_GEN_M_REG(SSIWSR, 0x20, 0x40),
- };
- int ret_adg;
- int ret_ssi;
-
- ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, "adg", conf_adg);
- ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, "ssi", conf_ssi);
- if (ret_adg < 0 ||
- ret_ssi < 0)
- return ret_adg | ret_ssi;
-
- return 0;
-}
-
-/*
- * Gen
- */
-int rsnd_gen_probe(struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_gen *gen;
- int ret;
-
- gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
- if (!gen)
- return -ENOMEM;
-
- priv->gen = gen;
-
- ret = -ENODEV;
- if (rsnd_is_gen1(priv))
- ret = rsnd_gen1_probe(priv);
- else if (rsnd_is_gen2(priv) ||
- rsnd_is_gen3(priv))
- ret = rsnd_gen2_probe(priv);
- else if (rsnd_is_gen4(priv))
- ret = rsnd_gen4_probe(priv);
-
- if (ret < 0)
- dev_err(dev, "unknown generation R-Car sound device\n");
-
- return ret;
-}
diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c
deleted file mode 100644
index 1de0e085804c..000000000000
--- a/sound/soc/sh/rcar/mix.c
+++ /dev/null
@@ -1,360 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// mix.c
-//
-// Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-/*
- * CTUn MIXn
- * +------+ +------+
- * [SRC3 / SRC6] -> |CTU n0| -> [MIX n0| ->
- * [SRC4 / SRC9] -> |CTU n1| -> [MIX n1| ->
- * [SRC0 / SRC1] -> |CTU n2| -> [MIX n2| ->
- * [SRC2 / SRC5] -> |CTU n3| -> [MIX n3| ->
- * +------+ +------+
- *
- * ex)
- * DAI0 : playback = <&src0 &ctu02 &mix0 &dvc0 &ssi0>;
- * DAI1 : playback = <&src2 &ctu03 &mix0 &dvc0 &ssi0>;
- *
- * MIX Volume
- * amixer set "MIX",0 100% // DAI0 Volume
- * amixer set "MIX",1 100% // DAI1 Volume
- *
- * Volume Ramp
- * amixer set "MIX Ramp Up Rate" "0.125 dB/1 step"
- * amixer set "MIX Ramp Down Rate" "4 dB/1 step"
- * amixer set "MIX Ramp" on
- * aplay xxx.wav &
- * amixer set "MIX",0 80% // DAI0 Volume Down
- * amixer set "MIX",1 100% // DAI1 Volume Up
- */
-
-#include "rsnd.h"
-
-#define MIX_NAME_SIZE 16
-#define MIX_NAME "mix"
-
-struct rsnd_mix {
- struct rsnd_mod mod;
- struct rsnd_kctrl_cfg_s volumeA; /* MDBAR */
- struct rsnd_kctrl_cfg_s volumeB; /* MDBBR */
- struct rsnd_kctrl_cfg_s volumeC; /* MDBCR */
- struct rsnd_kctrl_cfg_s volumeD; /* MDBDR */
- struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */
- struct rsnd_kctrl_cfg_s rup; /* Ramp Rate Up */
- struct rsnd_kctrl_cfg_s rdw; /* Ramp Rate Down */
- u32 flags;
-};
-
-#define ONCE_KCTRL_INITIALIZED (1 << 0)
-#define HAS_VOLA (1 << 1)
-#define HAS_VOLB (1 << 2)
-#define HAS_VOLC (1 << 3)
-#define HAS_VOLD (1 << 4)
-
-#define VOL_MAX 0x3ff
-
-#define rsnd_mod_to_mix(_mod) \
- container_of((_mod), struct rsnd_mix, mod)
-
-#define rsnd_mix_get(priv, id) ((struct rsnd_mix *)(priv->mix) + id)
-#define rsnd_mix_nr(priv) ((priv)->mix_nr)
-#define for_each_rsnd_mix(pos, priv, i) \
- for ((i) = 0; \
- ((i) < rsnd_mix_nr(priv)) && \
- ((pos) = (struct rsnd_mix *)(priv)->mix + i); \
- i++)
-
-static void rsnd_mix_activation(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, MIX_SWRSR, 0);
- rsnd_mod_write(mod, MIX_SWRSR, 1);
-}
-
-static void rsnd_mix_halt(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, MIX_MIXIR, 1);
- rsnd_mod_write(mod, MIX_SWRSR, 0);
-}
-
-#define rsnd_mix_get_vol(mix, X) \
- rsnd_flags_has(mix, HAS_VOL##X) ? \
- (VOL_MAX - rsnd_kctrl_vals(mix->volume##X)) : 0
-static void rsnd_mix_volume_parameter(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mix *mix = rsnd_mod_to_mix(mod);
- u32 volA = rsnd_mix_get_vol(mix, A);
- u32 volB = rsnd_mix_get_vol(mix, B);
- u32 volC = rsnd_mix_get_vol(mix, C);
- u32 volD = rsnd_mix_get_vol(mix, D);
-
- dev_dbg(dev, "MIX A/B/C/D = %02x/%02x/%02x/%02x\n",
- volA, volB, volC, volD);
-
- rsnd_mod_write(mod, MIX_MDBAR, volA);
- rsnd_mod_write(mod, MIX_MDBBR, volB);
- rsnd_mod_write(mod, MIX_MDBCR, volC);
- rsnd_mod_write(mod, MIX_MDBDR, volD);
-}
-
-static void rsnd_mix_volume_init(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_mix *mix = rsnd_mod_to_mix(mod);
-
- rsnd_mod_write(mod, MIX_MIXIR, 1);
-
- /* General Information */
- rsnd_mod_write(mod, MIX_ADINR, rsnd_runtime_channel_after_ctu(io));
-
- /* volume step */
- rsnd_mod_write(mod, MIX_MIXMR, rsnd_kctrl_vals(mix->ren));
- rsnd_mod_write(mod, MIX_MVPDR, rsnd_kctrl_vals(mix->rup) << 8 |
- rsnd_kctrl_vals(mix->rdw));
-
- /* common volume parameter */
- rsnd_mix_volume_parameter(io, mod);
-
- rsnd_mod_write(mod, MIX_MIXIR, 0);
-}
-
-static void rsnd_mix_volume_update(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- /* Disable MIX dB setting */
- rsnd_mod_write(mod, MIX_MDBER, 0);
-
- /* common volume parameter */
- rsnd_mix_volume_parameter(io, mod);
-
- /* Enable MIX dB setting */
- rsnd_mod_write(mod, MIX_MDBER, 1);
-}
-
-static int rsnd_mix_probe_(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- return rsnd_cmd_attach(io, rsnd_mod_id(mod));
-}
-
-static int rsnd_mix_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- ret = rsnd_mod_power_on(mod);
- if (ret < 0)
- return ret;
-
- rsnd_mix_activation(mod);
-
- rsnd_mix_volume_init(io, mod);
-
- rsnd_mix_volume_update(io, mod);
-
- return 0;
-}
-
-static int rsnd_mix_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_mix_halt(mod);
-
- rsnd_mod_power_off(mod);
-
- return 0;
-}
-
-static int rsnd_mix_pcm_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mix *mix = rsnd_mod_to_mix(mod);
- struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
- struct rsnd_kctrl_cfg_s *volume;
- int ret;
-
- switch (rsnd_mod_id(src_mod)) {
- case 3:
- case 6: /* MDBAR */
- volume = &mix->volumeA;
- rsnd_flags_set(mix, HAS_VOLA);
- break;
- case 4:
- case 9: /* MDBBR */
- volume = &mix->volumeB;
- rsnd_flags_set(mix, HAS_VOLB);
- break;
- case 0:
- case 1: /* MDBCR */
- volume = &mix->volumeC;
- rsnd_flags_set(mix, HAS_VOLC);
- break;
- case 2:
- case 5: /* MDBDR */
- volume = &mix->volumeD;
- rsnd_flags_set(mix, HAS_VOLD);
- break;
- default:
- dev_err(dev, "unknown SRC is connected\n");
- return -EINVAL;
- }
-
- /* Volume */
- ret = rsnd_kctrl_new_s(mod, io, rtd,
- "MIX Playback Volume",
- rsnd_kctrl_accept_anytime,
- rsnd_mix_volume_update,
- volume, VOL_MAX);
- if (ret < 0)
- return ret;
- rsnd_kctrl_vals(*volume) = VOL_MAX;
-
- if (rsnd_flags_has(mix, ONCE_KCTRL_INITIALIZED))
- return ret;
-
- /* Ramp */
- ret = rsnd_kctrl_new_s(mod, io, rtd,
- "MIX Ramp Switch",
- rsnd_kctrl_accept_anytime,
- rsnd_mix_volume_update,
- &mix->ren, 1);
- if (ret < 0)
- return ret;
-
- ret = rsnd_kctrl_new_e(mod, io, rtd,
- "MIX Ramp Up Rate",
- rsnd_kctrl_accept_anytime,
- rsnd_mix_volume_update,
- &mix->rup,
- volume_ramp_rate,
- VOLUME_RAMP_MAX_MIX);
- if (ret < 0)
- return ret;
-
- ret = rsnd_kctrl_new_e(mod, io, rtd,
- "MIX Ramp Down Rate",
- rsnd_kctrl_accept_anytime,
- rsnd_mix_volume_update,
- &mix->rdw,
- volume_ramp_rate,
- VOLUME_RAMP_MAX_MIX);
-
- rsnd_flags_set(mix, ONCE_KCTRL_INITIALIZED);
-
- return ret;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_mix_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0xd00 + rsnd_mod_id(mod) * 0x40, 0x30);
-}
-#define DEBUG_INFO .debug_info = rsnd_mix_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_mix_ops = {
- .name = MIX_NAME,
- .probe = rsnd_mix_probe_,
- .init = rsnd_mix_init,
- .quit = rsnd_mix_quit,
- .pcm_new = rsnd_mix_pcm_new,
- .get_status = rsnd_mod_get_status,
- DEBUG_INFO
-};
-
-struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv)))
- id = 0;
-
- return rsnd_mod_get(rsnd_mix_get(priv, id));
-}
-
-int rsnd_mix_probe(struct rsnd_priv *priv)
-{
- struct device_node *node;
- struct device_node *np;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mix *mix;
- struct clk *clk;
- char name[MIX_NAME_SIZE];
- int i, nr, ret;
-
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
- node = rsnd_mix_of_node(priv);
- if (!node)
- return 0; /* not used is not error */
-
- nr = of_get_child_count(node);
- if (!nr) {
- ret = -EINVAL;
- goto rsnd_mix_probe_done;
- }
-
- mix = devm_kcalloc(dev, nr, sizeof(*mix), GFP_KERNEL);
- if (!mix) {
- ret = -ENOMEM;
- goto rsnd_mix_probe_done;
- }
-
- priv->mix_nr = nr;
- priv->mix = mix;
-
- i = 0;
- ret = 0;
- for_each_child_of_node(node, np) {
- mix = rsnd_mix_get(priv, i);
-
- snprintf(name, MIX_NAME_SIZE, "%s.%d",
- MIX_NAME, i);
-
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- of_node_put(np);
- goto rsnd_mix_probe_done;
- }
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops,
- clk, RSND_MOD_MIX, i);
- if (ret) {
- of_node_put(np);
- goto rsnd_mix_probe_done;
- }
-
- i++;
- }
-
-rsnd_mix_probe_done:
- of_node_put(node);
-
- return ret;
-}
-
-void rsnd_mix_remove(struct rsnd_priv *priv)
-{
- struct rsnd_mix *mix;
- int i;
-
- for_each_rsnd_mix(mix, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(mix));
- }
-}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
deleted file mode 100644
index da716b1f52e4..000000000000
--- a/sound/soc/sh/rcar/rsnd.h
+++ /dev/null
@@ -1,916 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car
-//
-// Copyright (C) 2013 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-#ifndef RSND_H
-#define RSND_H
-
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/sh_dma.h>
-#include <linux/workqueue.h>
-#include <sound/soc.h>
-#include <sound/pcm_params.h>
-
-#define RSND_GEN1_SRU 0
-#define RSND_GEN1_ADG 1
-#define RSND_GEN1_SSI 2
-
-#define RSND_GEN2_SCU 0
-#define RSND_GEN2_ADG 1
-#define RSND_GEN2_SSIU 2
-#define RSND_GEN2_SSI 3
-
-#define RSND_GEN4_ADG 0
-#define RSND_GEN4_SSIU 1
-#define RSND_GEN4_SSI 2
-#define RSND_GEN4_SDMC 3
-
-#define RSND_BASE_MAX 4
-
-/*
- * pseudo register
- *
- * The register address offsets SRU/SCU/SSIU on Gen1/Gen2 are very different.
- * This driver uses pseudo register in order to hide it.
- * see gen1/gen2 for detail
- */
-enum rsnd_reg {
- /* SCU (MIX/CTU/DVC) */
- SRC_I_BUSIF_MODE,
- SRC_O_BUSIF_MODE,
- SRC_ROUTE_MODE0,
- SRC_SWRSR,
- SRC_SRCIR,
- SRC_ADINR,
- SRC_IFSCR,
- SRC_IFSVR,
- SRC_SRCCR,
- SRC_CTRL,
- SRC_BSDSR,
- SRC_BSISR,
- SRC_INT_ENABLE0,
- SRC_BUSIF_DALIGN,
- SRCIN_TIMSEL0,
- SRCIN_TIMSEL1,
- SRCIN_TIMSEL2,
- SRCIN_TIMSEL3,
- SRCIN_TIMSEL4,
- SRCOUT_TIMSEL0,
- SRCOUT_TIMSEL1,
- SRCOUT_TIMSEL2,
- SRCOUT_TIMSEL3,
- SRCOUT_TIMSEL4,
- SCU_SYS_STATUS0,
- SCU_SYS_STATUS1,
- SCU_SYS_INT_EN0,
- SCU_SYS_INT_EN1,
- CMD_CTRL,
- CMD_BUSIF_MODE,
- CMD_BUSIF_DALIGN,
- CMD_ROUTE_SLCT,
- CMDOUT_TIMSEL,
- CTU_SWRSR,
- CTU_CTUIR,
- CTU_ADINR,
- CTU_CPMDR,
- CTU_SCMDR,
- CTU_SV00R,
- CTU_SV01R,
- CTU_SV02R,
- CTU_SV03R,
- CTU_SV04R,
- CTU_SV05R,
- CTU_SV06R,
- CTU_SV07R,
- CTU_SV10R,
- CTU_SV11R,
- CTU_SV12R,
- CTU_SV13R,
- CTU_SV14R,
- CTU_SV15R,
- CTU_SV16R,
- CTU_SV17R,
- CTU_SV20R,
- CTU_SV21R,
- CTU_SV22R,
- CTU_SV23R,
- CTU_SV24R,
- CTU_SV25R,
- CTU_SV26R,
- CTU_SV27R,
- CTU_SV30R,
- CTU_SV31R,
- CTU_SV32R,
- CTU_SV33R,
- CTU_SV34R,
- CTU_SV35R,
- CTU_SV36R,
- CTU_SV37R,
- MIX_SWRSR,
- MIX_MIXIR,
- MIX_ADINR,
- MIX_MIXMR,
- MIX_MVPDR,
- MIX_MDBAR,
- MIX_MDBBR,
- MIX_MDBCR,
- MIX_MDBDR,
- MIX_MDBER,
- DVC_SWRSR,
- DVC_DVUIR,
- DVC_ADINR,
- DVC_DVUCR,
- DVC_ZCMCR,
- DVC_VOL0R,
- DVC_VOL1R,
- DVC_VOL2R,
- DVC_VOL3R,
- DVC_VOL4R,
- DVC_VOL5R,
- DVC_VOL6R,
- DVC_VOL7R,
- DVC_DVUER,
- DVC_VRCTR,
- DVC_VRPDR,
- DVC_VRDBR,
-
- /* ADG */
- BRRA,
- BRRB,
- BRGCKR,
- DIV_EN,
- AUDIO_CLK_SEL0,
- AUDIO_CLK_SEL1,
- AUDIO_CLK_SEL2,
-
- /* SSIU */
- SSI_MODE,
- SSI_MODE0,
- SSI_MODE1,
- SSI_MODE2,
- SSI_CONTROL,
- SSI_CTRL,
- SSI_BUSIF0_MODE,
- SSI_BUSIF1_MODE,
- SSI_BUSIF2_MODE,
- SSI_BUSIF3_MODE,
- SSI_BUSIF4_MODE,
- SSI_BUSIF5_MODE,
- SSI_BUSIF6_MODE,
- SSI_BUSIF7_MODE,
- SSI_BUSIF0_ADINR,
- SSI_BUSIF1_ADINR,
- SSI_BUSIF2_ADINR,
- SSI_BUSIF3_ADINR,
- SSI_BUSIF4_ADINR,
- SSI_BUSIF5_ADINR,
- SSI_BUSIF6_ADINR,
- SSI_BUSIF7_ADINR,
- SSI_BUSIF0_DALIGN,
- SSI_BUSIF1_DALIGN,
- SSI_BUSIF2_DALIGN,
- SSI_BUSIF3_DALIGN,
- SSI_BUSIF4_DALIGN,
- SSI_BUSIF5_DALIGN,
- SSI_BUSIF6_DALIGN,
- SSI_BUSIF7_DALIGN,
- SSI_INT_ENABLE,
- SSI_SYS_STATUS0,
- SSI_SYS_STATUS1,
- SSI_SYS_STATUS2,
- SSI_SYS_STATUS3,
- SSI_SYS_STATUS4,
- SSI_SYS_STATUS5,
- SSI_SYS_STATUS6,
- SSI_SYS_STATUS7,
- SSI_SYS_INT_ENABLE0,
- SSI_SYS_INT_ENABLE1,
- SSI_SYS_INT_ENABLE2,
- SSI_SYS_INT_ENABLE3,
- SSI_SYS_INT_ENABLE4,
- SSI_SYS_INT_ENABLE5,
- SSI_SYS_INT_ENABLE6,
- SSI_SYS_INT_ENABLE7,
- SSI_BUSIF,
- HDMI0_SEL,
- HDMI1_SEL,
- SSI9_BUSIF0_MODE,
- SSI9_BUSIF1_MODE,
- SSI9_BUSIF2_MODE,
- SSI9_BUSIF3_MODE,
- SSI9_BUSIF4_MODE,
- SSI9_BUSIF5_MODE,
- SSI9_BUSIF6_MODE,
- SSI9_BUSIF7_MODE,
- SSI9_BUSIF0_ADINR,
- SSI9_BUSIF1_ADINR,
- SSI9_BUSIF2_ADINR,
- SSI9_BUSIF3_ADINR,
- SSI9_BUSIF4_ADINR,
- SSI9_BUSIF5_ADINR,
- SSI9_BUSIF6_ADINR,
- SSI9_BUSIF7_ADINR,
- SSI9_BUSIF0_DALIGN,
- SSI9_BUSIF1_DALIGN,
- SSI9_BUSIF2_DALIGN,
- SSI9_BUSIF3_DALIGN,
- SSI9_BUSIF4_DALIGN,
- SSI9_BUSIF5_DALIGN,
- SSI9_BUSIF6_DALIGN,
- SSI9_BUSIF7_DALIGN,
-
- /* SSI */
- SSICR,
- SSISR,
- SSITDR,
- SSIRDR,
- SSIWSR,
-
- REG_MAX,
-};
-#define SRCIN_TIMSEL(i) (SRCIN_TIMSEL0 + (i))
-#define SRCOUT_TIMSEL(i) (SRCOUT_TIMSEL0 + (i))
-#define CTU_SVxxR(i, j) (CTU_SV00R + (i * 8) + (j))
-#define DVC_VOLxR(i) (DVC_VOL0R + (i))
-#define AUDIO_CLK_SEL(i) (AUDIO_CLK_SEL0 + (i))
-#define SSI_BUSIF_MODE(i) (SSI_BUSIF0_MODE + (i))
-#define SSI_BUSIF_ADINR(i) (SSI_BUSIF0_ADINR + (i))
-#define SSI_BUSIF_DALIGN(i) (SSI_BUSIF0_DALIGN + (i))
-#define SSI9_BUSIF_MODE(i) (SSI9_BUSIF0_MODE + (i))
-#define SSI9_BUSIF_ADINR(i) (SSI9_BUSIF0_ADINR + (i))
-#define SSI9_BUSIF_DALIGN(i) (SSI9_BUSIF0_DALIGN + (i))
-#define SSI_SYS_STATUS(i) (SSI_SYS_STATUS0 + (i))
-#define SSI_SYS_INT_ENABLE(i) (SSI_SYS_INT_ENABLE0 + (i))
-
-
-struct rsnd_priv;
-struct rsnd_mod;
-struct rsnd_dai;
-struct rsnd_dai_stream;
-
-/*
- * R-Car basic functions
- */
-u32 rsnd_mod_read(struct rsnd_mod *mod, enum rsnd_reg reg);
-void rsnd_mod_write(struct rsnd_mod *mod, enum rsnd_reg reg, u32 data);
-void rsnd_mod_bset(struct rsnd_mod *mod, enum rsnd_reg reg, u32 mask, u32 data);
-u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
-u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
-u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
-
-/*
- * R-Car DMA
- */
-int rsnd_dma_attach(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
-int rsnd_dma_probe(struct rsnd_priv *priv);
-struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, char *name,
- struct rsnd_mod *mod, char *x);
-
-/*
- * R-Car sound mod
- */
-enum rsnd_mod_type {
- RSND_MOD_AUDMAPP,
- RSND_MOD_AUDMA,
- RSND_MOD_DVC,
- RSND_MOD_MIX,
- RSND_MOD_CTU,
- RSND_MOD_CMD,
- RSND_MOD_SRC,
- RSND_MOD_SSIM3, /* SSI multi 3 */
- RSND_MOD_SSIM2, /* SSI multi 2 */
- RSND_MOD_SSIM1, /* SSI multi 1 */
- RSND_MOD_SSIP, /* SSI parent */
- RSND_MOD_SSI,
- RSND_MOD_SSIU,
- RSND_MOD_MAX,
-};
-
-struct rsnd_mod_ops {
- char *name;
- struct dma_chan* (*dma_req)(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod);
- int (*probe)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*remove)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*init)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*quit)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*start)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*stop)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*irq)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv, int enable);
- int (*pcm_new)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd);
- int (*hw_params)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params);
- int (*pointer)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- snd_pcm_uframes_t *pointer);
- int (*fallback)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*prepare)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*cleanup)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*hw_free)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_pcm_substream *substream);
- u32 *(*get_status)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type);
- int (*id)(struct rsnd_mod *mod);
- int (*id_sub)(struct rsnd_mod *mod);
- int (*id_cmd)(struct rsnd_mod *mod);
-
-#ifdef CONFIG_DEBUG_FS
- void (*debug_info)(struct seq_file *m,
- struct rsnd_dai_stream *io, struct rsnd_mod *mod);
-#endif
-};
-
-struct rsnd_dai_stream;
-struct rsnd_mod {
- int id;
- enum rsnd_mod_type type;
- struct rsnd_mod_ops *ops;
- struct rsnd_priv *priv;
- struct clk *clk;
- u32 status;
-};
-/*
- * status
- *
- * 0xH000DCB0
- *
- * B 0: init 1: quit
- * C 0: start 1: stop
- * D 0: hw_params 1: hw_free
- *
- * H is always called (see __rsnd_mod_call)
- */
-#define __rsnd_mod_shift_init 4
-#define __rsnd_mod_shift_quit 4
-#define __rsnd_mod_shift_start 8
-#define __rsnd_mod_shift_stop 8
-#define __rsnd_mod_shift_hw_params 12
-#define __rsnd_mod_shift_hw_free 12
-#define __rsnd_mod_shift_probe 28 /* always called */
-#define __rsnd_mod_shift_remove 28 /* always called */
-#define __rsnd_mod_shift_irq 28 /* always called */
-#define __rsnd_mod_shift_pcm_new 28 /* always called */
-#define __rsnd_mod_shift_fallback 28 /* always called */
-#define __rsnd_mod_shift_pointer 28 /* always called */
-#define __rsnd_mod_shift_prepare 28 /* always called */
-#define __rsnd_mod_shift_cleanup 28 /* always called */
-
-#define __rsnd_mod_add_probe 0
-#define __rsnd_mod_add_remove 0
-#define __rsnd_mod_add_prepare 0
-#define __rsnd_mod_add_cleanup 0
-#define __rsnd_mod_add_init 1 /* needs protect */
-#define __rsnd_mod_add_quit -1 /* needs protect */
-#define __rsnd_mod_add_start 1 /* needs protect */
-#define __rsnd_mod_add_stop -1 /* needs protect */
-#define __rsnd_mod_add_hw_params 1 /* needs protect */
-#define __rsnd_mod_add_hw_free -1 /* needs protect */
-#define __rsnd_mod_add_irq 0
-#define __rsnd_mod_add_pcm_new 0
-#define __rsnd_mod_add_fallback 0
-#define __rsnd_mod_add_pointer 0
-
-#define __rsnd_mod_call_probe 0
-#define __rsnd_mod_call_remove 0
-#define __rsnd_mod_call_prepare 0
-#define __rsnd_mod_call_cleanup 0
-#define __rsnd_mod_call_init 0 /* needs protect */
-#define __rsnd_mod_call_quit 1 /* needs protect */
-#define __rsnd_mod_call_start 0 /* needs protect */
-#define __rsnd_mod_call_stop 1 /* needs protect */
-#define __rsnd_mod_call_hw_params 0 /* needs protect */
-#define __rsnd_mod_call_hw_free 1 /* needs protect */
-#define __rsnd_mod_call_irq 0
-#define __rsnd_mod_call_pcm_new 0
-#define __rsnd_mod_call_fallback 0
-#define __rsnd_mod_call_pointer 0
-
-#define rsnd_mod_to_priv(mod) ((mod)->priv)
-#define rsnd_mod_power_on(mod) clk_enable((mod)->clk)
-#define rsnd_mod_power_off(mod) clk_disable((mod)->clk)
-#define rsnd_mod_get(ip) (&(ip)->mod)
-
-int rsnd_mod_init(struct rsnd_priv *priv,
- struct rsnd_mod *mod,
- struct rsnd_mod_ops *ops,
- struct clk *clk,
- enum rsnd_mod_type type,
- int id);
-void rsnd_mod_quit(struct rsnd_mod *mod);
-struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod);
-void rsnd_mod_interrupt(struct rsnd_mod *mod,
- void (*callback)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io));
-u32 *rsnd_mod_get_status(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type);
-int rsnd_mod_id(struct rsnd_mod *mod);
-int rsnd_mod_id_raw(struct rsnd_mod *mod);
-int rsnd_mod_id_sub(struct rsnd_mod *mod);
-char *rsnd_mod_name(struct rsnd_mod *mod);
-struct rsnd_mod *rsnd_mod_next(int *iterator,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type *array,
- int array_size);
-#define for_each_rsnd_mod(iterator, pos, io) \
- for (iterator = 0; \
- (pos = rsnd_mod_next(&iterator, io, NULL, 0)); iterator++)
-#define for_each_rsnd_mod_arrays(iterator, pos, io, array, size) \
- for (iterator = 0; \
- (pos = rsnd_mod_next(&iterator, io, array, size)); iterator++)
-#define for_each_rsnd_mod_array(iterator, pos, io, array) \
- for_each_rsnd_mod_arrays(iterator, pos, io, array, ARRAY_SIZE(array))
-
-void rsnd_parse_connect_common(struct rsnd_dai *rdai, char *name,
- struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id),
- struct device_node *node,
- struct device_node *playback,
- struct device_node *capture);
-int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name);
-int rsnd_node_fixed_index(struct device *dev, struct device_node *node, char *name, int idx);
-
-int rsnd_channel_normalization(int chan);
-#define rsnd_runtime_channel_original(io) \
- rsnd_runtime_channel_original_with_params(io, NULL)
-int rsnd_runtime_channel_original_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params);
-#define rsnd_runtime_channel_after_ctu(io) \
- rsnd_runtime_channel_after_ctu_with_params(io, NULL)
-int rsnd_runtime_channel_after_ctu_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params);
-#define rsnd_runtime_channel_for_ssi(io) \
- rsnd_runtime_channel_for_ssi_with_params(io, NULL)
-int rsnd_runtime_channel_for_ssi_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params);
-int rsnd_runtime_is_multi_ssi(struct rsnd_dai_stream *io);
-int rsnd_runtime_is_tdm(struct rsnd_dai_stream *io);
-int rsnd_runtime_is_tdm_split(struct rsnd_dai_stream *io);
-
-/*
- * DT
- */
-#define rsnd_parse_of_node(priv, node) \
- of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, node)
-#define RSND_NODE_DAI "rcar_sound,dai"
-#define RSND_NODE_SSI "rcar_sound,ssi"
-#define RSND_NODE_SSIU "rcar_sound,ssiu"
-#define RSND_NODE_SRC "rcar_sound,src"
-#define RSND_NODE_CTU "rcar_sound,ctu"
-#define RSND_NODE_MIX "rcar_sound,mix"
-#define RSND_NODE_DVC "rcar_sound,dvc"
-
-/*
- * R-Car sound DAI
- */
-#define RSND_DAI_NAME_SIZE 16
-struct rsnd_dai_stream {
- char name[RSND_DAI_NAME_SIZE];
- struct snd_pcm_substream *substream;
- struct rsnd_mod *mod[RSND_MOD_MAX];
- struct rsnd_mod *dma;
- struct rsnd_dai *rdai;
- struct device *dmac_dev; /* for IPMMU */
- u32 converted_rate; /* converted sampling rate */
- int converted_chan; /* converted channels */
- u32 parent_ssi_status;
- u32 flags;
-};
-
-/* flags */
-#define RSND_STREAM_HDMI0 (1 << 0) /* for HDMI0 */
-#define RSND_STREAM_HDMI1 (1 << 1) /* for HDMI1 */
-#define RSND_STREAM_TDM_SPLIT (1 << 2) /* for TDM split mode */
-#define RSND_HW_RULE_ERR (1 << 3) /* hw_rule error */
-
-#define rsnd_io_to_mod(io, i) ((i) < RSND_MOD_MAX ? (io)->mod[(i)] : NULL)
-#define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI)
-#define rsnd_io_to_mod_ssiu(io) rsnd_io_to_mod((io), RSND_MOD_SSIU)
-#define rsnd_io_to_mod_ssip(io) rsnd_io_to_mod((io), RSND_MOD_SSIP)
-#define rsnd_io_to_mod_src(io) rsnd_io_to_mod((io), RSND_MOD_SRC)
-#define rsnd_io_to_mod_ctu(io) rsnd_io_to_mod((io), RSND_MOD_CTU)
-#define rsnd_io_to_mod_mix(io) rsnd_io_to_mod((io), RSND_MOD_MIX)
-#define rsnd_io_to_mod_dvc(io) rsnd_io_to_mod((io), RSND_MOD_DVC)
-#define rsnd_io_to_mod_cmd(io) rsnd_io_to_mod((io), RSND_MOD_CMD)
-#define rsnd_io_to_rdai(io) ((io)->rdai)
-#define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io)))
-#define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io)
-#define rsnd_io_to_runtime(io) ((io)->substream ? \
- (io)->substream->runtime : NULL)
-#define rsnd_io_converted_rate(io) ((io)->converted_rate)
-#define rsnd_io_converted_chan(io) ((io)->converted_chan)
-int rsnd_io_is_working(struct rsnd_dai_stream *io);
-
-struct rsnd_dai {
- char name[RSND_DAI_NAME_SIZE];
- struct rsnd_dai_stream playback;
- struct rsnd_dai_stream capture;
- struct rsnd_priv *priv;
- struct snd_pcm_hw_constraint_list constraint;
- struct of_phandle_args dai_args;
-
- int max_channels; /* 2ch - 16ch */
- int ssi_lane; /* 1lane - 4lane */
- int chan_width; /* 16/24/32 bit width */
-
- unsigned int clk_master:1;
- unsigned int bit_clk_inv:1;
- unsigned int frm_clk_inv:1;
- unsigned int sys_delay:1;
- unsigned int data_alignment:1;
-};
-
-#define rsnd_rdai_nr(priv) ((priv)->rdai_nr)
-#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master)
-#define rsnd_rdai_to_priv(rdai) ((rdai)->priv)
-#define for_each_rsnd_dai(rdai, priv, i) \
- for (i = 0; \
- (i < rsnd_rdai_nr(priv)) && \
- ((rdai) = rsnd_rdai_get(priv, i)); \
- i++)
-
-struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id);
-
-#define rsnd_rdai_channels_set(rdai, max_channels) \
- rsnd_rdai_channels_ctrl(rdai, max_channels)
-#define rsnd_rdai_channels_get(rdai) \
- rsnd_rdai_channels_ctrl(rdai, 0)
-int rsnd_rdai_channels_ctrl(struct rsnd_dai *rdai,
- int max_channels);
-
-#define rsnd_rdai_ssi_lane_set(rdai, ssi_lane) \
- rsnd_rdai_ssi_lane_ctrl(rdai, ssi_lane)
-#define rsnd_rdai_ssi_lane_get(rdai) \
- rsnd_rdai_ssi_lane_ctrl(rdai, 0)
-int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai,
- int ssi_lane);
-
-#define rsnd_rdai_width_set(rdai, width) \
- rsnd_rdai_width_ctrl(rdai, width)
-#define rsnd_rdai_width_get(rdai) \
- rsnd_rdai_width_ctrl(rdai, 0)
-int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width);
-void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io);
-int rsnd_dai_connect(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type);
-
-/*
- * R-Car Gen1/Gen2
- */
-int rsnd_gen_probe(struct rsnd_priv *priv);
-void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
- struct rsnd_mod *mod,
- enum rsnd_reg reg);
-phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id);
-#ifdef CONFIG_DEBUG_FS
-void __iomem *rsnd_gen_get_base_addr(struct rsnd_priv *priv, int reg_id);
-#endif
-
-/*
- * R-Car ADG
- */
-int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate);
-int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod);
-int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate);
-int rsnd_adg_probe(struct rsnd_priv *priv);
-void rsnd_adg_remove(struct rsnd_priv *priv);
-int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,
- struct rsnd_dai_stream *io,
- unsigned int in_rate,
- unsigned int out_rate);
-int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
- struct rsnd_dai_stream *io);
-#define rsnd_adg_clk_enable(priv) rsnd_adg_clk_control(priv, 1)
-#define rsnd_adg_clk_disable(priv) rsnd_adg_clk_control(priv, 0)
-void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable);
-void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m);
-
-/*
- * R-Car sound priv
- */
-struct rsnd_priv {
-
- struct platform_device *pdev;
- spinlock_t lock;
- unsigned long flags;
-#define RSND_GEN_MASK (0xF << 0)
-#define RSND_GEN1 (1 << 0)
-#define RSND_GEN2 (2 << 0)
-#define RSND_GEN3 (3 << 0)
-#define RSND_GEN4 (4 << 0)
-#define RSND_SOC_MASK (0xFF << 4)
-#define RSND_SOC_E (1 << 4) /* E1/E2/E3 */
-
- /*
- * below value will be filled on rsnd_gen_probe()
- */
- void *gen;
-
- /*
- * below value will be filled on rsnd_adg_probe()
- */
- void *adg;
-
- /*
- * below value will be filled on rsnd_dma_probe()
- */
- void *dma;
-
- /*
- * below value will be filled on rsnd_ssi_probe()
- */
- void *ssi;
- int ssi_nr;
-
- /*
- * below value will be filled on rsnd_ssiu_probe()
- */
- void *ssiu;
- int ssiu_nr;
-
- /*
- * below value will be filled on rsnd_src_probe()
- */
- void *src;
- int src_nr;
-
- /*
- * below value will be filled on rsnd_ctu_probe()
- */
- void *ctu;
- int ctu_nr;
-
- /*
- * below value will be filled on rsnd_mix_probe()
- */
- void *mix;
- int mix_nr;
-
- /*
- * below value will be filled on rsnd_dvc_probe()
- */
- void *dvc;
- int dvc_nr;
-
- /*
- * below value will be filled on rsnd_cmd_probe()
- */
- void *cmd;
- int cmd_nr;
-
- /*
- * below value will be filled on rsnd_dai_probe()
- */
- struct snd_soc_dai_driver *daidrv;
- struct rsnd_dai *rdai;
- int rdai_nr;
-
-#define RSND_MAX_COMPONENT 3
- int component_dais[RSND_MAX_COMPONENT];
-};
-
-#define rsnd_priv_to_pdev(priv) ((priv)->pdev)
-#define rsnd_priv_to_dev(priv) (&(rsnd_priv_to_pdev(priv)->dev))
-
-#define rsnd_is_gen1(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN1)
-#define rsnd_is_gen2(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN2)
-#define rsnd_is_gen3(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN3)
-#define rsnd_is_gen4(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN4)
-#define rsnd_is_e3(priv) (((priv)->flags & \
- (RSND_GEN_MASK | RSND_SOC_MASK)) == \
- (RSND_GEN3 | RSND_SOC_E))
-
-#define rsnd_flags_has(p, f) ((p)->flags & (f))
-#define rsnd_flags_set(p, f) ((p)->flags |= (f))
-#define rsnd_flags_del(p, f) ((p)->flags &= ~(f))
-
-/*
- * rsnd_kctrl
- */
-struct rsnd_kctrl_cfg {
- unsigned int max;
- unsigned int size;
- u32 *val;
- const char * const *texts;
- int (*accept)(struct rsnd_dai_stream *io);
- void (*update)(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
- struct rsnd_dai_stream *io;
- struct snd_card *card;
- struct snd_kcontrol *kctrl;
- struct rsnd_mod *mod;
-};
-
-#define RSND_MAX_CHANNELS 8
-struct rsnd_kctrl_cfg_m {
- struct rsnd_kctrl_cfg cfg;
- u32 val[RSND_MAX_CHANNELS];
-};
-
-struct rsnd_kctrl_cfg_s {
- struct rsnd_kctrl_cfg cfg;
- u32 val;
-};
-#define rsnd_kctrl_size(x) ((x).cfg.size)
-#define rsnd_kctrl_max(x) ((x).cfg.max)
-#define rsnd_kctrl_valm(x, i) ((x).val[i]) /* = (x).cfg.val[i] */
-#define rsnd_kctrl_vals(x) ((x).val) /* = (x).cfg.val[0] */
-
-int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io);
-int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io);
-struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg);
-struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg);
-int rsnd_kctrl_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd,
- const unsigned char *name,
- int (*accept)(struct rsnd_dai_stream *io),
- void (*update)(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod),
- struct rsnd_kctrl_cfg *cfg,
- const char * const *texts,
- int size,
- u32 max);
-
-#define rsnd_kctrl_new_m(mod, io, rtd, name, accept, update, cfg, size, max) \
- rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_m(cfg), \
- NULL, size, max)
-
-#define rsnd_kctrl_new_s(mod, io, rtd, name, accept, update, cfg, max) \
- rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_s(cfg), \
- NULL, 1, max)
-
-#define rsnd_kctrl_new_e(mod, io, rtd, name, accept, update, cfg, texts, size) \
- rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_s(cfg), \
- texts, 1, size)
-
-extern const char * const volume_ramp_rate[];
-#define VOLUME_RAMP_MAX_DVC (0x17 + 1)
-#define VOLUME_RAMP_MAX_MIX (0x0a + 1)
-
-/*
- * R-Car SSI
- */
-int rsnd_ssi_probe(struct rsnd_priv *priv);
-void rsnd_ssi_remove(struct rsnd_priv *priv);
-struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
-int rsnd_ssi_use_busif(struct rsnd_dai_stream *io);
-u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io);
-int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
-
-#define rsnd_ssi_is_pin_sharing(io) \
- __rsnd_ssi_is_pin_sharing(rsnd_io_to_mod_ssi(io))
-int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
-
-#define rsnd_ssi_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_SSI)
-void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
- struct device_node *playback,
- struct device_node *capture);
-unsigned int rsnd_ssi_clk_query(struct rsnd_dai *rdai,
- int param1, int param2, int *idx);
-
-/*
- * R-Car SSIU
- */
-int rsnd_ssiu_attach(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod);
-int rsnd_ssiu_probe(struct rsnd_priv *priv);
-void rsnd_ssiu_remove(struct rsnd_priv *priv);
-void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
- struct device_node *playback,
- struct device_node *capture);
-#define rsnd_ssiu_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_SSIU)
-bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod);
-
-/*
- * R-Car SRC
- */
-int rsnd_src_probe(struct rsnd_priv *priv);
-void rsnd_src_remove(struct rsnd_priv *priv);
-struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
-
-#define rsnd_src_get_in_rate(priv, io) rsnd_src_get_rate(priv, io, 1)
-#define rsnd_src_get_out_rate(priv, io) rsnd_src_get_rate(priv, io, 0)
-unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- int is_in);
-
-#define rsnd_src_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_SRC)
-#define rsnd_parse_connect_src(rdai, playback, capture) \
- rsnd_parse_connect_common(rdai, "src", rsnd_src_mod_get, \
- rsnd_src_of_node(rsnd_rdai_to_priv(rdai)), \
- playback, capture)
-
-/*
- * R-Car CTU
- */
-int rsnd_ctu_probe(struct rsnd_priv *priv);
-void rsnd_ctu_remove(struct rsnd_priv *priv);
-struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id);
-#define rsnd_ctu_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_CTU)
-#define rsnd_parse_connect_ctu(rdai, playback, capture) \
- rsnd_parse_connect_common(rdai, "ctu", rsnd_ctu_mod_get, \
- rsnd_ctu_of_node(rsnd_rdai_to_priv(rdai)), \
- playback, capture)
-
-/*
- * R-Car MIX
- */
-int rsnd_mix_probe(struct rsnd_priv *priv);
-void rsnd_mix_remove(struct rsnd_priv *priv);
-struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id);
-#define rsnd_mix_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_MIX)
-#define rsnd_parse_connect_mix(rdai, playback, capture) \
- rsnd_parse_connect_common(rdai, "mix", rsnd_mix_mod_get, \
- rsnd_mix_of_node(rsnd_rdai_to_priv(rdai)), \
- playback, capture)
-
-/*
- * R-Car DVC
- */
-int rsnd_dvc_probe(struct rsnd_priv *priv);
-void rsnd_dvc_remove(struct rsnd_priv *priv);
-struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id);
-#define rsnd_dvc_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_DVC)
-#define rsnd_parse_connect_dvc(rdai, playback, capture) \
- rsnd_parse_connect_common(rdai, "dvc", rsnd_dvc_mod_get, \
- rsnd_dvc_of_node(rsnd_rdai_to_priv(rdai)), \
- playback, capture)
-
-/*
- * R-Car CMD
- */
-int rsnd_cmd_probe(struct rsnd_priv *priv);
-void rsnd_cmd_remove(struct rsnd_priv *priv);
-int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id);
-
-void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type);
-#ifdef DEBUG
-#define rsnd_mod_confirm_ssi(mssi) rsnd_mod_make_sure(mssi, RSND_MOD_SSI)
-#define rsnd_mod_confirm_src(msrc) rsnd_mod_make_sure(msrc, RSND_MOD_SRC)
-#define rsnd_mod_confirm_dvc(mdvc) rsnd_mod_make_sure(mdvc, RSND_MOD_DVC)
-#else
-#define rsnd_mod_confirm_ssi(mssi)
-#define rsnd_mod_confirm_src(msrc)
-#define rsnd_mod_confirm_dvc(mdvc)
-#endif
-
-/*
- * If you don't need interrupt status debug message,
- * define RSND_DEBUG_NO_IRQ_STATUS as 1 on top of src.c/ssi.c
- *
- * #define RSND_DEBUG_NO_IRQ_STATUS 1
- */
-#define rsnd_print_irq_status(dev, param...) do { \
- if (!IS_BUILTIN(RSND_DEBUG_NO_IRQ_STATUS)) \
- dev_info(dev, param); \
-} while (0)
-
-#ifdef CONFIG_DEBUG_FS
-int rsnd_debugfs_probe(struct snd_soc_component *component);
-void rsnd_debugfs_reg_show(struct seq_file *m, phys_addr_t _addr,
- void __iomem *base, int offset, int size);
-void rsnd_debugfs_mod_reg_show(struct seq_file *m, struct rsnd_mod *mod,
- int reg_id, int offset, int size);
-
-#else
-#define rsnd_debugfs_probe NULL
-#endif
-
-#endif /* RSND_H */
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
deleted file mode 100644
index 3241a1bdc9ea..000000000000
--- a/sound/soc/sh/rcar/src.c
+++ /dev/null
@@ -1,736 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car SRC support
-//
-// Copyright (C) 2013 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-/*
- * You can use Synchronous Sampling Rate Convert (if no DVC)
- *
- * amixer set "SRC Out Rate" on
- * aplay xxx.wav &
- * amixer set "SRC Out Rate" 96000 // convert rate to 96000Hz
- * amixer set "SRC Out Rate" 22050 // convert rate to 22050Hz
- */
-
-/*
- * you can enable below define if you don't need
- * SSI interrupt status debug message when debugging
- * see rsnd_print_irq_status()
- *
- * #define RSND_DEBUG_NO_IRQ_STATUS 1
- */
-
-#include <linux/of_irq.h>
-#include "rsnd.h"
-
-#define SRC_NAME "src"
-
-/* SCU_SYSTEM_STATUS0/1 */
-#define OUF_SRC(id) ((1 << (id + 16)) | (1 << id))
-
-struct rsnd_src {
- struct rsnd_mod mod;
- struct rsnd_mod *dma;
- struct rsnd_kctrl_cfg_s sen; /* sync convert enable */
- struct rsnd_kctrl_cfg_s sync; /* sync convert */
- int irq;
-};
-
-#define RSND_SRC_NAME_SIZE 16
-
-#define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id)
-#define rsnd_src_nr(priv) ((priv)->src_nr)
-#define rsnd_src_sync_is_enabled(mod) (rsnd_mod_to_src(mod)->sen.val)
-
-#define rsnd_mod_to_src(_mod) \
- container_of((_mod), struct rsnd_src, mod)
-
-#define for_each_rsnd_src(pos, priv, i) \
- for ((i) = 0; \
- ((i) < rsnd_src_nr(priv)) && \
- ((pos) = (struct rsnd_src *)(priv)->src + i); \
- i++)
-
-
-/*
- * image of SRC (Sampling Rate Converter)
- *
- * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+
- * 48kHz <-> | SRC | <------> | SSI | <-----> | codec |
- * 44.1kHz <-> +-----+ +-----+ +-------+
- * ...
- *
- */
-
-static void rsnd_src_activation(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, SRC_SWRSR, 0);
- rsnd_mod_write(mod, SRC_SWRSR, 1);
-}
-
-static void rsnd_src_halt(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, SRC_SRCIR, 1);
- rsnd_mod_write(mod, SRC_SWRSR, 0);
-}
-
-static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- int is_play = rsnd_io_is_play(io);
-
- return rsnd_dma_request_channel(rsnd_src_of_node(priv),
- SRC_NAME, mod,
- is_play ? "rx" : "tx");
-}
-
-static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- u32 convert_rate;
-
- if (!runtime)
- return 0;
-
- if (!rsnd_src_sync_is_enabled(mod))
- return rsnd_io_converted_rate(io);
-
- convert_rate = src->sync.val;
-
- if (!convert_rate)
- convert_rate = rsnd_io_converted_rate(io);
-
- if (!convert_rate)
- convert_rate = runtime->rate;
-
- return convert_rate;
-}
-
-unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- int is_in)
-{
- struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- unsigned int rate = 0;
- int is_play = rsnd_io_is_play(io);
-
- /*
- * Playback
- * runtime_rate -> [SRC] -> convert_rate
- *
- * Capture
- * convert_rate -> [SRC] -> runtime_rate
- */
-
- if (is_play == is_in)
- return runtime->rate;
-
- /*
- * return convert rate if SRC is used,
- * otherwise, return runtime->rate as usual
- */
- if (src_mod)
- rate = rsnd_src_convert_rate(io, src_mod);
-
- if (!rate)
- rate = runtime->rate;
-
- return rate;
-}
-
-static const u32 bsdsr_table_pattern1[] = {
- 0x01800000, /* 6 - 1/6 */
- 0x01000000, /* 6 - 1/4 */
- 0x00c00000, /* 6 - 1/3 */
- 0x00800000, /* 6 - 1/2 */
- 0x00600000, /* 6 - 2/3 */
- 0x00400000, /* 6 - 1 */
-};
-
-static const u32 bsdsr_table_pattern2[] = {
- 0x02400000, /* 6 - 1/6 */
- 0x01800000, /* 6 - 1/4 */
- 0x01200000, /* 6 - 1/3 */
- 0x00c00000, /* 6 - 1/2 */
- 0x00900000, /* 6 - 2/3 */
- 0x00600000, /* 6 - 1 */
-};
-
-static const u32 bsisr_table[] = {
- 0x00100060, /* 6 - 1/6 */
- 0x00100040, /* 6 - 1/4 */
- 0x00100030, /* 6 - 1/3 */
- 0x00100020, /* 6 - 1/2 */
- 0x00100020, /* 6 - 2/3 */
- 0x00100020, /* 6 - 1 */
-};
-
-static const u32 chan288888[] = {
- 0x00000006, /* 1 to 2 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
-};
-
-static const u32 chan244888[] = {
- 0x00000006, /* 1 to 2 */
- 0x0000001e, /* 1 to 4 */
- 0x0000001e, /* 1 to 4 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
-};
-
-static const u32 chan222222[] = {
- 0x00000006, /* 1 to 2 */
- 0x00000006, /* 1 to 2 */
- 0x00000006, /* 1 to 2 */
- 0x00000006, /* 1 to 2 */
- 0x00000006, /* 1 to 2 */
- 0x00000006, /* 1 to 2 */
-};
-
-static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- int is_play = rsnd_io_is_play(io);
- int use_src = 0;
- u32 fin, fout;
- u32 ifscr, fsrate, adinr;
- u32 cr, route;
- u32 i_busif, o_busif, tmp;
- const u32 *bsdsr_table;
- const u32 *chptn;
- uint ratio;
- int chan;
- int idx;
-
- if (!runtime)
- return;
-
- fin = rsnd_src_get_in_rate(priv, io);
- fout = rsnd_src_get_out_rate(priv, io);
-
- chan = rsnd_runtime_channel_original(io);
-
- /* 6 - 1/6 are very enough ratio for SRC_BSDSR */
- if (fin == fout)
- ratio = 0;
- else if (fin > fout)
- ratio = 100 * fin / fout;
- else
- ratio = 100 * fout / fin;
-
- if (ratio > 600) {
- dev_err(dev, "FSO/FSI ratio error\n");
- return;
- }
-
- use_src = (fin != fout) | rsnd_src_sync_is_enabled(mod);
-
- /*
- * SRC_ADINR
- */
- adinr = rsnd_get_adinr_bit(mod, io) | chan;
-
- /*
- * SRC_IFSCR / SRC_IFSVR
- */
- ifscr = 0;
- fsrate = 0;
- if (use_src) {
- u64 n;
-
- ifscr = 1;
- n = (u64)0x0400000 * fin;
- do_div(n, fout);
- fsrate = n;
- }
-
- /*
- * SRC_SRCCR / SRC_ROUTE_MODE0
- */
- cr = 0x00011110;
- route = 0x0;
- if (use_src) {
- route = 0x1;
-
- if (rsnd_src_sync_is_enabled(mod)) {
- cr |= 0x1;
- route |= rsnd_io_is_play(io) ?
- (0x1 << 24) : (0x1 << 25);
- }
- }
-
- /*
- * SRC_BSDSR / SRC_BSISR
- *
- * see
- * Combination of Register Setting Related to
- * FSO/FSI Ratio and Channel, Latency
- */
- switch (rsnd_mod_id(mod)) {
- case 0:
- chptn = chan288888;
- bsdsr_table = bsdsr_table_pattern1;
- break;
- case 1:
- case 3:
- case 4:
- chptn = chan244888;
- bsdsr_table = bsdsr_table_pattern1;
- break;
- case 2:
- case 9:
- chptn = chan222222;
- bsdsr_table = bsdsr_table_pattern1;
- break;
- case 5:
- case 6:
- case 7:
- case 8:
- chptn = chan222222;
- bsdsr_table = bsdsr_table_pattern2;
- break;
- default:
- goto convert_rate_err;
- }
-
- /*
- * E3 need to overwrite
- */
- if (rsnd_is_e3(priv))
- switch (rsnd_mod_id(mod)) {
- case 0:
- case 4:
- chptn = chan222222;
- }
-
- for (idx = 0; idx < ARRAY_SIZE(chan222222); idx++)
- if (chptn[idx] & (1 << chan))
- break;
-
- if (chan > 8 ||
- idx >= ARRAY_SIZE(chan222222))
- goto convert_rate_err;
-
- /* BUSIF_MODE */
- tmp = rsnd_get_busif_shift(io, mod);
- i_busif = ( is_play ? tmp : 0) | 1;
- o_busif = (!is_play ? tmp : 0) | 1;
-
- rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
-
- rsnd_mod_write(mod, SRC_SRCIR, 1); /* initialize */
- rsnd_mod_write(mod, SRC_ADINR, adinr);
- rsnd_mod_write(mod, SRC_IFSCR, ifscr);
- rsnd_mod_write(mod, SRC_IFSVR, fsrate);
- rsnd_mod_write(mod, SRC_SRCCR, cr);
- rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]);
- rsnd_mod_write(mod, SRC_BSISR, bsisr_table[idx]);
- rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */
-
- rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif);
- rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif);
-
- rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
-
- rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
-
- return;
-
-convert_rate_err:
- dev_err(dev, "unknown BSDSR/BSDIR settings\n");
-}
-
-static int rsnd_src_irq(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv,
- int enable)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- u32 sys_int_val, int_val, sys_int_mask;
- int irq = src->irq;
- int id = rsnd_mod_id(mod);
-
- sys_int_val =
- sys_int_mask = OUF_SRC(id);
- int_val = 0x3300;
-
- /*
- * IRQ is not supported on non-DT
- * see
- * rsnd_src_probe_()
- */
- if ((irq <= 0) || !enable) {
- sys_int_val = 0;
- int_val = 0;
- }
-
- /*
- * WORKAROUND
- *
- * ignore over flow error when rsnd_src_sync_is_enabled()
- */
- if (rsnd_src_sync_is_enabled(mod))
- sys_int_val = sys_int_val & 0xffff;
-
- rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
- rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
- rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
-
- return 0;
-}
-
-static void rsnd_src_status_clear(struct rsnd_mod *mod)
-{
- u32 val = OUF_SRC(rsnd_mod_id(mod));
-
- rsnd_mod_write(mod, SCU_SYS_STATUS0, val);
- rsnd_mod_write(mod, SCU_SYS_STATUS1, val);
-}
-
-static bool rsnd_src_error_occurred(struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- u32 val0, val1;
- u32 status0, status1;
- bool ret = false;
-
- val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
-
- /*
- * WORKAROUND
- *
- * ignore over flow error when rsnd_src_sync_is_enabled()
- */
- if (rsnd_src_sync_is_enabled(mod))
- val0 = val0 & 0xffff;
-
- status0 = rsnd_mod_read(mod, SCU_SYS_STATUS0);
- status1 = rsnd_mod_read(mod, SCU_SYS_STATUS1);
- if ((status0 & val0) || (status1 & val1)) {
- rsnd_print_irq_status(dev, "%s err status : 0x%08x, 0x%08x\n",
- rsnd_mod_name(mod), status0, status1);
-
- ret = true;
- }
-
- return ret;
-}
-
-static int rsnd_src_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- u32 val;
-
- /*
- * WORKAROUND
- *
- * Enable SRC output if you want to use sync convert together with DVC
- */
- val = (rsnd_io_to_mod_dvc(io) && !rsnd_src_sync_is_enabled(mod)) ?
- 0x01 : 0x11;
-
- rsnd_mod_write(mod, SRC_CTRL, val);
-
- return 0;
-}
-
-static int rsnd_src_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_mod_write(mod, SRC_CTRL, 0);
-
- return 0;
-}
-
-static int rsnd_src_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- int ret;
-
- /* reset sync convert_rate */
- src->sync.val = 0;
-
- ret = rsnd_mod_power_on(mod);
- if (ret < 0)
- return ret;
-
- rsnd_src_activation(mod);
-
- rsnd_src_set_convert_rate(io, mod);
-
- rsnd_src_status_clear(mod);
-
- return 0;
-}
-
-static int rsnd_src_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
-
- rsnd_src_halt(mod);
-
- rsnd_mod_power_off(mod);
-
- /* reset sync convert_rate */
- src->sync.val = 0;
-
- return 0;
-}
-
-static void __rsnd_src_interrupt(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- bool stop = false;
-
- spin_lock(&priv->lock);
-
- /* ignore all cases if not working */
- if (!rsnd_io_is_working(io))
- goto rsnd_src_interrupt_out;
-
- if (rsnd_src_error_occurred(mod))
- stop = true;
-
- rsnd_src_status_clear(mod);
-rsnd_src_interrupt_out:
-
- spin_unlock(&priv->lock);
-
- if (stop)
- snd_pcm_stop_xrun(io->substream);
-}
-
-static irqreturn_t rsnd_src_interrupt(int irq, void *data)
-{
- struct rsnd_mod *mod = data;
-
- rsnd_mod_interrupt(mod, __rsnd_src_interrupt);
-
- return IRQ_HANDLED;
-}
-
-static int rsnd_src_probe_(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- int irq = src->irq;
- int ret;
-
- if (irq > 0) {
- /*
- * IRQ is not supported on non-DT
- * see
- * rsnd_src_irq()
- */
- ret = devm_request_irq(dev, irq,
- rsnd_src_interrupt,
- IRQF_SHARED,
- dev_name(dev), mod);
- if (ret)
- return ret;
- }
-
- ret = rsnd_dma_attach(io, mod, &src->dma);
-
- return ret;
-}
-
-static int rsnd_src_pcm_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- int ret;
-
- /*
- * enable SRC sync convert if possible
- */
-
- /*
- * It can't use SRC Synchronous convert
- * when Capture if it uses CMD
- */
- if (rsnd_io_to_mod_cmd(io) && !rsnd_io_is_play(io))
- return 0;
-
- /*
- * enable sync convert
- */
- ret = rsnd_kctrl_new_s(mod, io, rtd,
- rsnd_io_is_play(io) ?
- "SRC Out Rate Switch" :
- "SRC In Rate Switch",
- rsnd_kctrl_accept_anytime,
- rsnd_src_set_convert_rate,
- &src->sen, 1);
- if (ret < 0)
- return ret;
-
- ret = rsnd_kctrl_new_s(mod, io, rtd,
- rsnd_io_is_play(io) ?
- "SRC Out Rate" :
- "SRC In Rate",
- rsnd_kctrl_accept_runtime,
- rsnd_src_set_convert_rate,
- &src->sync, 192000);
-
- return ret;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_src_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- rsnd_mod_id(mod) * 0x20, 0x20);
- seq_puts(m, "\n");
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0x1c0, 0x20);
- seq_puts(m, "\n");
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0x200 + rsnd_mod_id(mod) * 0x40, 0x40);
-}
-#define DEBUG_INFO .debug_info = rsnd_src_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_src_ops = {
- .name = SRC_NAME,
- .dma_req = rsnd_src_dma_req,
- .probe = rsnd_src_probe_,
- .init = rsnd_src_init,
- .quit = rsnd_src_quit,
- .start = rsnd_src_start,
- .stop = rsnd_src_stop,
- .irq = rsnd_src_irq,
- .pcm_new = rsnd_src_pcm_new,
- .get_status = rsnd_mod_get_status,
- DEBUG_INFO
-};
-
-struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
- id = 0;
-
- return rsnd_mod_get(rsnd_src_get(priv, id));
-}
-
-int rsnd_src_probe(struct rsnd_priv *priv)
-{
- struct device_node *node;
- struct device_node *np;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_src *src;
- struct clk *clk;
- char name[RSND_SRC_NAME_SIZE];
- int i, nr, ret;
-
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
- node = rsnd_src_of_node(priv);
- if (!node)
- return 0; /* not used is not error */
-
- nr = rsnd_node_count(priv, node, SRC_NAME);
- if (!nr) {
- ret = -EINVAL;
- goto rsnd_src_probe_done;
- }
-
- src = devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL);
- if (!src) {
- ret = -ENOMEM;
- goto rsnd_src_probe_done;
- }
-
- priv->src_nr = nr;
- priv->src = src;
-
- i = 0;
- for_each_child_of_node(node, np) {
- if (!of_device_is_available(np))
- goto skip;
-
- i = rsnd_node_fixed_index(dev, np, SRC_NAME, i);
- if (i < 0) {
- ret = -EINVAL;
- of_node_put(np);
- goto rsnd_src_probe_done;
- }
-
- src = rsnd_src_get(priv, i);
-
- snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
- SRC_NAME, i);
-
- src->irq = irq_of_parse_and_map(np, 0);
- if (!src->irq) {
- ret = -EINVAL;
- of_node_put(np);
- goto rsnd_src_probe_done;
- }
-
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- of_node_put(np);
- goto rsnd_src_probe_done;
- }
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(src),
- &rsnd_src_ops, clk, RSND_MOD_SRC, i);
- if (ret) {
- of_node_put(np);
- goto rsnd_src_probe_done;
- }
-
-skip:
- i++;
- }
-
- ret = 0;
-
-rsnd_src_probe_done:
- of_node_put(node);
-
- return ret;
-}
-
-void rsnd_src_remove(struct rsnd_priv *priv)
-{
- struct rsnd_src *src;
- int i;
-
- for_each_rsnd_src(src, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(src));
- }
-}
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
deleted file mode 100644
index 0a46aa1975fa..000000000000
--- a/sound/soc/sh/rcar/ssi.c
+++ /dev/null
@@ -1,1260 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car SSIU/SSI support
-//
-// Copyright (C) 2013 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-//
-// Based on fsi.c
-// Kuninori Morimoto <morimoto.kuninori@renesas.com>
-
-/*
- * you can enable below define if you don't need
- * SSI interrupt status debug message when debugging
- * see rsnd_print_irq_status()
- *
- * #define RSND_DEBUG_NO_IRQ_STATUS 1
- */
-
-#include <sound/simple_card_utils.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/delay.h>
-#include "rsnd.h"
-#define RSND_SSI_NAME_SIZE 16
-
-/*
- * SSICR
- */
-#define FORCE (1u << 31) /* Fixed */
-#define DMEN (1u << 28) /* DMA Enable */
-#define UIEN (1u << 27) /* Underflow Interrupt Enable */
-#define OIEN (1u << 26) /* Overflow Interrupt Enable */
-#define IIEN (1u << 25) /* Idle Mode Interrupt Enable */
-#define DIEN (1u << 24) /* Data Interrupt Enable */
-#define CHNL_4 (1u << 22) /* Channels */
-#define CHNL_6 (2u << 22) /* Channels */
-#define CHNL_8 (3u << 22) /* Channels */
-#define DWL_MASK (7u << 19) /* Data Word Length mask */
-#define DWL_8 (0u << 19) /* Data Word Length */
-#define DWL_16 (1u << 19) /* Data Word Length */
-#define DWL_18 (2u << 19) /* Data Word Length */
-#define DWL_20 (3u << 19) /* Data Word Length */
-#define DWL_22 (4u << 19) /* Data Word Length */
-#define DWL_24 (5u << 19) /* Data Word Length */
-#define DWL_32 (6u << 19) /* Data Word Length */
-
-/*
- * System word length
- */
-#define SWL_16 (1 << 16) /* R/W System Word Length */
-#define SWL_24 (2 << 16) /* R/W System Word Length */
-#define SWL_32 (3 << 16) /* R/W System Word Length */
-
-#define SCKD (1 << 15) /* Serial Bit Clock Direction */
-#define SWSD (1 << 14) /* Serial WS Direction */
-#define SCKP (1 << 13) /* Serial Bit Clock Polarity */
-#define SWSP (1 << 12) /* Serial WS Polarity */
-#define SDTA (1 << 10) /* Serial Data Alignment */
-#define PDTA (1 << 9) /* Parallel Data Alignment */
-#define DEL (1 << 8) /* Serial Data Delay */
-#define CKDV(v) (v << 4) /* Serial Clock Division Ratio */
-#define TRMD (1 << 1) /* Transmit/Receive Mode Select */
-#define EN (1 << 0) /* SSI Module Enable */
-
-/*
- * SSISR
- */
-#define UIRQ (1 << 27) /* Underflow Error Interrupt Status */
-#define OIRQ (1 << 26) /* Overflow Error Interrupt Status */
-#define IIRQ (1 << 25) /* Idle Mode Interrupt Status */
-#define DIRQ (1 << 24) /* Data Interrupt Status Flag */
-
-/*
- * SSIWSR
- */
-#define CONT (1 << 8) /* WS Continue Function */
-#define WS_MODE (1 << 0) /* WS Mode */
-
-#define SSI_NAME "ssi"
-
-struct rsnd_ssi {
- struct rsnd_mod mod;
-
- u32 flags;
- u32 cr_own;
- u32 cr_clk;
- u32 cr_mode;
- u32 cr_en;
- u32 wsr;
- int chan;
- int rate;
- int irq;
- unsigned int usrcnt;
-
- /* for PIO */
- int byte_pos;
- int byte_per_period;
- int next_period_byte;
-};
-
-/* flags */
-#define RSND_SSI_CLK_PIN_SHARE (1 << 0)
-#define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */
-#define RSND_SSI_PROBED (1 << 2)
-
-#define for_each_rsnd_ssi(pos, priv, i) \
- for (i = 0; \
- (i < rsnd_ssi_nr(priv)) && \
- ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \
- i++)
-
-#define rsnd_ssi_get(priv, id) ((struct rsnd_ssi *)(priv->ssi) + id)
-#define rsnd_ssi_nr(priv) ((priv)->ssi_nr)
-#define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
-#define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io))
-#define rsnd_ssi_is_multi_secondary(mod, io) \
- (rsnd_ssi_multi_secondaries(io) & (1 << rsnd_mod_id(mod)))
-#define rsnd_ssi_is_run_mods(mod, io) \
- (rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod)))
-#define rsnd_ssi_can_output_clk(mod) (!__rsnd_ssi_is_pin_sharing(mod))
-
-int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
-{
- struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- int use_busif = 0;
-
- if (!rsnd_ssi_is_dma_mode(mod))
- return 0;
-
- if (!(rsnd_flags_has(ssi, RSND_SSI_NO_BUSIF)))
- use_busif = 1;
- if (rsnd_io_to_mod_src(io))
- use_busif = 1;
-
- return use_busif;
-}
-
-static void rsnd_ssi_status_clear(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, SSISR, 0);
-}
-
-static u32 rsnd_ssi_status_get(struct rsnd_mod *mod)
-{
- return rsnd_mod_read(mod, SSISR);
-}
-
-static void rsnd_ssi_status_check(struct rsnd_mod *mod,
- u32 bit)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- u32 status;
- int i;
-
- for (i = 0; i < 1024; i++) {
- status = rsnd_ssi_status_get(mod);
- if (status & bit)
- return;
-
- udelay(5);
- }
-
- dev_warn(dev, "%s status check failed\n", rsnd_mod_name(mod));
-}
-
-static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io)
-{
- static const enum rsnd_mod_type types[] = {
- RSND_MOD_SSIM1,
- RSND_MOD_SSIM2,
- RSND_MOD_SSIM3,
- };
- int i, mask;
-
- mask = 0;
- for (i = 0; i < ARRAY_SIZE(types); i++) {
- struct rsnd_mod *mod = rsnd_io_to_mod(io, types[i]);
-
- if (!mod)
- continue;
-
- mask |= 1 << rsnd_mod_id(mod);
- }
-
- return mask;
-}
-
-static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io)
-{
- struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
- u32 mods;
-
- mods = rsnd_ssi_multi_secondaries_runtime(io) |
- 1 << rsnd_mod_id(ssi_mod);
-
- if (ssi_parent_mod)
- mods |= 1 << rsnd_mod_id(ssi_parent_mod);
-
- return mods;
-}
-
-u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io)
-{
- if (rsnd_runtime_is_multi_ssi(io))
- return rsnd_ssi_multi_secondaries(io);
-
- return 0;
-}
-
-static u32 rsnd_rdai_width_to_swl(struct rsnd_dai *rdai)
-{
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
- int width = rsnd_rdai_width_get(rdai);
-
- switch (width) {
- case 32: return SWL_32;
- case 24: return SWL_24;
- case 16: return SWL_16;
- }
-
- dev_err(dev, "unsupported slot width value: %d\n", width);
- return 0;
-}
-
-unsigned int rsnd_ssi_clk_query(struct rsnd_dai *rdai,
- int param1, int param2, int *idx)
-{
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- static const int ssi_clk_mul_table[] = {
- 1, 2, 4, 8, 16, 6, 12,
- };
- int j, ret;
- unsigned int main_rate;
- int width = rsnd_rdai_width_get(rdai);
-
- for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) {
-
- /*
- * It will set SSIWSR.CONT here, but SSICR.CKDV = 000
- * with it is not allowed. (SSIWSR.WS_MODE with
- * SSICR.CKDV = 000 is not allowed either).
- * Skip it. See SSICR.CKDV
- */
- if (j == 0)
- continue;
-
- main_rate = width * param1 * param2 * ssi_clk_mul_table[j];
-
- ret = rsnd_adg_clk_query(priv, main_rate);
- if (ret < 0)
- continue;
-
- if (idx)
- *idx = j;
-
- return main_rate;
- }
-
- return 0;
-}
-
-static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- int chan = rsnd_runtime_channel_for_ssi(io);
- int idx, ret;
- unsigned int main_rate;
- unsigned int rate = rsnd_io_is_play(io) ?
- rsnd_src_get_out_rate(priv, io) :
- rsnd_src_get_in_rate(priv, io);
-
- if (!rsnd_rdai_is_clk_master(rdai))
- return 0;
-
- if (!rsnd_ssi_can_output_clk(mod))
- return 0;
-
- if (rsnd_ssi_is_multi_secondary(mod, io))
- return 0;
-
- if (rsnd_runtime_is_tdm_split(io))
- chan = rsnd_io_converted_chan(io);
-
- chan = rsnd_channel_normalization(chan);
-
- if (ssi->usrcnt > 0) {
- if (ssi->rate != rate) {
- dev_err(dev, "SSI parent/child should use same rate\n");
- return -EINVAL;
- }
-
- if (ssi->chan != chan) {
- dev_err(dev, "SSI parent/child should use same chan\n");
- return -EINVAL;
- }
-
- return 0;
- }
-
- ret = -EIO;
- main_rate = rsnd_ssi_clk_query(rdai, rate, chan, &idx);
- if (!main_rate)
- goto rate_err;
-
- ret = rsnd_adg_ssi_clk_try_start(mod, main_rate);
- if (ret < 0)
- goto rate_err;
-
- /*
- * SSI clock will be output contiguously
- * by below settings.
- * This means, rsnd_ssi_master_clk_start()
- * and rsnd_ssi_register_setup() are necessary
- * for SSI parent
- *
- * SSICR : FORCE, SCKD, SWSD
- * SSIWSR : CONT
- */
- ssi->cr_clk = FORCE | rsnd_rdai_width_to_swl(rdai) |
- SCKD | SWSD | CKDV(idx);
- ssi->wsr = CONT;
- ssi->rate = rate;
- ssi->chan = chan;
-
- dev_dbg(dev, "%s outputs %d chan %u Hz\n",
- rsnd_mod_name(mod), chan, rate);
-
- return 0;
-
-rate_err:
- dev_err(dev, "unsupported clock rate\n");
- return ret;
-}
-
-static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- if (!rsnd_rdai_is_clk_master(rdai))
- return;
-
- if (!rsnd_ssi_can_output_clk(mod))
- return;
-
- if (ssi->usrcnt > 1)
- return;
-
- ssi->cr_clk = 0;
- ssi->rate = 0;
- ssi->chan = 0;
-
- rsnd_adg_ssi_clk_stop(mod);
-}
-
-static void rsnd_ssi_config_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- u32 cr_own = ssi->cr_own;
- u32 cr_mode = ssi->cr_mode;
- u32 wsr = ssi->wsr;
- int width;
- int is_tdm, is_tdm_split;
-
- is_tdm = rsnd_runtime_is_tdm(io);
- is_tdm_split = rsnd_runtime_is_tdm_split(io);
-
- if (is_tdm)
- dev_dbg(dev, "TDM mode\n");
- if (is_tdm_split)
- dev_dbg(dev, "TDM Split mode\n");
-
- cr_own |= FORCE | rsnd_rdai_width_to_swl(rdai);
-
- if (rdai->bit_clk_inv)
- cr_own |= SCKP;
- if (rdai->frm_clk_inv && !is_tdm)
- cr_own |= SWSP;
- if (rdai->data_alignment)
- cr_own |= SDTA;
- if (rdai->sys_delay)
- cr_own |= DEL;
-
- /*
- * TDM Mode
- * see
- * rsnd_ssiu_init_gen2()
- */
- if (is_tdm || is_tdm_split) {
- wsr |= WS_MODE;
- cr_own |= CHNL_8;
- }
-
- /*
- * We shouldn't exchange SWSP after running.
- * This means, parent needs to care it.
- */
- if (rsnd_ssi_is_parent(mod, io))
- goto init_end;
-
- if (rsnd_io_is_play(io))
- cr_own |= TRMD;
-
- cr_own &= ~DWL_MASK;
- width = snd_pcm_format_width(runtime->format);
- if (is_tdm_split) {
- /*
- * The SWL and DWL bits in SSICR should be fixed at 32-bit
- * setting when TDM split mode.
- * see datasheet
- * Operation :: TDM Format Split Function (TDM Split Mode)
- */
- width = 32;
- }
-
- switch (width) {
- case 8:
- cr_own |= DWL_8;
- break;
- case 16:
- cr_own |= DWL_16;
- break;
- case 24:
- cr_own |= DWL_24;
- break;
- case 32:
- cr_own |= DWL_32;
- break;
- }
-
- if (rsnd_ssi_is_dma_mode(mod)) {
- cr_mode = UIEN | OIEN | /* over/under run */
- DMEN; /* DMA : enable DMA */
- } else {
- cr_mode = DIEN; /* PIO : enable Data interrupt */
- }
-
-init_end:
- ssi->cr_own = cr_own;
- ssi->cr_mode = cr_mode;
- ssi->wsr = wsr;
-}
-
-static void rsnd_ssi_register_setup(struct rsnd_mod *mod)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- rsnd_mod_write(mod, SSIWSR, ssi->wsr);
- rsnd_mod_write(mod, SSICR, ssi->cr_own |
- ssi->cr_clk |
- ssi->cr_mode |
- ssi->cr_en);
-}
-
-/*
- * SSI mod common functions
- */
-static int rsnd_ssi_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- int ret;
-
- if (!rsnd_ssi_is_run_mods(mod, io))
- return 0;
-
- ret = rsnd_ssi_master_clk_start(mod, io);
- if (ret < 0)
- return ret;
-
- ssi->usrcnt++;
-
- ret = rsnd_mod_power_on(mod);
- if (ret < 0)
- return ret;
-
- rsnd_ssi_config_init(mod, io);
-
- rsnd_ssi_register_setup(mod);
-
- /* clear error status */
- rsnd_ssi_status_clear(mod);
-
- return 0;
-}
-
-static int rsnd_ssi_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- if (!rsnd_ssi_is_run_mods(mod, io))
- return 0;
-
- if (!ssi->usrcnt) {
- dev_err(dev, "%s usrcnt error\n", rsnd_mod_name(mod));
- return -EIO;
- }
-
- rsnd_ssi_master_clk_stop(mod, io);
-
- rsnd_mod_power_off(mod);
-
- ssi->usrcnt--;
-
- if (!ssi->usrcnt) {
- ssi->cr_own = 0;
- ssi->cr_mode = 0;
- ssi->wsr = 0;
- }
-
- return 0;
-}
-
-static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- unsigned int fmt_width = snd_pcm_format_width(params_format(params));
-
- if (fmt_width > rdai->chan_width) {
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_err(dev, "invalid combination of slot-width and format-data-width\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int rsnd_ssi_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- if (!rsnd_ssi_is_run_mods(mod, io))
- return 0;
-
- /*
- * EN will be set via SSIU :: SSI_CONTROL
- * if Multi channel mode
- */
- if (rsnd_ssi_multi_secondaries_runtime(io))
- return 0;
-
- /*
- * EN is for data output.
- * SSI parent EN is not needed.
- */
- if (rsnd_ssi_is_parent(mod, io))
- return 0;
-
- ssi->cr_en = EN;
-
- rsnd_mod_write(mod, SSICR, ssi->cr_own |
- ssi->cr_clk |
- ssi->cr_mode |
- ssi->cr_en);
-
- return 0;
-}
-
-static int rsnd_ssi_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- u32 cr;
-
- if (!rsnd_ssi_is_run_mods(mod, io))
- return 0;
-
- if (rsnd_ssi_is_parent(mod, io))
- return 0;
-
- cr = ssi->cr_own |
- ssi->cr_clk;
-
- /*
- * disable all IRQ,
- * Playback: Wait all data was sent
- * Capture: It might not receave data. Do nothing
- */
- if (rsnd_io_is_play(io)) {
- rsnd_mod_write(mod, SSICR, cr | ssi->cr_en);
- rsnd_ssi_status_check(mod, DIRQ);
- }
-
- /* In multi-SSI mode, stop is performed by setting ssi0129 in
- * SSI_CONTROL to 0 (in rsnd_ssio_stop_gen2). Do nothing here.
- */
- if (rsnd_ssi_multi_secondaries_runtime(io))
- return 0;
-
- /*
- * disable SSI,
- * and, wait idle state
- */
- rsnd_mod_write(mod, SSICR, cr); /* disabled all */
- rsnd_ssi_status_check(mod, IIRQ);
-
- ssi->cr_en = 0;
-
- return 0;
-}
-
-static int rsnd_ssi_irq(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv,
- int enable)
-{
- u32 val = 0;
- int is_tdm, is_tdm_split;
- int id = rsnd_mod_id(mod);
-
- is_tdm = rsnd_runtime_is_tdm(io);
- is_tdm_split = rsnd_runtime_is_tdm_split(io);
-
- if (rsnd_is_gen1(priv))
- return 0;
-
- if (rsnd_ssi_is_parent(mod, io))
- return 0;
-
- if (!rsnd_ssi_is_run_mods(mod, io))
- return 0;
-
- if (enable)
- val = rsnd_ssi_is_dma_mode(mod) ? 0x0e000000 : 0x0f000000;
-
- if (is_tdm || is_tdm_split) {
- switch (id) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 9:
- val |= 0x0000ff00;
- break;
- }
- }
-
- rsnd_mod_write(mod, SSI_INT_ENABLE, val);
-
- return 0;
-}
-
-static bool rsnd_ssi_pio_interrupt(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io);
-static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- int is_dma = rsnd_ssi_is_dma_mode(mod);
- u32 status;
- bool elapsed = false;
- bool stop = false;
-
- spin_lock(&priv->lock);
-
- /* ignore all cases if not working */
- if (!rsnd_io_is_working(io))
- goto rsnd_ssi_interrupt_out;
-
- status = rsnd_ssi_status_get(mod);
-
- /* PIO only */
- if (!is_dma && (status & DIRQ))
- elapsed = rsnd_ssi_pio_interrupt(mod, io);
-
- /* DMA only */
- if (is_dma && (status & (UIRQ | OIRQ))) {
- rsnd_print_irq_status(dev, "%s err status : 0x%08x\n",
- rsnd_mod_name(mod), status);
-
- stop = true;
- }
-
- stop |= rsnd_ssiu_busif_err_status_clear(mod);
-
- rsnd_ssi_status_clear(mod);
-rsnd_ssi_interrupt_out:
- spin_unlock(&priv->lock);
-
- if (elapsed)
- rsnd_dai_period_elapsed(io);
-
- if (stop)
- snd_pcm_stop_xrun(io->substream);
-
-}
-
-static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
-{
- struct rsnd_mod *mod = data;
-
- rsnd_mod_interrupt(mod, __rsnd_ssi_interrupt);
-
- return IRQ_HANDLED;
-}
-
-static u32 *rsnd_ssi_get_status(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type)
-{
- /*
- * SSIP (= SSI parent) needs to be special, otherwise,
- * 2nd SSI might doesn't start. see also rsnd_mod_call()
- *
- * We can't include parent SSI status on SSI, because we don't know
- * how many SSI requests parent SSI. Thus, it is localed on "io" now.
- * ex) trouble case
- * Playback: SSI0
- * Capture : SSI1 (needs SSI0)
- *
- * 1) start Capture -> SSI0/SSI1 are started.
- * 2) start Playback -> SSI0 doesn't work, because it is already
- * marked as "started" on 1)
- *
- * OTOH, using each mod's status is good for MUX case.
- * It doesn't need to start in 2nd start
- * ex)
- * IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0
- * |
- * IO-1: SRC1 -> CTU2 -+
- *
- * 1) start IO-0 -> start SSI0
- * 2) start IO-1 -> SSI0 doesn't need to start, because it is
- * already started on 1)
- */
- if (type == RSND_MOD_SSIP)
- return &io->parent_ssi_status;
-
- return rsnd_mod_get_status(mod, io, type);
-}
-
-/*
- * SSI PIO
- */
-static void rsnd_ssi_parent_attach(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-
- if (!__rsnd_ssi_is_pin_sharing(mod))
- return;
-
- if (!rsnd_rdai_is_clk_master(rdai))
- return;
-
- if (rsnd_ssi_is_multi_secondary(mod, io))
- return;
-
- switch (rsnd_mod_id(mod)) {
- case 1:
- case 2:
- case 9:
- rsnd_dai_connect(rsnd_ssi_mod_get(priv, 0), io, RSND_MOD_SSIP);
- break;
- case 4:
- rsnd_dai_connect(rsnd_ssi_mod_get(priv, 3), io, RSND_MOD_SSIP);
- break;
- case 8:
- rsnd_dai_connect(rsnd_ssi_mod_get(priv, 7), io, RSND_MOD_SSIP);
- break;
- }
-}
-
-static int rsnd_ssi_pcm_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd)
-{
- /*
- * rsnd_rdai_is_clk_master() will be enabled after set_fmt,
- * and, pcm_new will be called after it.
- * This function reuse pcm_new at this point.
- */
- rsnd_ssi_parent_attach(mod, io);
-
- return 0;
-}
-
-static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- int ret = 0;
-
- /*
- * SSIP/SSIU/IRQ are not needed on
- * SSI Multi secondaries
- */
- if (rsnd_ssi_is_multi_secondary(mod, io))
- return 0;
-
- /*
- * It can't judge ssi parent at this point
- * see rsnd_ssi_pcm_new()
- */
-
- /*
- * SSI might be called again as PIO fallback
- * It is easy to manual handling for IRQ request/free
- *
- * OTOH, this function might be called many times if platform is
- * using MIX. It needs xxx_attach() many times on xxx_probe().
- * Because of it, we can't control .probe/.remove calling count by
- * mod->status.
- * But it don't need to call request_irq() many times.
- * Let's control it by RSND_SSI_PROBED flag.
- */
- if (!rsnd_flags_has(ssi, RSND_SSI_PROBED)) {
- ret = request_irq(ssi->irq,
- rsnd_ssi_interrupt,
- IRQF_SHARED,
- dev_name(dev), mod);
-
- rsnd_flags_set(ssi, RSND_SSI_PROBED);
- }
-
- return ret;
-}
-
-static int rsnd_ssi_common_remove(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- struct rsnd_mod *pure_ssi_mod = rsnd_io_to_mod_ssi(io);
-
- /* Do nothing if non SSI (= SSI parent, multi SSI) mod */
- if (pure_ssi_mod != mod)
- return 0;
-
- /* PIO will request IRQ again */
- if (rsnd_flags_has(ssi, RSND_SSI_PROBED)) {
- free_irq(ssi->irq, mod);
-
- rsnd_flags_del(ssi, RSND_SSI_PROBED);
- }
-
- return 0;
-}
-
-/*
- * SSI PIO functions
- */
-static bool rsnd_ssi_pio_interrupt(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- u32 *buf = (u32 *)(runtime->dma_area + ssi->byte_pos);
- int shift = 0;
- int byte_pos;
- bool elapsed = false;
-
- if (snd_pcm_format_width(runtime->format) == 24)
- shift = 8;
-
- /*
- * 8/16/32 data can be assesse to TDR/RDR register
- * directly as 32bit data
- * see rsnd_ssi_init()
- */
- if (rsnd_io_is_play(io))
- rsnd_mod_write(mod, SSITDR, (*buf) << shift);
- else
- *buf = (rsnd_mod_read(mod, SSIRDR) >> shift);
-
- byte_pos = ssi->byte_pos + sizeof(*buf);
-
- if (byte_pos >= ssi->next_period_byte) {
- int period_pos = byte_pos / ssi->byte_per_period;
-
- if (period_pos >= runtime->periods) {
- byte_pos = 0;
- period_pos = 0;
- }
-
- ssi->next_period_byte = (period_pos + 1) * ssi->byte_per_period;
-
- elapsed = true;
- }
-
- WRITE_ONCE(ssi->byte_pos, byte_pos);
-
- return elapsed;
-}
-
-static int rsnd_ssi_pio_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- if (!rsnd_ssi_is_parent(mod, io)) {
- ssi->byte_pos = 0;
- ssi->byte_per_period = runtime->period_size *
- runtime->channels *
- samples_to_bytes(runtime, 1);
- ssi->next_period_byte = ssi->byte_per_period;
- }
-
- return rsnd_ssi_init(mod, io, priv);
-}
-
-static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- snd_pcm_uframes_t *pointer)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
-
- *pointer = bytes_to_frames(runtime, READ_ONCE(ssi->byte_pos));
-
- return 0;
-}
-
-static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
- .name = SSI_NAME,
- .probe = rsnd_ssi_common_probe,
- .remove = rsnd_ssi_common_remove,
- .init = rsnd_ssi_pio_init,
- .quit = rsnd_ssi_quit,
- .start = rsnd_ssi_start,
- .stop = rsnd_ssi_stop,
- .irq = rsnd_ssi_irq,
- .pointer = rsnd_ssi_pio_pointer,
- .pcm_new = rsnd_ssi_pcm_new,
- .hw_params = rsnd_ssi_hw_params,
- .get_status = rsnd_ssi_get_status,
-};
-
-static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- /*
- * SSIP/SSIU/IRQ/DMA are not needed on
- * SSI Multi secondaries
- */
- if (rsnd_ssi_is_multi_secondary(mod, io))
- return 0;
-
- ret = rsnd_ssi_common_probe(mod, io, priv);
- if (ret)
- return ret;
-
- /* SSI probe might be called many times in MUX multi path */
- ret = rsnd_dma_attach(io, mod, &io->dma);
-
- return ret;
-}
-
-static int rsnd_ssi_fallback(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
-
- /*
- * fallback to PIO
- *
- * SSI .probe might be called again.
- * see
- * rsnd_rdai_continuance_probe()
- */
- mod->ops = &rsnd_ssi_pio_ops;
-
- dev_info(dev, "%s fallback to PIO mode\n", rsnd_mod_name(mod));
-
- return 0;
-}
-
-static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- int is_play = rsnd_io_is_play(io);
- char *name;
-
- /*
- * It should use "rcar_sound,ssiu" on DT.
- * But, we need to keep compatibility for old version.
- *
- * If it has "rcar_sound.ssiu", it will be used.
- * If not, "rcar_sound.ssi" will be used.
- * see
- * rsnd_ssiu_dma_req()
- * rsnd_dma_of_path()
- */
-
- if (rsnd_ssi_use_busif(io))
- name = is_play ? "rxu" : "txu";
- else
- name = is_play ? "rx" : "tx";
-
- return rsnd_dma_request_channel(rsnd_ssi_of_node(priv),
- SSI_NAME, mod, name);
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_ssi_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- seq_printf(m, "clock: %s\n", rsnd_rdai_is_clk_master(rdai) ?
- "provider" : "consumer");
- seq_printf(m, "bit_clk_inv: %d\n", rdai->bit_clk_inv);
- seq_printf(m, "frm_clk_inv: %d\n", rdai->frm_clk_inv);
- seq_printf(m, "pin share: %d\n", __rsnd_ssi_is_pin_sharing(mod));
- seq_printf(m, "can out clk: %d\n", rsnd_ssi_can_output_clk(mod));
- seq_printf(m, "multi secondary: %d\n", rsnd_ssi_is_multi_secondary(mod, io));
- seq_printf(m, "tdm: %d, %d\n", rsnd_runtime_is_tdm(io),
- rsnd_runtime_is_tdm_split(io));
- seq_printf(m, "chan: %d\n", ssi->chan);
- seq_printf(m, "user: %d\n", ssi->usrcnt);
-
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SSI,
- rsnd_mod_id(mod) * 0x40, 0x40);
-}
-#define DEBUG_INFO .debug_info = rsnd_ssi_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
- .name = SSI_NAME,
- .dma_req = rsnd_ssi_dma_req,
- .probe = rsnd_ssi_dma_probe,
- .remove = rsnd_ssi_common_remove,
- .init = rsnd_ssi_init,
- .quit = rsnd_ssi_quit,
- .start = rsnd_ssi_start,
- .stop = rsnd_ssi_stop,
- .irq = rsnd_ssi_irq,
- .pcm_new = rsnd_ssi_pcm_new,
- .fallback = rsnd_ssi_fallback,
- .hw_params = rsnd_ssi_hw_params,
- .get_status = rsnd_ssi_get_status,
- DEBUG_INFO
-};
-
-int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod)
-{
- return mod->ops == &rsnd_ssi_dma_ops;
-}
-
-/*
- * ssi mod function
- */
-static void rsnd_ssi_connect(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- static const enum rsnd_mod_type types[] = {
- RSND_MOD_SSI,
- RSND_MOD_SSIM1,
- RSND_MOD_SSIM2,
- RSND_MOD_SSIM3,
- };
- enum rsnd_mod_type type;
- int i;
-
- /* try SSI -> SSIM1 -> SSIM2 -> SSIM3 */
- for (i = 0; i < ARRAY_SIZE(types); i++) {
- type = types[i];
- if (!rsnd_io_to_mod(io, type)) {
- rsnd_dai_connect(mod, io, type);
- rsnd_rdai_channels_set(rdai, (i + 1) * 2);
- rsnd_rdai_ssi_lane_set(rdai, (i + 1));
- return;
- }
- }
-}
-
-void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
- struct device_node *playback,
- struct device_node *capture)
-{
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *node;
- struct device_node *np;
- int i;
-
- node = rsnd_ssi_of_node(priv);
- if (!node)
- return;
-
- i = 0;
- for_each_child_of_node(node, np) {
- struct rsnd_mod *mod;
-
- i = rsnd_node_fixed_index(dev, np, SSI_NAME, i);
- if (i < 0) {
- of_node_put(np);
- break;
- }
-
- mod = rsnd_ssi_mod_get(priv, i);
-
- if (np == playback)
- rsnd_ssi_connect(mod, &rdai->playback);
- if (np == capture)
- rsnd_ssi_connect(mod, &rdai->capture);
- i++;
- }
-
- of_node_put(node);
-}
-
-struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
- id = 0;
-
- return rsnd_mod_get(rsnd_ssi_get(priv, id));
-}
-
-int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
-{
- if (!mod)
- return 0;
-
- return !!(rsnd_flags_has(rsnd_mod_to_ssi(mod), RSND_SSI_CLK_PIN_SHARE));
-}
-
-int rsnd_ssi_probe(struct rsnd_priv *priv)
-{
- struct device_node *node;
- struct device_node *np;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mod_ops *ops;
- struct clk *clk;
- struct rsnd_ssi *ssi;
- char name[RSND_SSI_NAME_SIZE];
- int i, nr, ret;
-
- node = rsnd_ssi_of_node(priv);
- if (!node)
- return -EINVAL;
-
- nr = rsnd_node_count(priv, node, SSI_NAME);
- if (!nr) {
- ret = -EINVAL;
- goto rsnd_ssi_probe_done;
- }
-
- ssi = devm_kcalloc(dev, nr, sizeof(*ssi), GFP_KERNEL);
- if (!ssi) {
- ret = -ENOMEM;
- goto rsnd_ssi_probe_done;
- }
-
- priv->ssi = ssi;
- priv->ssi_nr = nr;
-
- i = 0;
- for_each_child_of_node(node, np) {
- if (!of_device_is_available(np))
- goto skip;
-
- i = rsnd_node_fixed_index(dev, np, SSI_NAME, i);
- if (i < 0) {
- ret = -EINVAL;
- of_node_put(np);
- goto rsnd_ssi_probe_done;
- }
-
- ssi = rsnd_ssi_get(priv, i);
-
- snprintf(name, RSND_SSI_NAME_SIZE, "%s.%d",
- SSI_NAME, i);
-
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- of_node_put(np);
- goto rsnd_ssi_probe_done;
- }
-
- if (of_property_read_bool(np, "shared-pin"))
- rsnd_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE);
-
- if (of_property_read_bool(np, "no-busif"))
- rsnd_flags_set(ssi, RSND_SSI_NO_BUSIF);
-
- ssi->irq = irq_of_parse_and_map(np, 0);
- if (!ssi->irq) {
- ret = -EINVAL;
- of_node_put(np);
- goto rsnd_ssi_probe_done;
- }
-
- if (of_property_read_bool(np, "pio-transfer"))
- ops = &rsnd_ssi_pio_ops;
- else
- ops = &rsnd_ssi_dma_ops;
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk,
- RSND_MOD_SSI, i);
- if (ret) {
- of_node_put(np);
- goto rsnd_ssi_probe_done;
- }
-skip:
- i++;
- }
-
- ret = 0;
-
-rsnd_ssi_probe_done:
- of_node_put(node);
-
- return ret;
-}
-
-void rsnd_ssi_remove(struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi;
- int i;
-
- for_each_rsnd_ssi(ssi, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(ssi));
- }
-}
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c
deleted file mode 100644
index 17bd8cc86dd0..000000000000
--- a/sound/soc/sh/rcar/ssiu.c
+++ /dev/null
@@ -1,609 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car SSIU support
-//
-// Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-#include "rsnd.h"
-
-#define SSIU_NAME "ssiu"
-
-struct rsnd_ssiu {
- struct rsnd_mod mod;
- u32 busif_status[8]; /* for BUSIF0 - BUSIF7 */
- unsigned int usrcnt;
- int id;
- int id_sub;
-};
-
-/* SSI_MODE */
-#define TDM_EXT (1 << 0)
-#define TDM_SPLIT (1 << 8)
-
-#define rsnd_ssiu_nr(priv) ((priv)->ssiu_nr)
-#define rsnd_mod_to_ssiu(_mod) container_of((_mod), struct rsnd_ssiu, mod)
-#define for_each_rsnd_ssiu(pos, priv, i) \
- for (i = 0; \
- (i < rsnd_ssiu_nr(priv)) && \
- ((pos) = ((struct rsnd_ssiu *)(priv)->ssiu + i)); \
- i++)
-
-/*
- * SSI Gen2 Gen3 Gen4
- * 0 BUSIF0-3 BUSIF0-7 BUSIF0-7
- * 1 BUSIF0-3 BUSIF0-7
- * 2 BUSIF0-3 BUSIF0-7
- * 3 BUSIF0 BUSIF0-7
- * 4 BUSIF0 BUSIF0-7
- * 5 BUSIF0 BUSIF0
- * 6 BUSIF0 BUSIF0
- * 7 BUSIF0 BUSIF0
- * 8 BUSIF0 BUSIF0
- * 9 BUSIF0-3 BUSIF0-7
- * total 22 52 8
- */
-static const int gen2_id[] = { 0, 4, 8, 12, 13, 14, 15, 16, 17, 18 };
-static const int gen3_id[] = { 0, 8, 16, 24, 32, 40, 41, 42, 43, 44 };
-static const int gen4_id[] = { 0 };
-
-/* enable busif buffer over/under run interrupt. */
-#define rsnd_ssiu_busif_err_irq_enable(mod) rsnd_ssiu_busif_err_irq_ctrl(mod, 1)
-#define rsnd_ssiu_busif_err_irq_disable(mod) rsnd_ssiu_busif_err_irq_ctrl(mod, 0)
-static void rsnd_ssiu_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable)
-{
- int id = rsnd_mod_id(mod);
- int shift, offset;
- int i;
-
- switch (id) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- shift = id;
- offset = 0;
- break;
- case 9:
- shift = 1;
- offset = 1;
- break;
- default:
- return;
- }
-
- for (i = 0; i < 4; i++) {
- enum rsnd_reg reg = SSI_SYS_INT_ENABLE((i * 2) + offset);
- u32 val = 0xf << (shift * 4);
- u32 sys_int_enable = rsnd_mod_read(mod, reg);
-
- if (enable)
- sys_int_enable |= val;
- else
- sys_int_enable &= ~val;
- rsnd_mod_write(mod, reg, sys_int_enable);
- }
-}
-
-bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod)
-{
- bool error = false;
- int id = rsnd_mod_id(mod);
- int shift, offset;
- int i;
-
- switch (id) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- shift = id;
- offset = 0;
- break;
- case 9:
- shift = 1;
- offset = 1;
- break;
- default:
- goto out;
- }
-
- for (i = 0; i < 4; i++) {
- u32 reg = SSI_SYS_STATUS(i * 2) + offset;
- u32 status = rsnd_mod_read(mod, reg);
- u32 val = 0xf << (shift * 4);
-
- status &= val;
- if (status) {
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- rsnd_print_irq_status(dev, "%s err status : 0x%08x\n",
- rsnd_mod_name(mod), status);
- error = true;
- }
- rsnd_mod_write(mod, reg, val);
- }
-out:
- return error;
-}
-
-static u32 *rsnd_ssiu_get_status(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type)
-{
- struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
- int busif = rsnd_mod_id_sub(mod);
-
- return &ssiu->busif_status[busif];
-}
-
-static int rsnd_ssiu_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- u32 ssis = rsnd_ssi_multi_secondaries_runtime(io);
- int use_busif = rsnd_ssi_use_busif(io);
- int id = rsnd_mod_id(mod);
- int is_clk_master = rsnd_rdai_is_clk_master(rdai);
- u32 val1, val2;
-
- /* clear status */
- rsnd_ssiu_busif_err_status_clear(mod);
-
- /* Gen4 doesn't have SSI_MODE */
- if (rsnd_is_gen4(priv))
- goto ssi_mode_setting_end;
-
- /*
- * SSI_MODE0
- */
- rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
-
- /*
- * SSI_MODE1 / SSI_MODE2
- *
- * FIXME
- * sharing/multi with SSI0 are mainly supported
- */
- val1 = rsnd_mod_read(mod, SSI_MODE1);
- val2 = rsnd_mod_read(mod, SSI_MODE2);
- if (rsnd_ssi_is_pin_sharing(io)) {
-
- ssis |= (1 << id);
-
- } else if (ssis) {
- /*
- * Multi SSI
- *
- * set synchronized bit here
- */
-
- /* SSI4 is synchronized with SSI3 */
- if (ssis & (1 << 4))
- val1 |= (1 << 20);
- /* SSI012 are synchronized */
- if (ssis == 0x0006)
- val1 |= (1 << 4);
- /* SSI0129 are synchronized */
- if (ssis == 0x0206)
- val2 |= (1 << 4);
- }
-
- /* SSI1 is sharing pin with SSI0 */
- if (ssis & (1 << 1))
- val1 |= is_clk_master ? 0x2 : 0x1;
-
- /* SSI2 is sharing pin with SSI0 */
- if (ssis & (1 << 2))
- val1 |= is_clk_master ? 0x2 << 2 :
- 0x1 << 2;
- /* SSI4 is sharing pin with SSI3 */
- if (ssis & (1 << 4))
- val1 |= is_clk_master ? 0x2 << 16 :
- 0x1 << 16;
- /* SSI9 is sharing pin with SSI0 */
- if (ssis & (1 << 9))
- val2 |= is_clk_master ? 0x2 : 0x1;
-
- rsnd_mod_bset(mod, SSI_MODE1, 0x0013001f, val1);
- rsnd_mod_bset(mod, SSI_MODE2, 0x00000017, val2);
-
-ssi_mode_setting_end:
- /*
- * Enable busif buffer over/under run interrupt.
- * It will be handled from ssi.c
- * see
- * __rsnd_ssi_interrupt()
- */
- rsnd_ssiu_busif_err_irq_enable(mod);
-
- return 0;
-}
-
-static int rsnd_ssiu_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- /* disable busif buffer over/under run interrupt. */
- rsnd_ssiu_busif_err_irq_disable(mod);
-
- return 0;
-}
-
-static struct rsnd_mod_ops rsnd_ssiu_ops_gen1 = {
- .name = SSIU_NAME,
- .init = rsnd_ssiu_init,
- .quit = rsnd_ssiu_quit,
- .get_status = rsnd_ssiu_get_status,
-};
-
-static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
- u32 has_hdmi0 = rsnd_flags_has(io, RSND_STREAM_HDMI0);
- u32 has_hdmi1 = rsnd_flags_has(io, RSND_STREAM_HDMI1);
- int ret;
- u32 mode = 0;
-
- ret = rsnd_ssiu_init(mod, io, priv);
- if (ret < 0)
- return ret;
-
- ssiu->usrcnt++;
-
- /*
- * TDM Extend/Split Mode
- * see
- * rsnd_ssi_config_init()
- */
- if (rsnd_runtime_is_tdm(io))
- mode = TDM_EXT;
- else if (rsnd_runtime_is_tdm_split(io))
- mode = TDM_SPLIT;
-
- rsnd_mod_write(mod, SSI_MODE, mode);
-
- if (rsnd_ssi_use_busif(io)) {
- int id = rsnd_mod_id(mod);
- int busif = rsnd_mod_id_sub(mod);
- enum rsnd_reg adinr_reg, mode_reg, dalign_reg;
-
- if ((id == 9) && (busif >= 4)) {
- adinr_reg = SSI9_BUSIF_ADINR(busif);
- mode_reg = SSI9_BUSIF_MODE(busif);
- dalign_reg = SSI9_BUSIF_DALIGN(busif);
- } else {
- adinr_reg = SSI_BUSIF_ADINR(busif);
- mode_reg = SSI_BUSIF_MODE(busif);
- dalign_reg = SSI_BUSIF_DALIGN(busif);
- }
-
- rsnd_mod_write(mod, adinr_reg,
- rsnd_get_adinr_bit(mod, io) |
- (rsnd_io_is_play(io) ?
- rsnd_runtime_channel_after_ctu(io) :
- rsnd_runtime_channel_original(io)));
- rsnd_mod_write(mod, mode_reg,
- rsnd_get_busif_shift(io, mod) | 1);
- rsnd_mod_write(mod, dalign_reg,
- rsnd_get_dalign(mod, io));
- }
-
- if (has_hdmi0 || has_hdmi1) {
- enum rsnd_mod_type rsnd_ssi_array[] = {
- RSND_MOD_SSIM1,
- RSND_MOD_SSIM2,
- RSND_MOD_SSIM3,
- };
- struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_mod *pos;
- u32 val;
- int i;
-
- i = rsnd_mod_id(ssi_mod);
-
- /* output all same SSI as default */
- val = i << 16 |
- i << 20 |
- i << 24 |
- i << 28 |
- i;
-
- for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) {
- int shift = (i * 4) + 20;
-
- val = (val & ~(0xF << shift)) |
- rsnd_mod_id(pos) << shift;
- }
-
- if (has_hdmi0)
- rsnd_mod_write(mod, HDMI0_SEL, val);
- if (has_hdmi1)
- rsnd_mod_write(mod, HDMI1_SEL, val);
- }
-
- return 0;
-}
-
-static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int busif = rsnd_mod_id_sub(mod);
-
- if (!rsnd_ssi_use_busif(io))
- return 0;
-
- rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4));
-
- if (rsnd_ssi_multi_secondaries_runtime(io))
- rsnd_mod_write(mod, SSI_CONTROL, 0x1);
-
- return 0;
-}
-
-static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
- int busif = rsnd_mod_id_sub(mod);
-
- if (!rsnd_ssi_use_busif(io))
- return 0;
-
- rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 0);
-
- if (--ssiu->usrcnt)
- return 0;
-
- if (rsnd_ssi_multi_secondaries_runtime(io))
- rsnd_mod_write(mod, SSI_CONTROL, 0);
-
- return 0;
-}
-
-static int rsnd_ssiu_id(struct rsnd_mod *mod)
-{
- struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
-
- /* see rsnd_ssiu_probe() */
- return ssiu->id;
-}
-
-static int rsnd_ssiu_id_sub(struct rsnd_mod *mod)
-{
- struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
-
- /* see rsnd_ssiu_probe() */
- return ssiu->id_sub;
-}
-
-static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- int is_play = rsnd_io_is_play(io);
- char *name;
-
- /*
- * It should use "rcar_sound,ssiu" on DT.
- * But, we need to keep compatibility for old version.
- *
- * If it has "rcar_sound.ssiu", it will be used.
- * If not, "rcar_sound.ssi" will be used.
- * see
- * rsnd_ssi_dma_req()
- * rsnd_dma_of_path()
- */
-
- name = is_play ? "rx" : "tx";
-
- return rsnd_dma_request_channel(rsnd_ssiu_of_node(priv),
- SSIU_NAME, mod, name);
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_ssiu_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SSIU,
- rsnd_mod_id(mod) * 0x80, 0x80);
-}
-#define DEBUG_INFO .debug_info = rsnd_ssiu_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = {
- .name = SSIU_NAME,
- .dma_req = rsnd_ssiu_dma_req,
- .init = rsnd_ssiu_init_gen2,
- .quit = rsnd_ssiu_quit,
- .start = rsnd_ssiu_start_gen2,
- .stop = rsnd_ssiu_stop_gen2,
- .get_status = rsnd_ssiu_get_status,
- DEBUG_INFO
-};
-
-static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_ssiu_nr(priv)))
- id = 0;
-
- return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id);
-}
-
-static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_ssiu *ssiu;
- int is_dma_mode;
- int i;
-
- if (!ssi_mod)
- return;
-
- is_dma_mode = rsnd_ssi_is_dma_mode(ssi_mod);
-
- /* select BUSIF0 */
- for_each_rsnd_ssiu(ssiu, priv, i) {
- struct rsnd_mod *mod = rsnd_mod_get(ssiu);
-
- if (is_dma_mode &&
- (rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) &&
- (rsnd_mod_id_sub(mod) == 0)) {
- rsnd_dai_connect(mod, io, mod->type);
- return;
- }
- }
-}
-
-void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
- struct device_node *playback,
- struct device_node *capture)
-{
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *node = rsnd_ssiu_of_node(priv);
- struct rsnd_dai_stream *io_p = &rdai->playback;
- struct rsnd_dai_stream *io_c = &rdai->capture;
-
- /* use rcar_sound,ssiu if exist */
- if (node) {
- struct device_node *np;
- int i = 0;
-
- for_each_child_of_node(node, np) {
- struct rsnd_mod *mod;
-
- i = rsnd_node_fixed_index(dev, np, SSIU_NAME, i);
- if (i < 0) {
- of_node_put(np);
- break;
- }
-
- mod = rsnd_ssiu_mod_get(priv, i);
-
- if (np == playback)
- rsnd_dai_connect(mod, io_p, mod->type);
- if (np == capture)
- rsnd_dai_connect(mod, io_c, mod->type);
- i++;
- }
-
- of_node_put(node);
- }
-
- /* Keep DT compatibility */
- if (!rsnd_io_to_mod_ssiu(io_p))
- rsnd_parse_connect_ssiu_compatible(priv, io_p);
- if (!rsnd_io_to_mod_ssiu(io_c))
- rsnd_parse_connect_ssiu_compatible(priv, io_c);
-}
-
-int rsnd_ssiu_probe(struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *node;
- struct rsnd_ssiu *ssiu;
- struct rsnd_mod_ops *ops;
- const int *list = NULL;
- int i, nr;
-
- /*
- * Keep DT compatibility.
- * if it has "rcar_sound,ssiu", use it.
- * if not, use "rcar_sound,ssi"
- * see
- * rsnd_ssiu_bufsif_to_id()
- */
- node = rsnd_ssiu_of_node(priv);
- if (node)
- nr = rsnd_node_count(priv, node, SSIU_NAME);
- else
- nr = priv->ssi_nr;
-
- if (!nr)
- return -EINVAL;
-
- ssiu = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL);
- if (!ssiu)
- return -ENOMEM;
-
- priv->ssiu = ssiu;
- priv->ssiu_nr = nr;
-
- if (rsnd_is_gen1(priv))
- ops = &rsnd_ssiu_ops_gen1;
- else
- ops = &rsnd_ssiu_ops_gen2;
-
- /* Keep compatibility */
- nr = 0;
- if ((node) &&
- (ops == &rsnd_ssiu_ops_gen2)) {
- ops->id = rsnd_ssiu_id;
- ops->id_sub = rsnd_ssiu_id_sub;
-
- if (rsnd_is_gen2(priv)) {
- list = gen2_id;
- nr = ARRAY_SIZE(gen2_id);
- } else if (rsnd_is_gen3(priv)) {
- list = gen3_id;
- nr = ARRAY_SIZE(gen3_id);
- } else if (rsnd_is_gen4(priv)) {
- list = gen4_id;
- nr = ARRAY_SIZE(gen4_id);
- } else {
- dev_err(dev, "unknown SSIU\n");
- return -ENODEV;
- }
- }
-
- for_each_rsnd_ssiu(ssiu, priv, i) {
- int ret;
-
- if (node) {
- int j;
-
- /*
- * see
- * rsnd_ssiu_get_id()
- * rsnd_ssiu_get_id_sub()
- */
- for (j = 0; j < nr; j++) {
- if (list[j] > i)
- break;
- ssiu->id = j;
- ssiu->id_sub = i - list[ssiu->id];
- }
- } else {
- ssiu->id = i;
- }
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu),
- ops, NULL, RSND_MOD_SSIU, i);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-void rsnd_ssiu_remove(struct rsnd_priv *priv)
-{
- struct rsnd_ssiu *ssiu;
- int i;
-
- for_each_rsnd_ssiu(ssiu, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(ssiu));
- }
-}