|
@@ -61,32 +61,36 @@
|
|
|
#define SSI_NAME "ssi"
|
|
|
|
|
|
struct rsnd_ssi {
|
|
|
- struct rsnd_ssi_platform_info *info; /* rcar_snd.h */
|
|
|
struct rsnd_ssi *parent;
|
|
|
struct rsnd_mod mod;
|
|
|
struct rsnd_mod *dma;
|
|
|
|
|
|
+ u32 flags;
|
|
|
u32 cr_own;
|
|
|
u32 cr_clk;
|
|
|
u32 cr_mode;
|
|
|
int chan;
|
|
|
int rate;
|
|
|
int err;
|
|
|
+ int irq;
|
|
|
unsigned int usrcnt;
|
|
|
};
|
|
|
|
|
|
+/* flags */
|
|
|
+#define RSND_SSI_CLK_PIN_SHARE (1 << 0)
|
|
|
+#define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */
|
|
|
+
|
|
|
#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_to_dma(mod) ((ssi)->dma)
|
|
|
#define rsnd_ssi_nr(priv) ((priv)->ssi_nr)
|
|
|
#define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
|
|
|
-#define rsnd_ssi_pio_available(ssi) ((ssi)->info->irq > 0)
|
|
|
-#define rsnd_ssi_mode_flags(p) ((p)->info->flags)
|
|
|
-#define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
|
|
|
+#define rsnd_ssi_mode_flags(p) ((p)->flags)
|
|
|
#define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io))
|
|
|
|
|
|
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
|
|
@@ -587,7 +591,7 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
- ret = devm_request_irq(dev, ssi->info->irq,
|
|
|
+ ret = devm_request_irq(dev, ssi->irq,
|
|
|
rsnd_ssi_interrupt,
|
|
|
IRQF_SHARED,
|
|
|
dev_name(dev), mod);
|
|
@@ -610,7 +614,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
|
|
|
struct rsnd_priv *priv)
|
|
|
{
|
|
|
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
|
|
|
- int dma_id = ssi->info->dma_id;
|
|
|
+ int dma_id = 0; /* not needed */
|
|
|
int ret;
|
|
|
|
|
|
ret = rsnd_ssi_common_probe(mod, io, priv);
|
|
@@ -630,7 +634,7 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
|
|
|
{
|
|
|
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
|
|
|
struct device *dev = rsnd_priv_to_dev(priv);
|
|
|
- int irq = ssi->info->irq;
|
|
|
+ int irq = ssi->irq;
|
|
|
|
|
|
/* PIO will request IRQ again */
|
|
|
devm_free_irq(dev, irq, mod);
|
|
@@ -709,7 +713,7 @@ 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((struct rsnd_ssi *)(priv->ssi) + id);
|
|
|
+ return rsnd_mod_get(rsnd_ssi_get(priv, id));
|
|
|
}
|
|
|
|
|
|
int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
|
|
@@ -719,73 +723,12 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
|
|
|
return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE);
|
|
|
}
|
|
|
|
|
|
-static void rsnd_of_parse_ssi(struct platform_device *pdev,
|
|
|
- const struct rsnd_of_data *of_data,
|
|
|
- struct rsnd_priv *priv)
|
|
|
-{
|
|
|
- struct device_node *node;
|
|
|
- struct device_node *np;
|
|
|
- struct rsnd_ssi_platform_info *ssi_info;
|
|
|
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
|
|
|
- struct device *dev = &pdev->dev;
|
|
|
- int nr, i;
|
|
|
-
|
|
|
- node = rsnd_ssi_of_node(priv);
|
|
|
- if (!node)
|
|
|
- return;
|
|
|
-
|
|
|
- nr = of_get_child_count(node);
|
|
|
- if (!nr)
|
|
|
- goto rsnd_of_parse_ssi_end;
|
|
|
-
|
|
|
- ssi_info = devm_kzalloc(dev,
|
|
|
- sizeof(struct rsnd_ssi_platform_info) * nr,
|
|
|
- GFP_KERNEL);
|
|
|
- if (!ssi_info) {
|
|
|
- dev_err(dev, "ssi info allocation error\n");
|
|
|
- goto rsnd_of_parse_ssi_end;
|
|
|
- }
|
|
|
-
|
|
|
- info->ssi_info = ssi_info;
|
|
|
- info->ssi_info_nr = nr;
|
|
|
-
|
|
|
- i = -1;
|
|
|
- for_each_child_of_node(node, np) {
|
|
|
- i++;
|
|
|
-
|
|
|
- ssi_info = info->ssi_info + i;
|
|
|
-
|
|
|
- /*
|
|
|
- * pin settings
|
|
|
- */
|
|
|
- if (of_get_property(np, "shared-pin", NULL))
|
|
|
- ssi_info->flags |= RSND_SSI_CLK_PIN_SHARE;
|
|
|
-
|
|
|
- /*
|
|
|
- * irq
|
|
|
- */
|
|
|
- ssi_info->irq = irq_of_parse_and_map(np, 0);
|
|
|
-
|
|
|
- /*
|
|
|
- * DMA
|
|
|
- */
|
|
|
- ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ?
|
|
|
- 0 : 1;
|
|
|
-
|
|
|
- if (of_get_property(np, "no-busif", NULL))
|
|
|
- ssi_info->flags |= RSND_SSI_NO_BUSIF;
|
|
|
- }
|
|
|
-
|
|
|
-rsnd_of_parse_ssi_end:
|
|
|
- of_node_put(node);
|
|
|
-}
|
|
|
-
|
|
|
int rsnd_ssi_probe(struct platform_device *pdev,
|
|
|
const struct rsnd_of_data *of_data,
|
|
|
struct rsnd_priv *priv)
|
|
|
{
|
|
|
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
|
|
|
- struct rsnd_ssi_platform_info *pinfo;
|
|
|
+ struct device_node *node;
|
|
|
+ struct device_node *np;
|
|
|
struct device *dev = rsnd_priv_to_dev(priv);
|
|
|
struct rsnd_mod_ops *ops;
|
|
|
struct clk *clk;
|
|
@@ -793,44 +736,70 @@ int rsnd_ssi_probe(struct platform_device *pdev,
|
|
|
char name[RSND_SSI_NAME_SIZE];
|
|
|
int i, nr, ret;
|
|
|
|
|
|
- rsnd_of_parse_ssi(pdev, of_data, priv);
|
|
|
+ node = rsnd_ssi_of_node(priv);
|
|
|
+ if (!node)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ nr = of_get_child_count(node);
|
|
|
+ if (!nr) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto rsnd_ssi_probe_done;
|
|
|
+ }
|
|
|
|
|
|
- /*
|
|
|
- * init SSI
|
|
|
- */
|
|
|
- nr = info->ssi_info_nr;
|
|
|
ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL);
|
|
|
- if (!ssi)
|
|
|
- return -ENOMEM;
|
|
|
+ if (!ssi) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto rsnd_ssi_probe_done;
|
|
|
+ }
|
|
|
|
|
|
priv->ssi = ssi;
|
|
|
priv->ssi_nr = nr;
|
|
|
|
|
|
- for_each_rsnd_ssi(ssi, priv, i) {
|
|
|
- pinfo = &info->ssi_info[i];
|
|
|
+ i = 0;
|
|
|
+ for_each_child_of_node(node, np) {
|
|
|
+ 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))
|
|
|
- return PTR_ERR(clk);
|
|
|
+ if (IS_ERR(clk)) {
|
|
|
+ ret = PTR_ERR(clk);
|
|
|
+ goto rsnd_ssi_probe_done;
|
|
|
+ }
|
|
|
|
|
|
- ssi->info = pinfo;
|
|
|
+ if (of_get_property(np, "shared-pin", NULL))
|
|
|
+ ssi->flags |= RSND_SSI_CLK_PIN_SHARE;
|
|
|
+
|
|
|
+ if (of_get_property(np, "no-busif", NULL))
|
|
|
+ ssi->flags |= RSND_SSI_NO_BUSIF;
|
|
|
+
|
|
|
+ ssi->irq = irq_of_parse_and_map(np, 0);
|
|
|
+ if (!ssi->irq) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto rsnd_ssi_probe_done;
|
|
|
+ }
|
|
|
|
|
|
ops = &rsnd_ssi_non_ops;
|
|
|
- if (pinfo->dma_id > 0)
|
|
|
- ops = &rsnd_ssi_dma_ops;
|
|
|
- else if (rsnd_ssi_pio_available(ssi))
|
|
|
+ if (of_get_property(np, "pio-transfer", NULL))
|
|
|
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)
|
|
|
- return ret;
|
|
|
+ goto rsnd_ssi_probe_done;
|
|
|
+
|
|
|
+ i++;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ ret = 0;
|
|
|
+
|
|
|
+rsnd_ssi_probe_done:
|
|
|
+ of_node_put(node);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
void rsnd_ssi_remove(struct platform_device *pdev,
|