static int rsnd_src_probe_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_src *src = rsnd_mod_to_src(mod); struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); struct device *dev = rsnd_priv_to_dev(priv); int ret; int is_play; if (info->dai_info) is_play = rsnd_info_is_playback(priv, src); else is_play = rsnd_ssi_is_play(ssi); ret = rsnd_dma_init(priv, rsnd_mod_to_dma(mod), is_play, src->info->dma_id); if (ret < 0) dev_err(dev, "SRC DMA failed\n"); return ret; }
static void rsnd_of_parse_src(struct platform_device *pdev, const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct device_node *src_node; struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_src_platform_info *src_info; struct device *dev = &pdev->dev; int nr; if (!of_data) return; src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); if (!src_node) return; nr = of_get_child_count(src_node); if (!nr) return; src_info = devm_kzalloc(dev, sizeof(struct rsnd_src_platform_info) * nr, GFP_KERNEL); if (!src_info) { dev_err(dev, "src info allocation error\n"); return; } info->src_info = src_info; info->src_info_nr = nr; }
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct device *dev = rsnd_priv_to_dev(priv); int dma_id = ssi->info->dma_id; int is_play; int ret; if (info->dai_info) is_play = rsnd_info_is_playback(priv, ssi); else is_play = rsnd_ssi_is_play(&ssi->mod); ret = rsnd_dma_init( priv, rsnd_mod_to_dma(mod), is_play, dma_id); if (ret < 0) dev_err(dev, "SSI DMA failed\n"); return ret; }
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; if (!of_data) return; 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; }
int rsnd_src_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 device *dev = rsnd_priv_to_dev(priv); struct rsnd_src *src; struct rsnd_mod_ops *ops; struct clk *clk; char name[RSND_SRC_NAME_SIZE]; int i, nr; rsnd_of_parse_src(pdev, of_data, priv); /* * init SRC */ nr = info->src_info_nr; if (!nr) return 0; src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); if (!src) { dev_err(dev, "SRC allocate failed\n"); return -ENOMEM; } priv->src_nr = nr; priv->src = src; for_each_rsnd_src(src, priv, i) { snprintf(name, RSND_SRC_NAME_SIZE, "src.%d", i); clk = devm_clk_get(dev, name); if (IS_ERR(clk)) { snprintf(name, RSND_SRC_NAME_SIZE, "scu.%d", i); clk = devm_clk_get(dev, name); } if (IS_ERR(clk)) return PTR_ERR(clk); src->info = &info->src_info[i]; src->clk = clk; ops = &rsnd_src_non_ops; if (rsnd_src_hpbif_is_enable(src)) { if (rsnd_is_gen1(priv)) ops = &rsnd_src_gen1_ops; if (rsnd_is_gen2(priv)) ops = &rsnd_src_gen2_ops; } rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i); dev_dbg(dev, "SRC%d probed\n", i); }
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 *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; rsnd_of_parse_ssi(pdev, of_data, priv); /* * init SSI */ nr = info->ssi_info_nr; ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL); if (!ssi) { dev_err(dev, "SSI allocate failed\n"); return -ENOMEM; } priv->ssi = ssi; priv->ssi_nr = nr; for_each_rsnd_ssi(ssi, priv, i) { pinfo = &info->ssi_info[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); ssi->info = pinfo; ops = &rsnd_ssi_non_ops; if (pinfo->dma_id > 0) ops = &rsnd_ssi_dma_ops; else if (rsnd_ssi_pio_available(ssi)) ops = &rsnd_ssi_pio_ops; ret = rsnd_mod_init(&ssi->mod, ops, clk, RSND_MOD_SSI, i); if (ret) return ret; rsnd_ssi_parent_clk_setup(priv, ssi); }
/* * Gen1/Gen2 common functions */ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); struct rcar_snd_info *info = rsnd_priv_to_info(priv); int ssi_id = rsnd_mod_id(ssi_mod); int has_src = 0; /* * SSI_MODE0 */ if (info->dai_info) { has_src = !!src_mod; } else { struct rsnd_src *src = rsnd_mod_to_src(src_mod); has_src = rsnd_src_hpbif_is_enable(src); } rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), has_src ? 0 : (1 << ssi_id)); /* * SSI_MODE1 */ if (rsnd_ssi_is_pin_sharing(ssi_mod)) { int shift = -1; switch (ssi_id) { case 1: shift = 0; break; case 2: shift = 2; break; case 4: shift = 16; break; } if (shift >= 0) rsnd_mod_bset(ssi_mod, SSI_MODE1, 0x3 << shift, rsnd_dai_is_clk_master(rdai) ? 0x2 << shift : 0x1 << shift); } return 0; }
static void rsnd_of_parse_dai(struct platform_device *pdev, const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct device_node *dai_node, *dai_np; struct device_node *ssi_node, *ssi_np; struct device_node *src_node, *src_np; struct device_node *dvc_node, *dvc_np; struct device_node *playback, *capture; struct rsnd_dai_platform_info *dai_info; struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct device *dev = &pdev->dev; int nr, i; int dai_i, ssi_i, src_i, dvc_i; if (!of_data) return; dai_node = of_get_child_by_name(dev->of_node, "rcar_sound,dai"); if (!dai_node) return; nr = of_get_child_count(dai_node); if (!nr) return; dai_info = devm_kzalloc(dev, sizeof(struct rsnd_dai_platform_info) * nr, GFP_KERNEL); if (!dai_info) { dev_err(dev, "dai info allocation error\n"); return; } info->dai_info_nr = nr; info->dai_info = dai_info; ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); #define mod_parse(name) \ if (name##_node) { \ struct rsnd_##name##_platform_info *name##_info; \ \ name##_i = 0; \ for_each_child_of_node(name##_node, name##_np) { \ name##_info = info->name##_info + name##_i; \ \ if (name##_np == playback) \ dai_info->playback.name = name##_info; \ if (name##_np == capture) \ dai_info->capture.name = name##_info; \ \ name##_i++; \ } \ } /* * parse all dai */ dai_i = 0; for_each_child_of_node(dai_node, dai_np) { dai_info = info->dai_info + dai_i; for (i = 0;; i++) { playback = of_parse_phandle(dai_np, "playback", i); capture = of_parse_phandle(dai_np, "capture", i); if (!playback && !capture) break; mod_parse(ssi); mod_parse(src); mod_parse(dvc); of_node_put(playback); of_node_put(capture); } dai_i++; }