-/*
- * 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>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
+// 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
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)
{
int io_i;
rdai = rsnd_rdai_get(priv, dai_i);
- drv = priv->daidrv + dai_i;
+ drv = rsnd_daidrv_get(priv, dai_i);
io_playback = &rdai->playback;
io_capture = &rdai->capture;
of_node_put(capture);
}
+ if (rsnd_ssi_is_pin_sharing(io_capture) ||
+ rsnd_ssi_is_pin_sharing(io_playback)) {
+ /* should have symmetric_rates if pin sharing */
+ drv->symmetric_rates = 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" : " -- ");
if (!nr)
return -EINVAL;
- rdrv = devm_kzalloc(dev, sizeof(*rdrv) * nr, GFP_KERNEL);
- rdai = devm_kzalloc(dev, sizeof(*rdai) * nr, GFP_KERNEL);
+ rdrv = devm_kcalloc(dev, nr, sizeof(*rdrv), GFP_KERNEL);
+ rdai = devm_kcalloc(dev, nr, sizeof(*rdai), GFP_KERNEL);
if (!rdrv || !rdai)
return -ENOMEM;
};
module_platform_driver(rsnd_driver);
-MODULE_LICENSE("GPL");
+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");
-/*
- * 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>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
+// 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
#define CHNL_4 (1 << 22) /* Channels */
#define CHNL_6 (2 << 22) /* Channels */
#define CHNL_8 (3 << 22) /* Channels */
+ #define DWL_MASK (7 << 19) /* Data Word Length mask */
#define DWL_8 (0 << 19) /* Data Word Length */
#define DWL_16 (1 << 19) /* Data Word Length */
#define DWL_18 (2 << 19) /* Data Word Length */
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- u32 cr_own;
- u32 cr_mode;
- u32 wsr;
+ u32 cr_own = ssi->cr_own;
+ u32 cr_mode = ssi->cr_mode;
+ u32 wsr = ssi->wsr;
int is_tdm;
- if (rsnd_ssi_is_parent(mod, io))
- return;
-
is_tdm = rsnd_runtime_is_ssi_tdm(io);
/*
* always use 32bit system word.
* see also rsnd_ssi_master_clk_enable()
*/
- cr_own = FORCE | SWL_32;
+ cr_own |= FORCE | SWL_32;
if (rdai->bit_clk_inv)
cr_own |= SCKP;
cr_own |= SDTA;
if (rdai->sys_delay)
cr_own |= DEL;
+
+ /*
+ * 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;
switch (snd_pcm_format_width(runtime->format)) {
case 16:
cr_own |= DWL_16;
wsr |= WS_MODE;
cr_own |= CHNL_8;
}
-
+ init_end:
ssi->cr_own = cr_own;
ssi->cr_mode = cr_mode;
ssi->wsr = wsr;
return -EIO;
}
- if (!rsnd_ssi_is_parent(mod, io))
- ssi->cr_own = 0;
-
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;
}
int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+ if (!mod)
+ return 0;
- return !!(rsnd_flags_has(ssi, RSND_SSI_CLK_PIN_SHARE));
+ return !!(rsnd_flags_has(rsnd_mod_to_ssi(mod), RSND_SSI_CLK_PIN_SHARE));
}
static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io,
goto rsnd_ssi_probe_done;
}
- ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL);
+ ssi = devm_kcalloc(dev, nr, sizeof(*ssi), GFP_KERNEL);
if (!ssi) {
ret = -ENOMEM;
goto rsnd_ssi_probe_done;
list_for_each(it, widgets)
size++;
- *list = kzalloc(sizeof(**list) + size * sizeof(*w), GFP_KERNEL);
+ *list = kzalloc(struct_size(*list, widgets, size), GFP_KERNEL);
if (*list == NULL)
return -ENOMEM;
continue;
if (w->num_kcontrols) {
- w->kcontrols = kzalloc(w->num_kcontrols *
+ w->kcontrols = kcalloc(w->num_kcontrols,
sizeof(struct snd_kcontrol *),
GFP_KERNEL);
if (!w->kcontrols) {
continue;
}
+ /* let users know there is no DAI to link */
+ if (!dai_w->priv) {
+ dev_dbg(card->dev, "dai widget %s has no DAI\n",
+ dai_w->name);
+ continue;
+ }
+
dai = dai_w->priv;
/* ...find all widgets with the same stream and link them */